wok view syslinux/stuff/iso2exe/bootloader.S @ rev 21824

syslinux/taziso: floppy by floppy fallback
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Sep 10 09:01:01 2019 +0200 (2019-09-10)
parents 13835bce7189
children
line source
1 BOOTSEG = 0x07C0 /* original address of boot-sector */
2 SYSSEG = 0x1000 /* historical load address >> 4 */
3 INITSEG = 0x9000 /* boot address >> 4 */
4 SETUPSEG = 0x9020 /* setup address >> 4 */
5 ASK_VGA = -3
7 #ifndef SVGA_MODE
8 #define SVGA_MODE ASK_VGA
9 #endif
11 #ifndef RAMDISK
12 #define RAMDISK 0
13 #endif
15 #ifndef ROOT_RDONLY
16 #define ROOT_RDONLY 1
17 #endif
19 /* some extra features */
20 #define CMDLINE kernel >= 2.4
21 #define OLDCMDLINE kernel < 2.4
22 #define MORETHAN16M up to 4Gb RAM, not 16Mb
23 #define KEYBOARDLESS_SUPPORT scan floppy swap each 5 seconds
25 #define EDIT_CMDLINE
26 #define CMDLINE_SUPPORT
27 #define MOVE_CMDLINE
28 #define INITRD_SUPPORT
29 #define INITRD_AUTOADDR
30 #ifndef MULTI_INITRD
31 #define README_SUPPORT
32 #define COUNTER
33 #endif
35 .code16
36 .org 0
38 bootsect_start:
40 cur_initrd_size_ofs = 494
41 ramdisk_image_ofs = 0x218
42 ramdisk_image = bootsect_start+ramdisk_image_ofs
43 ramdisk_size_ofs = 0x21C
44 ramdisk_size = bootsect_start+ramdisk_size_ofs
45 cmd_line_ptr_ofs = 0x228
46 cmd_line_ptr = bootsect_start+cmd_line_ptr_ofs
47 setup_sects = bootsect_start+497
48 syssize = bootsect_start+500
49 boot_flag_ofs = 510
50 boot_flag = bootsect_start+boot_flag_ofs
53 stacktop = 0x9E00 # in 0x8000 .. 0xA000
54 zeroed = 48+10 # gdt + zeroed registers
55 .macro INIT_REGS
56 movw $stacktop-zeroed, %di # stacktop is an arbitrary value >=
57 # length of bootsect + length of
58 # setup + room for stack;
59 # 12 is disk parm size.
60 pushw $INITSEG
61 popw %ss # %ss contain INITSEG
62 movw %di, %sp # put stack at INITSEG:stacktop-...
63 pushw %ss
64 popw %es # %es = %ss = INITSEG
65 xorw %ax, %ax # %ax = 0
66 #if defined(CMDLINE)
67 movw $zeroed+1, %cx # clear gdt + offset, %ds, limits, cmdline=""
68 rep # don't worry about cld
69 stosb # already done above
70 //decw %di
71 #else
72 movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
73 rep # don't worry about cld
74 stosw # already done above
75 #endif
76 popw %bx # offset = 0
77 .endm
79 LOADSEG = 0x8000 # 0x1000 multiple, up to 512K zImage
80 LOADSZ = 0x10000
82 # bootsect_start:
83 INIT_REGS
84 popw %ds # %ds = 0
85 movb setup_sects+0x7C00, %al # read bootsector + setup
86 incw %ax # %ax = setup_sects+bootsect
87 popw %fs # %fs = 0
89 # Many BIOS's default disk parameter tables will not recognize
90 # multi-sector reads beyond the maximum sector number specified
91 # in the default diskette parameter tables - this may mean 7
92 # sectors in some cases.
93 #
94 # Since single sector reads are slow and out of the question,
95 # we must take care of this by creating new parameter tables
96 # (for the first disk) in RAM. We can set the maximum sector
97 # count to 36 - the most we will encounter on an ED 2.88.
98 #
99 # High doesn't hurt. Low does. Let's use the max: 63
101 cli
102 ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address
103 popw %di
104 pushw %es
105 pushw %di
106 #ifdef CMDLINE_SUPPORT
107 movw $0, %bp # patched by installer (7C22)
108 skipcmdline:
109 #define cmd_line_ptr 0x22
110 #endif
111 movb $6, %cl # copy 12 bytes
112 rep # don't worry about cld
113 movsw # already done above
114 pushw %ss
115 popw %ds # now %ds = %es = %ss = INITSEG
116 popl %fs:0x78(%bx) # update parameter table address
117 movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
119 xchg %ax, %di # sector count
120 popw %ax # limits = 0
121 incw %cx # cylinder 0, sector 1, clear Z
122 call read_first_sectors # read setup
123 #ifdef README_SUPPORT
124 xorw %si, %si
125 orw readme, %si
126 jz readmeend
127 readmeloop:
128 call puts
129 jz readmeend
130 call wait4key
131 cmpb $27, %al
132 jne readmeloop
133 readmeend:
134 #endif
135 loadsys:
136 movw $0x200,%si
137 type_of_loader = 0x10
138 loadflags = 0x11
139 heap_end_ptr = 0x24
140 orw $0x8020, type_of_loader(%si) # loader type = 0x20 = bootsect-loader
141 movb $(stacktop-0x300)/256, heap_end_ptr+1(%si)
142 call puts_version # show which kernel we are loading
144 #ifdef CMDLINE_SUPPORT
145 # The cmdline can be entered and modifed at boot time.
146 # Only characters before the cursor are passed to the kernel.
148 xorw %si, %si
149 orw (%bx), %si
150 jz nocmdline
151 #ifdef OLDCMDLINE
152 movw $0xA33F, -2(%bx)
153 #endif
154 call puts
155 #ifdef EDIT_CMDLINE
156 cmdlp:
157 movb $0x20, %al # clear end of line
158 cmdlpz:
159 call putc # with Space
160 subb $0x18, %al # and BackSpace
161 jnc cmdlpz
162 decw %si
163 cmdget:
164 #ifdef KEYBOARDLESS_SUPPORT
165 call wait4key
166 #else
167 int $0x16
168 cbw # %ah = 0, get keyboard character
169 #endif
170 cmpb $8, %al # BackSpace ?
171 je cmdbs
172 movb %al, (%si) # store char
173 lodsw # %si += 2
174 cmdbs:
175 cmpw %si, (%bx)
176 je cmdget
177 call putc
178 cmpb $10, %al # Enter/linefeed ?
179 jne cmdlp
180 movb %bh,-2(%si) # set end of string and remove CR
181 endcmdline:
182 #endif
183 #ifdef MOVE_CMDLINE
184 pushw %ss
185 popw %es
186 movw $0x8000, %di
187 movw %di, %si
188 xchgw %si, (%bx)
189 movb $0x2, %ch
190 rep
191 movsb
192 #endif
193 nocmdline:
194 #endif
196 # This routine loads the system at address LOADSEG, making sure
197 # no 64kB boundaries are crossed. We try to load it as fast as
198 # possible, loading whole tracks whenever we can.
200 .macro autoaddr base
201 #ifdef INITRD_AUTOADDR
202 movb $0x88, %ah
203 int $0x15
204 //jc NeedMoreRAM # error code 80 or 86
205 cmpw $0xB000, %ax # more than 45M ?
206 jb NeedMoreRAM
207 movb %ch, bootsect_dst_base_hi(%si) # initramfs @ 32M
208 movb %ch, ramdisk_image_ofs+3-\base
209 NeedMoreRAM:
210 #endif
211 .endm
213 bootsect_src_limit = 16
214 bootsect_dst_limit = 24
215 bootsect_src_base = 18
216 bootsect_dst_base = 26 # bits 0..23
217 bootsect_dst_base_hi = 31 # bits 24..31
218 popw %bx # clear %bx
219 movw %sp, %si # for bootsect_gdt
220 init_gdt:
221 decw bootsect_src_limit(%bx,%si) # max 64Kb
222 movw $0x9300+(LOADSEG/0x1000), bootsect_src_base+2(%bx,%si)
223 xorb $bootsect_dst_limit-bootsect_src_limit, %bl
224 jne init_gdt
225 #ifdef INITRD_SUPPORT
226 movw $syssize, %bx
227 movb $5, %cl
228 code32_start = 0x214
229 movw code32_start+1, %ax # destination = 0x00100000 or 0x00010000
230 initrdlp:
231 movl (%bx), %ebx
232 decl %ebx
233 shrl %cl, %ebx
234 #else
235 code32_start = 0x214
236 movw code32_start+1, %ax # destination = 0x00100000 or 0x00010000
237 movl syssize, %ebx
238 decl %ebx
239 shrl $5, %ebx
240 #endif
241 #ifdef MORETHAN16M
242 incl %ebx
243 #else
244 incw %bx
245 #endif
246 syslp:
247 movw %ax, bootsect_dst_base+1(%si)
248 #ifdef MORETHAN16M
249 movl $LOADSZ/512, %edi # size in sectors
250 subl %edi, %ebx
251 #else
252 movw $LOADSZ/512, %di # size in sectors
253 subw %di, %bx
254 #endif
255 pushf
256 jnc not_last
257 addw %bx, %di
258 not_last:
259 #ifdef MULTI_INITRD
260 pushw %di
261 #endif
262 pushw %ax
263 pushw %bx
264 pushw %si
265 xorw %bx,%bx
266 pushw $LOADSEG
267 popw %es
268 patchcall:
269 call read_sectors # update %bp
270 popw %si
271 popw %bx
272 movw %es, %cx # word count = LOADSZ/2 (= LOADSEG)
273 movb $0x87, %ah
274 pushw %ss
275 popw %es # restore es
276 int $0x15 # max 16M, maybe more...
277 popw %ax
278 #ifdef MULTI_INITRD
279 popw %di
280 shlw $1,%di # sectors to pages
281 addw %di, %ax
282 #ifdef MORETHAN16M
283 adcb %cl, bootsect_dst_base_hi(%si) # breaks 16M limit ?
284 #endif
285 #else
286 #ifdef MORETHAN16M
287 addw $0x100, %ax # next dest (ax+=LOADSZ/256)
288 adcb %cl, bootsect_dst_base_hi(%si) # breaks 16M limit ?
289 #else
290 incb %ah # next dest (ax+=LOADSZ/256)
291 #endif
292 #endif
293 popf
294 ja syslp
295 #ifdef INITRD_SUPPORT
296 initrdlp2:
297 #ifdef INITRD_AUTOADDR
298 movw $0x209, %cx
299 #else
300 movb $9, %cl
301 #endif
302 #ifdef MULTI_INITRD
303 movw $cur_initrd_size_ofs, %di
304 movw (%di), %bx
305 addw $4, (%di)
306 shrw %cl, boot_flag_ofs-cur_initrd_size_ofs(%di)
307 je nextInitrd
308 orw %bx, %bx
309 je bootit # no initrd
310 autoaddr cur_initrd_size_ofs(%di)
311 movw ramdisk_image+1,%ax
312 jmp initrdlp
313 nextInitrd:
314 pushw %bx
315 movl -4(%bx), %ebx
316 addl %ebx, ramdisk_size_ofs-cur_initrd_size_ofs(%di)
317 movb $swap_floppy2-0x100, %cs:dpy_swap_floppy-2+0x7C00
318 popw %bx
319 cmpb 2(%di), %bl
320 jb initrdlp
321 #else
322 movw $ramdisk_size, %bx
323 #ifdef MORETHAN16M
324 cmpb %cl, ramdisk_image+2-ramdisk_size(%bx)
325 jb bootit
326 autoaddr ramdisk_size_ofs(%bx)
327 movw ramdisk_image+1,%ax
328 shrw %cl, boot_flag-ramdisk_size(%bx)
329 jne initrdlp
330 #else
331 movw ramdisk_image+1,%ax
332 cmpw %ax, bootsect_dst_base+1(%si)
333 jb initrdlp
334 #endif
335 #endif
336 #endif
337 bootit:
338 #ifdef MULTI_INITRD
339 jcxz read_sectorslp
340 #endif
342 # This procedure turns off the floppy drive motor, so
343 # that we enter the kernel in a known state, and
344 # don't have to worry about it later.
346 kill_motor:
347 xchgw %ax, %di # reset FDC (%di < 128)
348 int $0x13
350 # After that (everything loaded), we jump to the setup-routine
351 # loaded directly after the bootblock:
352 # Segments are as follows: %ds = %ss = INITSEG
354 ljmp $SETUPSEG, $0
356 # read_sectors reads %di sectors into %es:0 buffer.
357 # %es:0 is updated to the next memory location.
358 # First, sectors are read sector by sector until
359 # sector per track count is known. Then they are
360 # read track by track.
361 # Assume no error on first track.
363 #define FLOPPY_CYLINDERS 80
364 #define FLOPPY_HEADS 2
366 .macro putsmsg
367 #ifdef COUNTER
368 movw $msgdigit+1-msg, %bx
369 nextdigit:
370 andb $0xF0, (%bx,%si)
371 decw %bx
372 incb (%bx,%si)
373 cmpb $'9', (%bx,%si)
374 ja nextdigit
375 #endif
376 call puts
377 .endm
379 check_limits:
380 popw %dx
381 cmpb %cl, %al # max sector known ?
382 jbe next_head # no -> store it
383 #.byte 0xd6 # SALC # sector by sector
384 movb $0, %al # sector by sector
385 pushaw
386 int $0x13 # reset controler
387 stc
388 call putcdot # print '-'
389 read_sectorslp:
390 popaw
391 bdendlp:
392 pushw %dx # some bios break dx...
393 pushw %ax # limits
394 subb %cl, %al # sectors remaining in track
395 ja tolastsect
396 movb $1, %al # 1 sector mini
397 tolastsect:
398 cmpw %di, %ax
399 jb more1trk
400 movw %di, %ax # sectors to read
401 more1trk:
402 pushw %ax # save context
403 movb $2, %ah # cmd: read chs
404 int $0x13
405 popw %dx # save %ax
406 popw %ax # limits
407 jc check_limits
408 xchgw %ax, %bp
409 addw %dx,%cx # next sector
410 movw %cx, %gs
411 addb %dl,%bh
412 addb %dl,%bh # next location
413 subw %dx,%di # update sector counter
414 popw %dx
415 jz putcdot
416 read_sectors:
417 movw %gs, %cx
418 # al is last sector+1
419 # ah is 0
420 xchgw %ax, %bp
421 cmpb %al,%cl # reach sector limit ?
422 jne bdendlp
423 next_head:
424 movb %cl,%al
425 movb $1, %cl # first sector
426 inc_head:
427 xorb %cl, %dh # next head
428 jne bdendlp # reach head limit ?
429 incb %ch # next cylinder
430 read_first_sectors:
431 cmpb $FLOPPY_CYLINDERS,%ch # reach cylinder limit ?
432 jne bdendlp
433 next_floppy:
434 movb $0,%ch # first cylinder
435 pushaw
436 movw $swap_floppy,%si
437 dpy_swap_floppy:
438 #ifdef KEYBOARDLESS_SUPPORT
439 pushw %bx
440 putsmsg
441 popw %bx
442 movw %si, %bp
443 waitfloppy:
444 call wait
445 jne waitfloppydone
446 #ifdef MULTI_INITRD
447 decb (%si) # max_timeouts
448 gobootit:
449 //movw ramdisk_size+2-max_timeouts(%si), %cx
450 .byte 0x8B, 0x4C, ramdisk_size+2-max_timeouts
451 jz bootit
452 #endif
453 pushw %dx # some bios break dx...
454 cbw
455 int $0x13 # reset FDC
456 movw $0x201,%ax
457 int $0x13 # read first sector
458 popw %dx
459 rclb $1,%ah # floppy changed 06=>0D no error 00
460 cmpb -2(%bp), %ah # 0D then 00
461 jne waitfloppy # no => try again
462 incw %bp
463 decw %ax # was 0001 ?
464 jne waitfloppy
465 waitfloppydone:
466 #else
467 putsmsg
468 cbw # %ah = 0, get keyboard character
469 int $0x16
470 #endif
471 #ifdef MULTI_INITRD
472 orb $0x20, %al
473 cmp $'b', %al
474 jz gobootit
475 #endif
476 jmp read_sectorslp
478 putcdot:
479 movb $'.'+3, %al // . = success, - = failure
480 putclf:
481 sbbb $3, %al
482 putc:
483 movb $0xe, %ah
484 movw $7, %bx # one dot each 64k
485 int $0x10
486 cmp $0xd, %al # CR ?
487 je putclf
488 #ifdef CMDLINE_SUPPORT
489 movb $cmd_line_ptr, %bl
490 #endif
491 ret
493 #ifdef KEYBOARDLESS_SUPPORT
494 clock = 0x46C
495 wait:
496 wait4key:
497 movw $clock, %di
498 #define DELAY 5
499 movb $257-(DELAY*182)/10, %fs:(%di)
500 waitkbd:
501 movw $0x10D, %ax # test keyboard, timeout => CR
502 cmpb %fs:(%di),%ah
503 je waitdone
504 int $0x16
505 jz waitkbd
506 cbw
507 int $0x16 # eat char
508 movw %di, %fs # disable timeout
509 incw %di # clear Z
510 waitdone:
511 ret
512 #endif
514 #define kernel_version_offset 0xE
515 puts_version:
516 addw kernel_version_offset(%si),%si # starting protocol 2.00, Kernel 1.3.73
517 puts:
518 movb $0xd, %al # CR
519 putcs:
520 call putc
521 lodsb
522 cmpb $0, %al # end of string is any byte <= 0
523 jg putcs
524 ret
526 #ifdef MULTI_INITRD
527 swap_floppy2:
528 .ascii "B or "
529 #endif
530 swap_floppy:
531 #ifdef COUNTER
532 msg:
533 .ascii "Insert disk 00"
534 msgdigit:
535 .ascii "1 and Enter."
536 #else
537 .ascii "Next!"
538 #endif
539 .byte 7,13,0 # swap detection needs 13, 0
540 #ifdef MULTI_INITRD
541 max_timeouts:
542 .byte 20
543 table:
544 .org cur_initrd_size_ofs
545 cur_initrd_size:
546 .word table
547 .byte table+4-256
548 #endif
549 #ifdef README_SUPPORT
550 .org 0x1EF
551 readme:
552 .word 0
553 #endif
554 .org 0x1F1