wok view ipxe/stuff/bootloader.S @ rev 25284
roundup: added BUILD_DEPENDS
author | Hans-G?nter Theisgen |
---|---|
date | Mon Jul 18 16:14:38 2022 +0100 (2022-07-18) |
parents | 8e505f99deb3 |
children |
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 .byte 0x6A, SEL_DATA // pushw $SEL_DATA
462 popw %ss
463 movl %cr0,%eax
464 andl $0x7FFFFFFE,%eax
465 movl %eax,%cr0
466 movl %eax,%cr3
467 isrm:
468 # ifdef SHUTDOWNDOS
469 trace_int19
470 # else
471 popaw
472 retf
473 # endif
474 #else
475 # ifdef SHUTDOWNDOS
476 # ifdef ONLY8086
477 pushw %ax
478 pushw %bx
479 pushw %cx
480 pushw %dx
481 pushw %si
482 pushw %di
483 pushw %bp
484 # else
485 pushaw
486 # endif
487 trace_int19
488 # endif
489 retf
490 #endif
491 #endif
493 # read_sectors reads %di sectors into %es:0 buffer.
494 # %es:0 is updated to the next memory location.
495 # First, sectors are read sector by sector until
496 # sector per track count is known. Then they are
497 # read track by track.
498 # Assume no error on first track.
500 #ifdef FLOPPY_1440K_ONLY
501 #ifndef FLOPPY_HAS_2_SIDES
502 #define FLOPPY_HAS_2_SIDES hardcore heads count to 2
503 #endif
504 #define FLOPPY_SECTORS 18 /* 18 sectors */
505 #else
506 #define FLOPPY_HEADS 2 /* 2 heads minimum */
507 #endif
509 return:
510 #ifndef NO_DOTS
511 movw $0xE2E,%ax
512 int $0x10
513 #endif
514 ret
516 check_limits:
517 #ifndef FLOPPY_1440K_ONLY
518 popw %dx
519 cmpb %al, %cl # max sector known ?
520 ja next_head # no -> store it
521 #ifndef FLOPPY_HAS_2_SIDES
522 #ifdef FLOPPY_HEADS
523 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
524 jb check_cylinder
525 #endif
526 cmpb %ah, %dh # max head known ?
527 ja next_cylinder # no -> store it
528 check_cylinder:
529 #endif
530 pushw %ax
531 cbw # %ah = 0
532 #else
533 pushw %dx
534 #endif
535 int $0x13 # reset controler
536 #ifndef FLOPPY_1440K_ONLY
537 popw %ax
538 movb $1, %al # sector by sector...
539 #else
540 movw $1, %ax
541 jmp more1trk
542 #endif
543 read_sectorslp:
544 pushw %dx # some bios break dx...
545 #ifndef FLOPPY_1440K_ONLY
546 pushw %ax # limits
547 subb %cl, %al # sectors remaining in track
548 ja tolastsect
549 movb $1, %al # first track sector by sector
550 tolastsect:
551 #else
552 movb $FLOPPY_SECTORS+1, %al
553 subb %cl, %al # sectors remaining in track
554 #endif
555 cbw
556 cmpw %di, %ax
557 jb more1trk
558 movw %di, %ax # sectors to read
559 more1trk:
560 pushw %ax # save context
561 movb $2, %ah # cmd: read chs
562 int $0x13
563 #ifndef FLOPPY_1440K_ONLY
564 popw %dx # save %ax
565 popw %ax # limits
566 #else
567 popw %ax # restore context
568 popw %dx
569 #endif
570 jc check_limits
571 #ifndef FLOPPY_1440K_ONLY
572 xchgw %ax, %bp
573 addw %dx,%cx # next sector
574 movw %cx, %si
575 pushw %dx
576 shlclw $5, %dx
577 movw %es, %cx
578 addw %dx, %cx
579 popw %dx
580 subw %dx,%di # update sector counter
581 popw %dx
582 #else
583 addw %ax,%cx # next sector
584 movw %cx, %si
585 pushw %ax
586 shlclw $5, %ax
587 movw %es, %cx
588 addw %ax, %cx
589 popw %ax
590 subw %ax,%di # update sector counter
591 #endif
592 read_sectorsCX:
593 movw %cx, %es # next location
594 jz return
595 read_sectors:
596 movw %si, %cx
597 #ifndef FLOPPY_1440K_ONLY
598 # al is last sector+1
599 # ah is last head+1
600 xchgw %ax, %bp
601 #endif
602 #ifndef FLOPPY_1440K_ONLY
603 cmpb %al,%cl # reach sector limit ?
604 jne bdendlp
605 next_head:
606 movb %cl,%al
607 #else
608 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
609 jne bdendlp
610 #endif
611 movb $1,%cl # first sector
612 #ifndef FLOPPY_HAS_2_SIDES
613 incb %dh # next head
614 cmpb %ah, %dh # reach head limit ?
615 jne bdendlp
616 next_cylinder:
617 movb %dh,%ah
618 movb $0,%dh # first head
619 #else
620 xorb %cl,%dh # next head
621 jne bdendlp # reach head limit ?
622 #endif
623 # NOTE : support 256 cylinders max
624 incb %ch # next cylinder
625 read_first_sectors:
626 bdendlp:
627 jmp read_sectorslp
629 #ifdef VCPI
630 pagebuf = 0x98000
631 tss = gdt_abs-40
632 gdt = gdt_abs-32
633 gdt_null = gdt_abs-32
634 gdt_vcpi = gdt_abs-24
635 gdt_vcpi2 = gdt_abs-16
636 gdt_vcpi3 = gdt_abs-8
637 gdt_abs:
638 SEL_DATA = gdt_abs-gdt_null
639 .word 0xFFFF
640 .long 0x92000000
641 .byte 0x8F,0
642 gdt_code:
643 .word 0xFFFF
644 gdt_code_base:
645 .long 0x9A000000+FLAT20(0)
646 .byte 0x8F,0
647 gdt_tss:
648 .word 0x00FF
649 gdt_tss_base:
650 .long 0x89000000+FLAT20(tss)
651 .byte 0,0
652 gdtr:
653 gdt_lim:
654 .word 0xFFFF
655 gdt_base:
656 .long FLAT20(gdt)
657 sw2pm_params:
658 sw2pm_cr3:
659 .long pagebuf+0x1000
660 sw2pm_gdtr_ptr:
661 .long FLAT20(gdtr)
662 sw2pm_idtr_ptr:
663 .long FLAT20(idtr)
664 sw2pm_ldtr:
665 .word 0
666 sw2pm_tr:
667 SEL_TSS = gdt_tss-gdt_null
668 .word SEL_TSS
669 sw2pm_jumpaddr:
670 .long pm_code
671 SEL_CODE = gdt_code-gdt_null
672 .word SEL_CODE
673 idtr:
674 idt_lim:
675 .word 0x03FF
676 idt_base:
677 .long 0
678 #endif
679 #ifdef ELKS
680 .org 0x1E3
681 .byte 13,10,7
682 .asciz "ELKS Boot"
683 #endif
684 .org 0x1F1