wok-current view memtest/stuff/bootloader.S @ rev 24381

updated blktrace (1.2.0 -> 1.3.0)
author Hans-G?nter Theisgen
date Sun Feb 06 10:30:31 2022 +0100 (2022-02-06)
parents 6e3d30b3031f
children d1f31f5f6401
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 //#define 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 jnc 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 //movw $0x8FFF, %ax
317 movb $0x90, %ah
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 #ifndef FLOPPY_HAS_2_SIDES
471 #define FLOPPY_HAS_2_SIDES hardcore heads count to 2
472 #endif
473 #define FLOPPY_SECTORS 18 /* 18 sectors */
474 #else
475 #define FLOPPY_HEADS 2 /* 2 heads minimum */
476 #endif
478 return:
479 #ifndef NO_DOTS
480 movw $0xE2E,%ax
481 int $0x10
482 #endif
483 ret
485 check_limits:
486 #ifndef FLOPPY_1440K_ONLY
487 popw %dx
488 cmpb %al, %cl # max sector known ?
489 ja next_head # no -> store it
490 #ifndef FLOPPY_HAS_2_SIDES
491 #ifdef FLOPPY_HEADS
492 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
493 jb check_cylinder
494 #endif
495 cmpb %ah, %dh # max head known ?
496 ja next_cylinder # no -> store it
497 check_cylinder:
498 #endif
499 pushw %ax
500 cbw # %ah = 0
501 #else
502 pushw %dx
503 #endif
504 int $0x13 # reset controler
505 #ifndef FLOPPY_1440K_ONLY
506 popw %ax
507 movb $1, %al # sector by sector...
508 #else
509 movw $1, %ax
510 jmp more1trk
511 #endif
512 read_sectorslp:
513 pushw %dx # some bios break dx...
514 #ifndef FLOPPY_1440K_ONLY
515 pushw %ax # limits
516 subb %cl, %al # sectors remaining in track
517 ja tolastsect
518 movb $1, %al # first track sector by sector
519 tolastsect:
520 #else
521 movb $FLOPPY_SECTORS+1, %al
522 subb %cl, %al # sectors remaining in track
523 #endif
524 cbw
525 cmpw %di, %ax
526 jb more1trk
527 movw %di, %ax # sectors to read
528 more1trk:
529 pushw %ax # save context
530 movb $2, %ah # cmd: read chs
531 int $0x13
532 #ifndef FLOPPY_1440K_ONLY
533 popw %dx # save %ax
534 popw %ax # limits
535 #else
536 popw %ax # restore context
537 popw %dx
538 #endif
539 jc check_limits
540 #ifndef FLOPPY_1440K_ONLY
541 xchgw %ax, %bp
542 addw %dx,%cx # next sector
543 movw %cx, %si
544 pushw %dx
545 shlclw $5, %dx
546 movw %es, %cx
547 addw %dx, %cx
548 popw %dx
549 subw %dx,%di # update sector counter
550 popw %dx
551 #else
552 addw %ax,%cx # next sector
553 movw %cx, %si
554 pushw %ax
555 shlclw $5, %ax
556 movw %es, %cx
557 addw %ax, %cx
558 popw %ax
559 subw %ax,%di # update sector counter
560 #endif
561 read_sectorsCX:
562 movw %cx, %es # next location
563 jz return
564 read_sectors:
565 movw %si, %cx
566 #ifndef FLOPPY_1440K_ONLY
567 # al is last sector+1
568 # ah is last head+1
569 xchgw %ax, %bp
570 #endif
571 #ifndef FLOPPY_1440K_ONLY
572 cmpb %al,%cl # reach sector limit ?
573 jne bdendlp
574 next_head:
575 movb %cl,%al
576 #else
577 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
578 jne bdendlp
579 #endif
580 movb $1,%cl # first sector
581 #ifndef FLOPPY_HAS_2_SIDES
582 incb %dh # next head
583 cmpb %ah, %dh # reach head limit ?
584 jne bdendlp
585 next_cylinder:
586 movb %dh,%ah
587 movb $0,%dh # first head
588 #else
589 xorb %cl,%dh # next head
590 jne bdendlp # reach head limit ?
591 #endif
592 # NOTE : support 256 cylinders max
593 incb %ch # next cylinder
594 read_first_sectors:
595 bdendlp:
596 jmp read_sectorslp
598 #ifdef VCPI
599 pagebuf = 0x98000
600 tss = gdt_abs-40
601 gdt = gdt_abs-32
602 gdt_null = gdt_abs-32
603 gdt_vcpi = gdt_abs-24
604 gdt_vcpi2 = gdt_abs-16
605 gdt_vcpi3 = gdt_abs-8
606 gdt_abs:
607 .word 0xFFFF
608 .long 0x92000000
609 .byte 0xCF,0
610 gdt_code:
611 .word 0xFFFF
612 gdt_code_base:
613 .long 0x9A000000+FLAT20(0)
614 .byte 0x8F,0
615 gdt_tss:
616 .word 0x00FF
617 gdt_tss_base:
618 .long 0x89000000+FLAT20(tss)
619 .byte 0,0
620 gdtr:
621 gdt_lim:
622 .word 0xFFFF
623 gdt_base:
624 .long FLAT20(gdt)
625 sw2pm_params:
626 sw2pm_cr3:
627 .long pagebuf+0x1000
628 sw2pm_gdtr_ptr:
629 .long FLAT20(gdtr)
630 sw2pm_idtr_ptr:
631 .long FLAT20(idtr)
632 sw2pm_ldtr:
633 .word 0
634 sw2pm_tr:
635 SEL_TSS = gdt_tss-gdt_null
636 .word SEL_TSS
637 sw2pm_jumpaddr:
638 .long pm_code
639 SEL_CODE = gdt_code-gdt_null
640 .word SEL_CODE
641 idtr:
642 idt_lim:
643 .word 0x03FF
644 idt_base:
645 .long 0
646 # ifndef SHUTDOWNDOS
647 saved_ss_sp:
648 .word stacktop-4-16-4,INITSEG
649 # endif
650 #endif
651 #ifdef ELKS
652 .org 0x1E3
653 .byte 13,10,7
654 .asciz "ELKS Boot"
655 #endif