wok-next view syslinux/stuff/iso2exe/bootloader.S @ rev 18145
Add defragfs
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Thu Jun 18 16:31:01 2015 +0200 (2015-06-18) |
parents | 490951fbd6fd |
children | 0a22c10d35b2 |
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 cli
100 ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address
101 popw %di
102 pushw %es
103 pushw %di
104 #ifdef CMDLINE_SUPPORT
105 movw $0, %bp # patched by installer (7C22)
106 skipcmdline:
107 #define cmd_line_ptr 0x22
108 #endif
109 movb $6, %cl # copy 12 bytes
110 rep # don't worry about cld
111 movsw # already done above
112 pushw %ss
113 popw %ds # now %ds = %es = %ss = INITSEG
114 popl %fs:0x78(%bx) # update parameter table address
115 movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
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 #ifdef EDIT_CMDLINE
142 cmdlp:
143 movb $0x20, %al # clear end of line
144 cmdlpz:
145 call putc # with Space
146 subb $0x18, %al # and BackSpace
147 jnc cmdlpz
148 decw %si
149 cmdget:
150 #ifdef KEYBOARDLESS_SUPPORT
151 call wait4key
152 #else
153 int $0x16
154 #endif
155 cbw # %ah = 0, get keyboard character
156 cmpb $8, %al # BackSpace ?
157 je cmdbs
158 movb %al, (%si) # store char
159 lodsw # %si += 2
160 cmdbs:
161 cmpw %si, cmd_line_ptr-7(%bx)
162 je cmdget
163 call putc
164 cmpb $10, %al # Enter/linefeed ?
165 jne cmdlp
166 movb %bh,-2(%si) # set end of string and remove CR
167 endcmdline:
168 #endif
169 #ifdef MOVE_CMDLINE
170 pushw %ss
171 popw %es
172 movw $0x8000, %di
173 movw %di, %si
174 xchgw %si, cmd_line_ptr-7(%bx)
175 movb $0x2, %ch
176 rep
177 movsb
178 #endif
179 nocmdline:
180 #endif
182 # This routine loads the system at address LOADSEG, making sure
183 # no 64kB boundaries are crossed. We try to load it as fast as
184 # possible, loading whole tracks whenever we can.
186 .macro autoaddr base
187 #ifdef INITRD_AUTOADDR
188 movb $0x88, %ah
189 int $0x15
190 //jc NeedMoreRAM # error code 80 or 86
191 cmpw $0xB000, %ax # more than 45M ?
192 jb NeedMoreRAM
193 movb %ch, bootsect_dst_base_hi(%si) # initramfs @ 32M
194 movb %ch, ramdisk_image_ofs+3-\base
195 NeedMoreRAM:
196 #endif
197 .endm
199 bootsect_src_limit = 16
200 bootsect_dst_limit = 24
201 bootsect_src_base = 18
202 bootsect_dst_base = 26 # bits 0..23
203 bootsect_dst_base_hi = 31 # bits 24..31
204 popw %bx # clear %bx
205 movw %sp, %si # for bootsect_gdt
206 init_gdt:
207 decw bootsect_src_limit(%bx,%si) # max 64Kb
208 movw $0x9300+(LOADSEG/0x1000), bootsect_src_base+2(%bx,%si)
209 xorb $bootsect_dst_limit-bootsect_src_limit, %bl
210 jne init_gdt
211 #ifdef INITRD_SUPPORT
212 movw $syssize, %bx
213 movb $5, %cl
214 code32_start = 0x214
215 movw code32_start+1, %ax # destination = 0x00100000 or 0x00010000
216 initrdlp:
217 movl (%bx), %ebx
218 decl %ebx
219 shrl %cl, %ebx
220 #else
221 code32_start = 0x214
222 movw code32_start+1, %ax # destination = 0x00100000 or 0x00010000
223 movl syssize, %ebx
224 decl %ebx
225 shrl $5, %ebx
226 #endif
227 #ifdef MORETHAN16M
228 incl %ebx
229 #else
230 incw %bx
231 #endif
232 syslp:
233 movw %ax, bootsect_dst_base+1(%si)
234 #ifdef MORETHAN16M
235 movl $LOADSZ/512, %edi # size in sectors
236 subl %edi, %ebx
237 #else
238 movw $LOADSZ/512, %di # size in sectors
239 subw %di, %bx
240 #endif
241 pushf
242 jnc not_last
243 addw %bx, %di
244 not_last:
245 #ifdef MULTI_INITRD
246 pushw %di
247 #endif
248 pushw %ax
249 pushw %bx
250 pushw %si
251 xorw %bx,%bx
252 pushw $LOADSEG
253 popw %es
254 patchcall:
255 call read_sectors # update %bp
256 popw %si
257 popw %bx
258 movw %es, %cx # word count = LOADSZ/2 (= LOADSEG)
259 movb $0x87, %ah
260 pushw %ss
261 popw %es # restore es
262 int $0x15 # max 16M, maybe more...
263 popw %ax
264 #ifdef MULTI_INITRD
265 popw %di
266 shlw $1,%di # sectors to pages
267 addw %di, %ax
268 #ifdef MORETHAN16M
269 adcb %cl, bootsect_dst_base_hi(%si) # breaks 16M limit ?
270 #endif
271 #else
272 #ifdef MORETHAN16M
273 addw $0x100, %ax # next dest (ax+=LOADSZ/256)
274 adcb %cl, bootsect_dst_base_hi(%si) # breaks 16M limit ?
275 #else
276 incb %ah # next dest (ax+=LOADSZ/256)
277 #endif
278 #endif
279 popf
280 ja syslp
281 #ifdef INITRD_SUPPORT
282 initrdlp2:
283 #ifdef INITRD_AUTOADDR
284 movw $0x209, %cx
285 #else
286 movb $9, %cl
287 #endif
288 #ifdef MULTI_INITRD
289 movw $cur_initrd_size_ofs, %di
290 movw (%di), %bx
291 addw $4, (%di)
292 shrw %cl, boot_flag_ofs-cur_initrd_size_ofs(%di)
293 je nextInitrd
294 orw %bx, %bx
295 je bootit # no initrd
296 autoaddr cur_initrd_size_ofs(%di)
297 movw ramdisk_image+1,%ax
298 jmp initrdlp
299 nextInitrd:
300 pushw %bx
301 movl -4(%bx), %ebx
302 addl %ebx, ramdisk_size_ofs-cur_initrd_size_ofs(%di)
303 movb $swap_floppy2-0x100, %cs:dpy_swap_floppy-2+0x7C00
304 popw %bx
305 cmpb 2(%di), %bl
306 jb initrdlp
307 #else
308 movw $ramdisk_size, %bx
309 autoaddr ramdisk_size_ofs(%bx)
310 movw ramdisk_image+1,%ax
311 #ifdef MORETHAN16M
312 cmpb %cl, ramdisk_image+2-ramdisk_size(%bx)
313 jb bootit
314 shrw %cl, boot_flag-ramdisk_size(%bx)
315 jne initrdlp
316 #else
317 cmpw %ax, bootsect_dst_base+1(%si)
318 jb initrdlp
319 #endif
320 #endif
321 #endif
322 #ifdef MULTI_INITRD
323 bootit:
324 jcxz read_sectorslp
325 #endif
327 # This procedure turns off the floppy drive motor, so
328 # that we enter the kernel in a known state, and
329 # don't have to worry about it later.
331 kill_motor:
332 xchgw %ax, %di # reset FDC (%di < 128)
333 int $0x13
335 # After that (everything loaded), we jump to the setup-routine
336 # loaded directly after the bootblock:
337 # Segments are as follows: %ds = %ss = INITSEG
339 ljmp $SETUPSEG, $0
341 # read_sectors reads %di sectors into %es:0 buffer.
342 # %es:0 is updated to the next memory location.
343 # First, sectors are read sector by sector until
344 # sector per track count is known. Then they are
345 # read track by track.
346 # Assume no error on first track.
348 #define FLOPPY_CYLINDERS 80
349 #define FLOPPY_HEADS 2
351 check_limits:
352 popw %dx
353 cmpb %al, %cl # max sector known ?
354 ja next_head # no -> store it
355 pushaw
356 int $0x13 # reset controler
357 stc
358 call putcdot # print '-'
359 read_sectorslp:
360 popaw
361 bdendlp:
362 pushw %dx # some bios break dx...
363 pushw %ax # limits
364 subb %cl, %al # sectors remaining in track
365 ja tolastsect
366 movb $1, %al # 1 sector mini
367 tolastsect:
368 cmpw %di, %ax
369 jb more1trk
370 movw %di, %ax # sectors to read
371 more1trk:
372 pushw %ax # save context
373 movb $2, %ah # cmd: read chs
374 int $0x13
375 popw %dx # save %ax
376 popw %ax # limits
377 jc check_limits
378 xchgw %ax, %bp
379 addw %dx,%cx # next sector
380 movw %cx, %gs
381 addb %dl,%bh
382 addb %dl,%bh # next location
383 subw %dx,%di # update sector counter
384 popw %dx
385 jz putcdot
386 read_sectors:
387 movw %gs, %cx
388 # al is last sector+1
389 # ah is 0
390 xchgw %ax, %bp
391 cmpb %al,%cl # reach sector limit ?
392 jne bdendlp
393 next_head:
394 movb %cl,%al
395 movb $1, %cl # first sector
396 inc_head:
397 xorb %cl, %dh # next head
398 jne bdendlp # reach head limit ?
399 incb %ch # next cylinder
400 read_first_sectors:
401 cmpb $FLOPPY_CYLINDERS,%ch # reach cylinder limit ?
402 jne bdendlp
403 next_floppy:
404 movb $0,%ch # first cylinder
405 pushaw
406 movw $swap_floppy,%si
407 dpy_swap_floppy:
408 #ifdef KEYBOARDLESS_SUPPORT
409 pushw %bx
410 call puts
411 popw %bx
412 movw %si, %bp
413 waitfloppy:
414 call wait
415 jne waitfloppydone
416 #ifdef MULTI_INITRD
417 decb (%si) # max_timeouts
418 gobootit:
419 //movw ramdisk_size+2-max_timeouts(%si), %cx
420 .byte 0x8B, 0x4C, ramdisk_size+2-max_timeouts
421 jz bootit
422 #endif
423 pushw %dx # some bios break dx...
424 cbw
425 int $0x13 # reset FDC
426 movw $0x201,%ax
427 int $0x13 # read first sector
428 popw %dx
429 rclb $1,%ah # floppy changed 06=>0D no error 00
430 cmpb -2(%bp), %ah # 0D then 00
431 jne waitfloppy # no => try again
432 incw %bp
433 decw %ax # was 0001 ?
434 jne waitfloppy
435 waitfloppydone:
436 #else
437 call puts
438 cbw # %ah = 0, get keyboard character
439 int $0x16
440 #endif
441 #ifdef MULTI_INITRD
442 orb $0x20, %al
443 cmp $'b', %al
444 jz gobootit
445 #endif
446 jmp read_sectorslp
448 putcdot:
449 movb $'.'+3, %al // . = success, - = failure
450 putclf:
451 sbbb $3, %al
452 putc:
453 movb $0xe, %ah
454 movw $7, %bx # one dot each 64k
455 int $0x10
456 cmp $0xd, %al # CR ?
457 je putclf
458 ret
460 #ifdef KEYBOARDLESS_SUPPORT
461 clock = 0x46C
462 wait:
463 wait4key:
464 movw $clock, %di
465 #define DELAY 5
466 movb $257-(DELAY*182)/10, %fs:(%di)
467 waitkbd:
468 movw $0x10D, %ax # test keyboard, timeout => CR
469 cmpb %fs:(%di),%ah
470 je waitdone
471 int $0x16
472 jz waitkbd
473 cbw
474 int $0x16 # eat char
475 movw %di, %fs # disable timeout
476 incw %di # clear Z
477 waitdone:
478 ret
479 #endif
481 #define kernel_version_offset 0xE
482 puts_version:
483 addw kernel_version_offset(%si),%si # starting protocol 2.00, Kernel 1.3.73
484 puts:
485 movb $0xd, %al # CR
486 putcs:
487 call putc
488 lodsb
489 cmpb $0, %al # end of string is any byte <= 0
490 jg putcs
491 ret
493 #ifdef MULTI_INITRD
494 swap_floppy2:
495 .ascii "B or "
496 #endif
497 swap_floppy:
498 .ascii "Next!"
499 .byte 7,13,0 # swap detection needs 13, 0
500 #ifdef MULTI_INITRD
501 max_timeouts:
502 .byte 20
503 table:
504 .org cur_initrd_size_ofs
505 cur_initrd_size:
506 .word table
507 .byte table+4-256
508 #endif
509 .org 0x1F1