wok view ipxe/stuff/bootloader.S @ rev 21501

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