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

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