wok-tiny view x86test/stuff/bootloader.S @ rev 172

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