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

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