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

memtest, ipxe: update bootsector
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Feb 01 12:59:51 2018 +0100 (2018-02-01)
parents d74b8b5a78d0
children ccdba9b27403
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 pushw %ds
171 movb $6, %cl # copy 12 bytes
172 rep # don't worry about cld
173 movsw # already done above
174 popw %ds
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 jc 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 movb $0x90, %ah
318 ;decw %ax
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 jcxz nocmdline
361 # if defined(BZIMAGE) && BZIMAGE >= 0x202
362 movw $INITSEG/16+stacktop/256, EXEADRS(cmd_line_ptr+1)
363 # else
364 movw $0xA33F, 0x7F(%si)
365 # endif
366 # ifndef NO_CMDLINE_SHRINK
367 skipspace:
368 lodsb
369 cmpb $0x20, %al
370 je skipspace
371 # ifndef NO_CMDLINE_FILE
372 movw %si,%dx
373 decw %si
374 subb $'@',%al
375 jne notafile
376 movb $0x3D,%ah
377 int $0x21
378 jc notafile
379 xchgw %ax,%bx
380 //movw %si,%dx // ~320 bytes max
381 movw $EXEADRS(notafile)-130,%cx
382 movb $0x3F,%ah
383 int $0x21
384 xchgw %ax,%cx
385 notafile:
386 # else
387 decw %si
388 # endif
389 # endif
390 rep
391 movsb
392 nocmdline:
393 orb EXEADRS(setup_sects), %ch
394 # ifndef NO_MINSETUP
395 # ifndef BZIMAGE
396 jnz setupok
397 mov $4, %ch
398 setupok:
399 # endif
400 # endif
401 #else
402 movb EXEADRS(setup_sects), %ch
403 #endif
404 movb $(512-(end_header-_start))/2, %cl
405 movw $0x100, %si
406 movw $end_header, %di
407 rep
408 movsw
409 movw $SYSSEG, %ax
410 movw %ds, %bx
411 pushw %es
412 popw %ss
413 #ifndef SHUTDOWNDOS
414 pushw %es
415 pushw $movesys
416 #endif
417 #ifdef VCPI
418 pushaw
419 smsww %ax
420 andb $1, %al
421 je isrm
422 movw $EXEADRS(gdt_vcpi),%si
423 movw $pagebuf-0x90000,%di // %es = 0x9000
424 movl $pagebuf+3,%es:0x1000(%di)
425 call_vcpi:
426 movb $0xDE,%ah // DE01, EBX = getiface(DS:SI, ES:DI)
427 int $0x67
428 movl $FLAT20(sw2pm_params),%esi
429 movb $0x0C,%al // DE0C switchpm(ESI)
430 jmp call_vcpi
431 pm_code:
432 movl %cr0,%eax
433 andl $0x7FFFFFFE,%eax
434 movl %eax,%cr0
435 movl %eax,%cr3
436 isrm:
437 # ifdef SHUTDOWNDOS
438 trace_int19
439 # else
440 lssw %cs:EXEADRS(saved_ss_sp),%sp
441 popaw
442 retf
443 # endif
444 #else
445 # ifdef SHUTDOWNDOS
446 # ifdef ONLY8086
447 pushw %ax
448 pushw %bx
449 pushw %cx
450 pushw %dx
451 pushw %si
452 pushw %di
453 pushw %bp
454 # else
455 pushaw
456 # endif
457 trace_int19
458 # endif
459 retf
460 #endif
461 #endif
463 # read_sectors reads %di sectors into %es:0 buffer.
464 # %es:0 is updated to the next memory location.
465 # First, sectors are read sector by sector until
466 # sector per track count is known. Then they are
467 # read track by track.
468 # Assume no error on first track.
470 #ifdef FLOPPY_1440K_ONLY
471 #define FLOPPY_HAS_2_SIDES hardcore heads count to 2
472 #define FLOPPY_SECTORS 18 /* 18 sectors */
473 #else
474 #define FLOPPY_HEADS 2 /* 2 heads minimum */
475 #endif
477 return:
478 #ifndef NO_DOTS
479 movw $0xE2E,%ax
480 int $0x10
481 #endif
482 ret
484 check_limits:
485 #ifndef FLOPPY_1440K_ONLY
486 popw %dx
487 cmpb %al, %cl # max sector known ?
488 ja next_head # no -> store it
489 #ifndef FLOPPY_HAS_2_SIDES
490 #ifdef FLOPPY_HEADS
491 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
492 jb check_cylinder
493 #endif
494 cmpb %ah, %dh # max head known ?
495 ja next_cylinder # no -> store it
496 check_cylinder:
497 #endif
498 pushw %ax
499 cbw # %ah = 0
500 #else
501 pushw %dx
502 #endif
503 int $0x13 # reset controler
504 #ifndef FLOPPY_1440K_ONLY
505 popw %ax
506 movb $1, %al # sector by sector...
507 #else
508 movw $1, %ax
509 jmp more1trk
510 #endif
511 read_sectorslp:
512 pushw %dx # some bios break dx...
513 #ifndef FLOPPY_1440K_ONLY
514 pushw %ax # limits
515 subb %cl, %al # sectors remaining in track
516 ja tolastsect
517 movb $1, %al # first track sector by sector
518 tolastsect:
519 #else
520 movb $FLOPPY_SECTORS+1, %al
521 subb %cl, %al # sectors remaining in track
522 #endif
523 cbw
524 cmpw %di, %ax
525 jb more1trk
526 movw %di, %ax # sectors to read
527 more1trk:
528 pushw %ax # save context
529 movb $2, %ah # cmd: read chs
530 int $0x13
531 #ifndef FLOPPY_1440K_ONLY
532 popw %dx # save %ax
533 popw %ax # limits
534 #else
535 popw %ax # restore context
536 popw %dx
537 #endif
538 jc check_limits
539 #ifndef FLOPPY_1440K_ONLY
540 xchgw %ax, %bp
541 addw %dx,%cx # next sector
542 movw %cx, %si
543 pushw %dx
544 shlclw $5, %dx
545 movw %es, %cx
546 addw %dx, %cx
547 popw %dx
548 subw %dx,%di # update sector counter
549 popw %dx
550 #else
551 addw %ax,%cx # next sector
552 movw %cx, %si
553 pushw %ax
554 shlclw $5, %ax
555 movw %es, %cx
556 addw %ax, %cx
557 popw %ax
558 subw %ax,%di # update sector counter
559 #endif
560 read_sectorsCX:
561 movw %cx, %es # next location
562 jz return
563 read_sectors:
564 movw %si, %cx
565 #ifndef FLOPPY_1440K_ONLY
566 # al is last sector+1
567 # ah is last head+1
568 xchgw %ax, %bp
569 #endif
570 #ifndef FLOPPY_1440K_ONLY
571 cmpb %al,%cl # reach sector limit ?
572 jne bdendlp
573 next_head:
574 movb %cl,%al
575 #else
576 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
577 jne bdendlp
578 #endif
579 movb $1,%cl # first sector
580 #ifndef FLOPPY_HAS_2_SIDES
581 incb %dh # next head
582 cmpb %ah, %dh # reach head limit ?
583 jne bdendlp
584 next_cylinder:
585 movb %dh,%ah
586 movb $0,%dh # first head
587 #else
588 xorb %cl,%dh # next head
589 jne bdendlp # reach head limit ?
590 #endif
591 # NOTE : support 256 cylinders max
592 incb %ch # next cylinder
593 read_first_sectors:
594 bdendlp:
595 jmp read_sectorslp
597 #ifdef VCPI
598 pagebuf = 0x98000
599 tss = gdt_abs-40
600 gdt = gdt_abs-32
601 gdt_null = gdt_abs-32
602 gdt_vcpi = gdt_abs-24
603 gdt_vcpi2 = gdt_abs-16
604 gdt_vcpi3 = gdt_abs-8
605 gdt_abs:
606 .word 0xFFFF
607 .long 0x92000000
608 .byte 0xCF,0
609 gdt_code:
610 .word 0xFFFF
611 gdt_code_base:
612 .long 0x9A000000+FLAT20(0)
613 .byte 0x8F,0
614 gdt_tss:
615 .word 0x00FF
616 gdt_tss_base:
617 .long 0x89000000+FLAT20(tss)
618 .byte 0,0
619 gdtr:
620 gdt_lim:
621 .word 0xFFFF
622 gdt_base:
623 .long FLAT20(gdt)
624 sw2pm_params:
625 sw2pm_cr3:
626 .long pagebuf+0x1000
627 sw2pm_gdtr_ptr:
628 .long FLAT20(gdtr)
629 sw2pm_idtr_ptr:
630 .long FLAT20(idtr)
631 sw2pm_ldtr:
632 .word 0
633 sw2pm_tr:
634 SEL_TSS = gdt_tss-gdt_null
635 .word SEL_TSS
636 sw2pm_jumpaddr:
637 .long pm_code
638 SEL_CODE = gdt_code-gdt_null
639 .word SEL_CODE
640 idtr:
641 idt_lim:
642 .word 0x03FF
643 idt_base:
644 .long 0
645 # ifndef SHUTDOWNDOS
646 saved_ss_sp:
647 .word stacktop-4-16-4,INITSEG
648 # endif
649 #endif
650 #ifdef ELKS
651 .org 0x1E3
652 .byte 13,10,7
653 .asciz "ELKS Boot"
654 #endif