wok view memtest/stuff/bootloader.S @ rev 24957

*/stuff/bootloader.S: add CHK_DOS_INT19 (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Apr 23 15:41:59 2022 +0000 (2022-04-23)
parents e197a1539e2e
children 8e505f99deb3
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 pushw %es
82 movw $skip_step19, %si
83 pushw %si
84 retf
85 stepit:
86 # endif
87 pushw 4+2(%si)
88 pushw 4(%si)
89 movw $step19, 4(%si)
90 movw $INITSEG, 4+2(%si)
91 #else
92 pushl $4
93 popw %si
94 popw %ds
95 # ifdef CHK_DOS_INT19
96 cmpb $0xF0, 4*0x19+3-4(%si)
97 jne stepit
98 pushw %es
99 pushw $skip_step19
100 retf
101 stepit:
102 # endif
103 pushl (%si)
104 movl $step19+(INITSEG<<16), (%si)
105 #endif
106 pushfw
107 popw %ax
108 incb %ah # set TF
109 pushw %ax
110 popfw
111 #ifdef ONLY8086
112 ljmp *4*0x19(%si)
113 #else
114 ljmp *4*0x19-4(%si)
115 #endif
116 .endm
118 stacktop = 0x9E00 # in 0x8000 .. 0xA000
119 decw %bp // Magic number: MZ
120 popw %dx
121 jmp start // Bytes on last page of file
122 .word (CODESZ+511)/512 // Pages in file INSTALLER
123 .word 0 // Relocations
124 .word (end_header-_start)/16 // Size of header in paragraphs
125 .word 4096 // Minimum extra paragraphs needed
126 .word -1 // Maximum extra paragraphs needed
127 .word (CODESZ+15)/16 // Initial (relative) SS value INSTALLER
128 .word stacktop // Initial SP value
129 .word 0 // Checksum INSTALLER?
130 .word EXEADRS(comstart) // Initial IP value
131 .word 0xFFF0 // Initial (relative) CS value
132 // .word 0x001C // File address of relocation table
133 // .word 0,0,0 // Overlay number
134 #else
135 #undef VCPI
136 #endif
137 start:
138 xorw %ax, %ax # %ax = 0
139 zeroed = 12 # zeroed registers
140 movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
141 stacktop = 0x9E00 # in 0x8000 .. 0xA000 (+zeroed+12)
142 #ifdef ONLY8086
143 movw $INITSEG, %bx
144 #else
145 pushw $INITSEG
146 #endif
147 end_header:
148 cld # assume nothing
149 #if defined(BZIMAGE) && BZIMAGE >= 0x202
150 popw %es # %es contain INITSEG
151 movw %es, %di
152 #else
153 # cmdline offset at 0x22
154 movw $stacktop, %di # stacktop is an arbitrary value >=
155 # length of bootsect + length of
156 # setup + room for stack;
157 # 12 is disk parm size.
158 # ifdef ONLY8086
159 pushw %bx
160 # endif
161 popw %es # %es contain INITSEG
162 #endif
163 pushw %es
164 popw %ss # %es = %ss = INITSEG
165 movw %di, %sp # put stack at INITSEG:stacktop-...
166 #ifdef EXE_SUPPORT
167 cwd # force %dx = 0 (floppy only)
168 #endif
170 # Many BIOS's default disk parameter tables will not recognize
171 # multi-sector reads beyond the maximum sector number specified
172 # in the default diskette parameter tables - this may mean 7
173 # sectors in some cases.
174 #
175 # Since single sector reads are slow and out of the question,
176 # we must take care of this by creating new parameter tables
177 # (for the first disk) in RAM. We can set the maximum sector
178 # count to 36 - the most we will encounter on an ED 2.88.
179 #
180 # High doesn't hurt. Low does. Let's use the max: 63
182 rep # don't worry about cld
183 stosw # already done above
184 popw %bx # offset = 0
185 popw %ds # %ds = 0
187 movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0)
188 incw %ax
190 ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address
191 pushw %es
192 pushw %di
193 movb $6, %cl # copy 12 bytes
194 rep # don't worry about cld
195 movsw # already done above
196 movw %cx, %ds # %ds = 0
197 #ifdef ONLY8086
198 popw 0x78(%bx) # update parameter table address
199 popw 0x78+2(%bx)
200 #else
201 popl 0x78(%bx) # update parameter table address
202 #endif
203 pushw %ss
204 popw %ds # now %ds = %es = %ss = INITSEG
205 movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
207 xchg %ax, %di # sector count
208 popw %ax # limits = 0
209 incw %cx # cylinder 0, sector 1, clear Z
210 call read_first_sectors # read setup
212 # This routine loads the system at address LOADSEG, making sure
213 # no 64kB boundaries are crossed. We try to load it as fast as
214 # possible, loading whole tracks whenever we can.
216 movw syssize, %di
217 decw %di
218 shrclw $9-4, %di
219 incw %di
220 movw $SYSSEG, %cx
221 #ifdef BZIMAGE
222 push %cx
223 #endif
224 call read_sectorsCX
226 # This procedure turns off the floppy drive motor, so
227 # that we enter the kernel in a known state, and
228 # don't have to worry about it later.
230 kill_motor:
231 xchgw %ax, %di # reset FDC (%di < 128)
232 int $0x13
234 # After that (everything loaded), we jump to the setup-routine
235 # loaded directly after the bootblock:
236 # Segments are as follows: %ds = %ss = INITSEG
238 #ifdef BZIMAGE
239 popw %bx
240 popw %si // SYSSEG:0
241 movesys: // %bx = DS, %si
242 movw $16, %ax
243 mulw %bx
244 addw %si, %ax
245 adcw $0x9300, %dx // %dx:%ax src flat address
246 movw $9, %cx
247 zero1:
248 pushw $0 // 2E..1E
249 loop zero1
250 //pushl $0x93100000 // 1A: dest
251 pushw $0x9310
252 pushw %cx
253 pushw $-1 // 18
254 pushw %cx // 16
255 pushw %dx // src
256 pushw %ax
257 pushw $-1 // 10
258 movb $8, %cl
259 movw %cx, %bx // will move 8*64 = 512Kb
260 zero2:
261 pushw $0 // 0E..00
262 loop zero2
263 movw %sp, %si
264 pushw %ss
265 popw %es
266 pushw %es
267 popw %ds
268 syslp:
269 movb $0x80, %ch
270 movb $0x87, %ah
271 int $0x15
272 incb 0x14(%si)
273 incb 0x1C(%si)
274 decw %bx
275 jne syslp
276 #endif
277 jmp_setup:
278 cli
279 ljmp $SETUPSEG, $0
281 #ifdef EXE_SUPPORT
282 #ifdef SHUTDOWNDOS
283 doiret:
284 iret
285 step19:
286 pushw %si
287 pushw %ds
288 movw %sp, %si
289 ldsw %ss:4(%si), %si
290 cmpw $0x19CD, (%si)
291 popw %ds
292 popw %si
293 jne doiret
294 xorw %si, %si
295 movw %si, %ds
296 pushw %cs
297 popw %ss
298 movw $stacktop-4-16, %sp
299 #ifdef ONLY8086
300 popw 4(%si)
301 popw 4+2(%si)
302 skip_step19:
303 popw %bp
304 popw %di
305 popw %si
306 popw %dx
307 popw %cx
308 popw %bx
309 popw %ax
310 #else
311 popl 4(%si)
312 skip_step19:
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