wok view plop/stuff/bootloader.S @ rev 24954

*/stuff/bootloader.S: add CHK_DOS_INT19
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Apr 23 15:28:40 2022 +0000 (2022-04-23)
parents d1f31f5f6401
children 50e835d951d8
line source
1 // Image/zImage & tiny bzImage linux kernel boot sector, (C) SliTaz, GPL2.
3 SYSSEG = 0x1000
4 setup_sects = 497
5 syssize = 500
6 cmd_line_ptr = 0x228
8 .text
9 .code16
10 .org 0
11 .globl _start
12 _start:
14 #define CODESZ 512 /* patched by installer */
16 // Default kernel format is 386 Image/zImage
17 //#define BZIMAGE 0x207 /* setup version ; for bzImage < 512 Kb only */
18 //#define ELKS /* 8086/286 linux port */
20 /* some extra features */
21 #define EXE_SUPPORT real mode dos .exe file support +208/264
22 #define CMDLINE dos kernel cmdline support +45
23 #define BUGGY_CMDLINE verify cmdline length +2
24 #define VCPI VCPI 4.0 support (386+) +109
25 #define SHUTDOWNDOS shutdown DOS services +29
26 #define CHK_DOS_INT19 do not trace bios +12/13
28 /* some contraints to reduce the code size */
29 //#define FLOPPY_1440K_ONLY 1.44M floppies support only -26
30 //#define FLOPPY_HAS_2_SIDES hardcoded heads count to 2 -15
31 //#define NO_CMDLINE_SHRINK remove heading spaces ? -6-21
32 //#define NO_CMDLINE_FILE remove @cmdline file support ? -21
33 //#define NO_DOTS show progression dots ? -5
34 #ifndef BZIMAGE
35 #define TINY_ZIMAGE system < 64Kb ? -11
36 #define NO_MINSETUP default setup (dos only) ? -4
37 //#define NO_CURSOR_DEFINITION -8
38 #endif
40 #ifdef ELKS
41 .arch i8086
42 INITSEG = 0x0100
43 SETUPSEG = 0x0120
44 #define ONLY8086
45 #undef BZIMAGE
46 #undef VCPI
47 #else
48 INITSEG = 0x9000
49 SETUPSEG = 0x9020
50 #endif
52 .macro shlclw cnt,obj
53 #ifdef ONLY8086
54 movb \cnt,%cl
55 shlw %cl,\obj
56 #else
57 shlw \cnt,\obj
58 #endif
59 .endm
61 .macro shrclw cnt,obj
62 #ifdef ONLY8086
63 movb \cnt,%cl
64 shrw %cl,\obj
65 #else
66 shrw \cnt,\obj
67 #endif
68 .endm
70 #ifdef EXE_SUPPORT
71 #define EXEADRS(x) (x+0xE0)
72 #define FLAT20(x) (x+16*INITSEG)
74 .macro trace_int19
75 #ifdef ONLY8086
76 xorw %si, %si
77 movw %si, %ds
78 # ifdef CHK_DOS_INT19
79 cmpb $0xF0, 4*0x19+3(%si)
80 jne stepit
81 popaw
82 pushw %es
83 movw $movesys, %si
84 pushw %si
85 retf
86 stepit:
87 # endif
88 pushw 4+2(%si)
89 pushw 4(%si)
90 movw $step19, 4(%si)
91 movw $INITSEG, 4+2(%si)
92 #else
93 pushl $4
94 popw %si
95 popw %ds
96 # ifdef CHK_DOS_INT19
97 cmpb $0xF0, 4*0x19+3-4(%si)
98 jne stepit
99 popaw
100 pushw %es
101 pushw $movesys
102 retf
103 stepit:
104 # endif
105 pushl (%si)
106 movl $step19+(INITSEG<<16), (%si)
107 #endif
108 pushfw
109 popw %ax
110 incb %ah # set TF
111 pushw %ax
112 popfw
113 #ifdef ONLY8086
114 ljmp *4*0x19(%si)
115 #else
116 ljmp *4*0x19-4(%si)
117 #endif
118 .endm
120 stacktop = 0x9E00 # in 0x8000 .. 0xA000
121 decw %bp // Magic number: MZ
122 popw %dx
123 jmp start // Bytes on last page of file
124 .word (CODESZ+511)/512 // Pages in file INSTALLER
125 .word 0 // Relocations
126 .word (end_header-_start)/16 // Size of header in paragraphs
127 .word 4096 // Minimum extra paragraphs needed
128 .word -1 // Maximum extra paragraphs needed
129 .word (CODESZ+15)/16 // Initial (relative) SS value INSTALLER
130 .word stacktop // Initial SP value
131 .word 0 // Checksum INSTALLER?
132 .word EXEADRS(comstart) // Initial IP value
133 .word 0xFFF0 // Initial (relative) CS value
134 // .word 0x001C // File address of relocation table
135 // .word 0,0,0 // Overlay number
136 #else
137 #undef VCPI
138 #endif
139 start:
140 xorw %ax, %ax # %ax = 0
141 zeroed = 12 # zeroed registers
142 movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
143 stacktop = 0x9E00 # in 0x8000 .. 0xA000 (+zeroed+12)
144 #ifdef ONLY8086
145 movw $INITSEG, %bx
146 #else
147 pushw $INITSEG
148 #endif
149 end_header:
150 cld # assume nothing
151 #if defined(BZIMAGE) && BZIMAGE >= 0x202
152 popw %es # %es contain INITSEG
153 movw %es, %di
154 #else
155 # cmdline offset at 0x22
156 movw $stacktop, %di # stacktop is an arbitrary value >=
157 # length of bootsect + length of
158 # setup + room for stack;
159 # 12 is disk parm size.
160 # ifdef ONLY8086
161 pushw %bx
162 # endif
163 popw %es # %es contain INITSEG
164 #endif
165 pushw %es
166 popw %ss # %es = %ss = INITSEG
167 movw %di, %sp # put stack at INITSEG:stacktop-...
168 #ifdef EXE_SUPPORT
169 cwd # force %dx = 0 (floppy only)
170 #endif
172 # Many BIOS's default disk parameter tables will not recognize
173 # multi-sector reads beyond the maximum sector number specified
174 # in the default diskette parameter tables - this may mean 7
175 # sectors in some cases.
176 #
177 # Since single sector reads are slow and out of the question,
178 # we must take care of this by creating new parameter tables
179 # (for the first disk) in RAM. We can set the maximum sector
180 # count to 36 - the most we will encounter on an ED 2.88.
181 #
182 # High doesn't hurt. Low does. Let's use the max: 63
184 rep # don't worry about cld
185 stosw # already done above
186 popw %bx # offset = 0
187 popw %ds # %ds = 0
189 movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0)
190 incw %ax
192 ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address
193 pushw %es
194 pushw %di
195 movb $6, %cl # copy 12 bytes
196 rep # don't worry about cld
197 movsw # already done above
198 movw %cx, %ds # %ds = 0
199 #ifdef ONLY8086
200 popw 0x78(%bx) # update parameter table address
201 popw 0x78+2(%bx)
202 #else
203 popl 0x78(%bx) # update parameter table address
204 #endif
205 pushw %ss
206 popw %ds # now %ds = %es = %ss = INITSEG
207 movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
209 xchg %ax, %di # sector count
210 popw %ax # limits = 0
211 incw %cx # cylinder 0, sector 1, clear Z
212 call read_first_sectors # read setup
214 # This routine loads the system at address LOADSEG, making sure
215 # no 64kB boundaries are crossed. We try to load it as fast as
216 # possible, loading whole tracks whenever we can.
218 movw syssize, %di
219 decw %di
220 shrclw $9-4, %di
221 incw %di
222 movw $SYSSEG, %cx
223 #ifdef BZIMAGE
224 push %cx
225 #endif
226 call read_sectorsCX
228 # This procedure turns off the floppy drive motor, so
229 # that we enter the kernel in a known state, and
230 # don't have to worry about it later.
232 kill_motor:
233 xchgw %ax, %di # reset FDC (%di < 128)
234 int $0x13
236 # After that (everything loaded), we jump to the setup-routine
237 # loaded directly after the bootblock:
238 # Segments are as follows: %ds = %ss = INITSEG
240 #ifdef BZIMAGE
241 popw %bx
242 popw %si // SYSSEG:0
243 movesys: // %bx = DS, %si
244 movw $16, %ax
245 mulw %bx
246 addw %si, %ax
247 adcw $0x9300, %dx // %dx:%ax src flat address
248 movw $9, %cx
249 zero1:
250 pushw $0 // 2E..1E
251 loop zero1
252 //pushl $0x93100000 // 1A: dest
253 pushw $0x9310
254 pushw %cx
255 pushw $-1 // 18
256 pushw %cx // 16
257 pushw %dx // src
258 pushw %ax
259 pushw $-1 // 10
260 movb $8, %cl
261 movw %cx, %bx // will move 8*64 = 512Kb
262 zero2:
263 pushw $0 // 0E..00
264 loop zero2
265 movw %sp, %si
266 pushw %ss
267 popw %es
268 pushw %es
269 popw %ds
270 syslp:
271 movb $0x80, %ch
272 movb $0x87, %ah
273 int $0x15
274 incb 0x14(%si)
275 incb 0x1C(%si)
276 decw %bx
277 jne syslp
278 #endif
279 jmp_setup:
280 cli
281 ljmp $SETUPSEG, $0
283 #ifdef EXE_SUPPORT
284 #ifdef SHUTDOWNDOS
285 doiret:
286 iret
287 step19:
288 pushw %si
289 pushw %ds
290 movw %sp, %si
291 ldsw %ss:4(%si), %si
292 cmpw $0x19CD, (%si)
293 popw %ds
294 popw %si
295 jne doiret
296 xorw %si, %si
297 movw %si, %ds
298 pushw %cs
299 popw %ss
300 movw $stacktop-4-16, %sp
301 #ifdef ONLY8086
302 popw 4(%si)
303 popw 4+2(%si)
304 popw %bp
305 popw %di
306 popw %si
307 popw %dx
308 popw %cx
309 popw %bx
310 popw %ax
311 #else
312 popl 4(%si)
313 popaw
314 #endif
315 #ifdef BZIMAGE
316 jmp movesys
317 #endif
318 #endif
319 #ifndef BZIMAGE
320 movesys: // %ax = SYSSEG, %bx = DS, %si
321 shrclw $4, %si
322 addw %si, %bx
323 #ifdef TINY_ZIMAGE
324 movw $0xFFFF, %cx
325 xorw %si, %si
326 xorw %di, %di
327 cmpw %ax, %bx
328 jnc forward
329 decw %si
330 decw %di
331 std
332 forward:
333 movw %ax, %es
334 movw %bx, %ds
335 rep
336 movsb
337 cld
338 #else
339 subw %ax, %bx
340 jnc forward
341 //movw $0x8FFF, %ax
342 movb $0x90, %ah
343 forward:
344 movw %ax, %es
345 movw %ax, %di
346 addw %bx, %di
347 movw %di, %ds
348 sbbw %di, %di // %di = 0 : -1
349 cmc // C = 1 : 0
350 adcw %di, %ax
351 xorw %si, %si
352 xorw %di, %di
353 movb $0x10, %cl
354 cmpb %cl, %ah // move 512k
355 rep
356 movsb
357 jns forward
358 #endif
359 #ifndef NO_CURSOR_DEFINITION
360 movb $1, %ah
361 movb $0, %bh
362 movb $0x20, %ch // 0x2000
363 int $0x10
364 #endif
365 pushw %ss
366 popw %ds
367 jmp jmp_setup
368 #endif
369 comstart:
370 cld # assume nothing
371 #ifdef ONLY8086
372 movw $INITSEG, %ax
373 pushw %ax
374 #else
375 pushw $INITSEG
376 #endif
377 popw %es
378 #ifdef CMDLINE
379 movw %sp, %di
380 movw $0x80, %si
381 lodsb
382 cbw
383 xchgw %ax, %cx
384 #ifdef BUGGY_CMDLINE
385 test %cl, %cl # C=O=0, set S & Z
386 jng nocmdline # Z == 1 or O != S ?
387 #else
388 jcxz nocmdline
389 #endif
390 # if defined(BZIMAGE) && BZIMAGE >= 0x202
391 movw $INITSEG/16+stacktop/256, EXEADRS(cmd_line_ptr+1)
392 # else
393 movw $0xA33F, 0x7F(%si)
394 # endif
395 # ifndef NO_CMDLINE_SHRINK
396 skipspace:
397 lodsb
398 cmpb $0x20, %al
399 je skipspace
400 # ifndef NO_CMDLINE_FILE
401 movw %si,%dx
402 decw %si
403 subb $'@',%al
404 jne notafile
405 movb $0x3D,%ah
406 int $0x21
407 jc notafile
408 xchgw %ax,%bx
409 //movw %si,%dx // ~320 bytes max
410 movw $EXEADRS(notafile)-130,%cx
411 movb $0x3F,%ah
412 int $0x21
413 xchgw %ax,%cx
414 notafile:
415 # else
416 decw %si
417 # endif
418 # endif
419 rep
420 movsb
421 nocmdline:
422 orb EXEADRS(setup_sects), %ch
423 # ifndef NO_MINSETUP
424 # ifndef BZIMAGE
425 jnz setupok
426 mov $4, %ch
427 setupok:
428 # endif
429 # endif
430 #else
431 movb EXEADRS(setup_sects), %ch
432 #endif
433 movb $(512-(end_header-_start))/2, %cl
434 movw $0x100, %si
435 movw $end_header, %di
436 rep
437 movsw
438 movw $SYSSEG, %ax
439 movw %ds, %bx
440 pushw %es
441 popw %ss
442 #ifndef SHUTDOWNDOS
443 pushw %es
444 pushw $movesys
445 #endif
446 #ifdef VCPI
447 pushaw
448 smsww %ax
449 andb $1, %al
450 je isrm
451 movw $EXEADRS(gdt_vcpi),%si
452 movw $pagebuf-0x90000,%di // %es = 0x9000
453 movl $pagebuf+3,%es:0x1000(%di)
454 call_vcpi:
455 movb $0xDE,%ah // DE01, EBX = getiface(DS:SI, ES:DI)
456 int $0x67
457 movl $FLAT20(sw2pm_params),%esi
458 movb $0x0C,%al // DE0C switchpm(ESI)
459 jmp call_vcpi
460 pm_code:
461 movl %cr0,%eax
462 andl $0x7FFFFFFE,%eax
463 movl %eax,%cr0
464 movl %eax,%cr3
465 isrm:
466 # ifdef SHUTDOWNDOS
467 trace_int19
468 # else
469 popaw
470 retf
471 # endif
472 #else
473 # ifdef SHUTDOWNDOS
474 # ifdef ONLY8086
475 pushw %ax
476 pushw %bx
477 pushw %cx
478 pushw %dx
479 pushw %si
480 pushw %di
481 pushw %bp
482 # else
483 pushaw
484 # endif
485 trace_int19
486 # endif
487 retf
488 #endif
489 #endif
491 # read_sectors reads %di sectors into %es:0 buffer.
492 # %es:0 is updated to the next memory location.
493 # First, sectors are read sector by sector until
494 # sector per track count is known. Then they are
495 # read track by track.
496 # Assume no error on first track.
498 #ifdef FLOPPY_1440K_ONLY
499 #ifndef FLOPPY_HAS_2_SIDES
500 #define FLOPPY_HAS_2_SIDES hardcore heads count to 2
501 #endif
502 #define FLOPPY_SECTORS 18 /* 18 sectors */
503 #else
504 #define FLOPPY_HEADS 2 /* 2 heads minimum */
505 #endif
507 return:
508 #ifndef NO_DOTS
509 movw $0xE2E,%ax
510 int $0x10
511 #endif
512 ret
514 check_limits:
515 #ifndef FLOPPY_1440K_ONLY
516 popw %dx
517 cmpb %al, %cl # max sector known ?
518 ja next_head # no -> store it
519 #ifndef FLOPPY_HAS_2_SIDES
520 #ifdef FLOPPY_HEADS
521 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
522 jb check_cylinder
523 #endif
524 cmpb %ah, %dh # max head known ?
525 ja next_cylinder # no -> store it
526 check_cylinder:
527 #endif
528 pushw %ax
529 cbw # %ah = 0
530 #else
531 pushw %dx
532 #endif
533 int $0x13 # reset controler
534 #ifndef FLOPPY_1440K_ONLY
535 popw %ax
536 movb $1, %al # sector by sector...
537 #else
538 movw $1, %ax
539 jmp more1trk
540 #endif
541 read_sectorslp:
542 pushw %dx # some bios break dx...
543 #ifndef FLOPPY_1440K_ONLY
544 pushw %ax # limits
545 subb %cl, %al # sectors remaining in track
546 ja tolastsect
547 movb $1, %al # first track sector by sector
548 tolastsect:
549 #else
550 movb $FLOPPY_SECTORS+1, %al
551 subb %cl, %al # sectors remaining in track
552 #endif
553 cbw
554 cmpw %di, %ax
555 jb more1trk
556 movw %di, %ax # sectors to read
557 more1trk:
558 pushw %ax # save context
559 movb $2, %ah # cmd: read chs
560 int $0x13
561 #ifndef FLOPPY_1440K_ONLY
562 popw %dx # save %ax
563 popw %ax # limits
564 #else
565 popw %ax # restore context
566 popw %dx
567 #endif
568 jc check_limits
569 #ifndef FLOPPY_1440K_ONLY
570 xchgw %ax, %bp
571 addw %dx,%cx # next sector
572 movw %cx, %si
573 pushw %dx
574 shlclw $5, %dx
575 movw %es, %cx
576 addw %dx, %cx
577 popw %dx
578 subw %dx,%di # update sector counter
579 popw %dx
580 #else
581 addw %ax,%cx # next sector
582 movw %cx, %si
583 pushw %ax
584 shlclw $5, %ax
585 movw %es, %cx
586 addw %ax, %cx
587 popw %ax
588 subw %ax,%di # update sector counter
589 #endif
590 read_sectorsCX:
591 movw %cx, %es # next location
592 jz return
593 read_sectors:
594 movw %si, %cx
595 #ifndef FLOPPY_1440K_ONLY
596 # al is last sector+1
597 # ah is last head+1
598 xchgw %ax, %bp
599 #endif
600 #ifndef FLOPPY_1440K_ONLY
601 cmpb %al,%cl # reach sector limit ?
602 jne bdendlp
603 next_head:
604 movb %cl,%al
605 #else
606 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
607 jne bdendlp
608 #endif
609 movb $1,%cl # first sector
610 #ifndef FLOPPY_HAS_2_SIDES
611 incb %dh # next head
612 cmpb %ah, %dh # reach head limit ?
613 jne bdendlp
614 next_cylinder:
615 movb %dh,%ah
616 movb $0,%dh # first head
617 #else
618 xorb %cl,%dh # next head
619 jne bdendlp # reach head limit ?
620 #endif
621 # NOTE : support 256 cylinders max
622 incb %ch # next cylinder
623 read_first_sectors:
624 bdendlp:
625 jmp read_sectorslp
627 #ifdef VCPI
628 pagebuf = 0x98000
629 tss = gdt_abs-40
630 gdt = gdt_abs-32
631 gdt_null = gdt_abs-32
632 gdt_vcpi = gdt_abs-24
633 gdt_vcpi2 = gdt_abs-16
634 gdt_vcpi3 = gdt_abs-8
635 gdt_abs:
636 .word 0xFFFF
637 .long 0x92000000
638 .byte 0xCF,0
639 gdt_code:
640 .word 0xFFFF
641 gdt_code_base:
642 .long 0x9A000000+FLAT20(0)
643 .byte 0x8F,0
644 gdt_tss:
645 .word 0x00FF
646 gdt_tss_base:
647 .long 0x89000000+FLAT20(tss)
648 .byte 0,0
649 gdtr:
650 gdt_lim:
651 .word 0xFFFF
652 gdt_base:
653 .long FLAT20(gdt)
654 sw2pm_params:
655 sw2pm_cr3:
656 .long pagebuf+0x1000
657 sw2pm_gdtr_ptr:
658 .long FLAT20(gdtr)
659 sw2pm_idtr_ptr:
660 .long FLAT20(idtr)
661 sw2pm_ldtr:
662 .word 0
663 sw2pm_tr:
664 SEL_TSS = gdt_tss-gdt_null
665 .word SEL_TSS
666 sw2pm_jumpaddr:
667 .long pm_code
668 SEL_CODE = gdt_code-gdt_null
669 .word SEL_CODE
670 idtr:
671 idt_lim:
672 .word 0x03FF
673 idt_base:
674 .long 0
675 #endif
676 #ifdef ELKS
677 .org 0x1E3
678 .byte 13,10,7
679 .asciz "ELKS Boot"
680 #endif