wok view linux/stuff/linux-header-2.6.30.6.u @ rev 5564
linux/bootloader.sh: coreutils compatible
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Fri May 14 13:34:05 2010 +0200 (2010-05-14) |
parents | efca0feeb58e |
children |
line source
1 --- linux-2.6.30.6/arch/x86/boot/header.S
2 +++ linux-2.6.30.6/arch/x86/boot/header.S
3 @@ -6,7 +6,7 @@
4 * Based on bootsect.S and setup.S
5 * modified by more people than can be counted
6 *
7 - * Rewritten as a common file by H. Peter Anvin (Apr 2007)
8 + * Rewritten Pascal Bellard (Nov 2009)
9 *
10 * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment
11 * addresses must be multiplied by 16 to obtain their respective linear
12 @@ -26,6 +26,8 @@
14 BOOTSEG = 0x07C0 /* original address of boot-sector */
15 SYSSEG = 0x1000 /* historical load address >> 4 */
16 +INITSEG = 0x9000 /* boot address >> 4 */
17 +SETUPSEG = 0x9020 /* setup address >> 4 */
19 #ifndef SVGA_MODE
20 #define SVGA_MODE ASK_VGA
21 @@ -39,53 +41,412 @@
22 #define ROOT_RDONLY 1
23 #endif
25 +/* some extra features */
26 +#define EDIT_CMDLINE on hotkey
27 +#define SHOW_REGS show int13 status & parameters
28 +
29 .code16
30 .section ".bstext", "ax"
32 .global bootsect_start
33 bootsect_start:
34 + cld # assume nothing
35 +stacktop = 0x9E00 # in 0x8000 .. 0xA000
36 +zeroed = 48+10 # gdt + zeroed registers
37 + movw $stacktop-12-zeroed, %di # stacktop is an arbitrary value >=
38 + # length of bootsect + length of
39 + # setup + room for stack;
40 + # 12 is disk parm size.
41 + pushw $INITSEG
42 + popw %es # %es = INITSEG
44 - # Normalize the start address
45 - ljmp $BOOTSEG, $start2
46 + pushw %es
47 + popw %ss # %ss and %es already contain INITSEG
48 + movw %di, %sp # put stack at INITSEG:stacktop-...
50 -start2:
51 - movw %cs, %ax
52 - movw %ax, %ds
53 - movw %ax, %es
54 - movw %ax, %ss
55 - xorw %sp, %sp
56 - sti
57 - cld
58 +# Many BIOS's default disk parameter tables will not recognize
59 +# multi-sector reads beyond the maximum sector number specified
60 +# in the default diskette parameter tables - this may mean 7
61 +# sectors in some cases.
62 +#
63 +# Since single sector reads are slow and out of the question,
64 +# we must take care of this by creating new parameter tables
65 +# (for the first disk) in RAM. We can set the maximum sector
66 +# count to 36 - the most we will encounter on an ED 2.88.
67 +#
68 +# High doesn't hurt. Low does. Let's use the max: 63
69 +#
70 +# Segments are as follows: %es = %ss = INITSEG,
72 - movw $bugger_off_msg, %si
73 + xorw %ax, %ax # %ax = 0
74 + movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
75 + rep # don't worry about cld
76 + stosw # already done above
77 + popw %bx # offset = 0
78 + popw %ds # %ds = 0
79 + popw %gs # %gs = 0
81 -msg_loop:
82 - lodsb
83 - andb %al, %al
84 - jz bs_die
85 - movb $0xe, %ah
86 - movw $7, %bx
87 + movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0)
88 + incw %ax
89 +
90 + pushw %es
91 + pushw %di # %ds:%bx+0x78 is parameter table address
92 + ldsw 0x78(%bx), %si # %ds:%si is source
93 + movb $6, %cl # copy 12 bytes
94 + rep # don't worry about cld
95 + movsw # already done above
96 + popl %gs:0x78(%bx) # update parameter table address
97 + pushw %es
98 + popw %ds # now %ds = %es = %ss = INITSEG
99 + movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
100 + cli
101 +
102 + xchg %ax, %di # sector count
103 + popw %ax # limits = 0
104 + incw %cx # cylinder 0, sector 1
105 + call read_first_sectors # read setup
106 +
107 +offset_version = 0xE
108 + movw $0x200,%si
109 + addw offset_version(%si),%si # starting protocol 2.00, Kernel 1.3.73
110 + call puts # show which kernel we are loading
111 +
112 +# The cmdline can be entered and modifed at boot time.
113 +# Only characters before the cursor are passed to the kernel.
114 + popw %bx # clear %bx
115 + orw cmd_line_ptr, %bx
116 + jz nocmdline
117 + pushw %bx
118 + call read_one_sector
119 + popw %si
120 + call puts
121 +#ifdef EDIT_CMDLINE
122 +cmdlp:
123 + movb $0x20, %al # clear end of line
124 + int $0x10 # with Space
125 + movb $8, %al # and BackSpace
126 int $0x10
127 - jmp msg_loop
128 + decw %si
129 +cmdget:
130 + call wait4key
131 + cmpb $8, %al # BackSpace ?
132 + je cmdbs
133 + movb %al, (%si) # store char
134 + lodsw # %si += 2
135 +cmdbs:
136 +#if 1
137 + cmpw %si,cmd_line_ptr
138 + je cmdget
139 +#endif
140 + call putc # set %ah and %bx
141 + cmpb $10, %al # Enter ?
142 + jne cmdlp
143 + movb %bh,-2(%si) # set end of string and remove CR
144 +endcmdline:
145 +#endif
146 +nocmdline:
148 -bs_die:
149 - # Allow the user to press a key, then reboot
150 - xorw %ax, %ax
151 - int $0x16
152 - int $0x19
153 +# This routine loads the system at address SYSSEG, making sure
154 +# no 64kB boundaries are crossed. We try to load it as fast as
155 +# possible, loading whole tracks whenever we can.
157 - # int 0x19 should never return. In case it does anyway,
158 - # invoke the BIOS reset code...
159 - ljmp $0xf000,$0xfff0
160 +ramdisk_image = 0x0218
161 +ramdisk_size = 0x021C
162 + movw %sp, %si # for bootsect_gdt
163 + decw 16(%si) # bootsect_src = 64Kb
164 + decw 24(%si) # bootsect_dst = 64Kb
165 + movw $syssize, %di
166 +type_of_loader = 0x210
167 +loadflags = 0x211
168 +heap_end_ptr = 0x224
169 +ksyssize = 500
170 + orw $0x80FF, type_of_loader-ksyssize(%di) # loader type = 0xFF
171 + movw $stacktop-0x200, heap_end_ptr-ksyssize(%di)
172 + movb $0x10, %al # destination = 0x100000
173 + movb $5, %cl
174 +initrdlp:
175 + decw %ax
176 + movb $0x93,%ah
177 + movw %ax, 28(%si) # bootsect_dst_base+2
178 + movb $(SYSSEG/4096), %al # source = SYSSEG
179 + movw %ax, 20(%si) # bootsect_src_base+2
180 + cbw
181 + cwde
182 + shlw %cl, %ax
183 + decw %ax
184 + addl (%di),%eax
185 + shrl %cl, %eax
186 +syslp:
187 + pushw $SYSSEG
188 + popw %es
189 + movw $128,%di # 64Kb
190 + subw %di, %ax # max 32M > int 15 limit
191 + pushf
192 + jnc not_last
193 + addw %ax, %di
194 +not_last:
195 + xorw %bx, %bx # clear %bx
196 + pushw %ax
197 +#if defined(SHOW_REGS)
198 + pushw %si
199 + call read_sectors
200 + popw %si
201 +#else
202 + call read_sectors
203 +#endif
204 + movw $0x8000, %cx # full 64K
205 + movb $0x87, %ah
206 + incb 28(%si) # bootsect_dst_base+2
207 + int $0x15 # max 16M
208 + popw %ax
209 + popf
210 + ja syslp
211 + movw ramdisk_image+2,%ax
212 + movw $ramdisk_size,%di
213 + movb $9, %cl
214 + cmpb %al,28(%si)
215 + jb initrdlp
217 - .section ".bsdata", "a"
218 -bugger_off_msg:
219 - .ascii "Direct booting from floppy is no longer supported.\r\n"
220 - .ascii "Please use a boot loader program instead.\r\n"
221 - .ascii "\n"
222 - .ascii "Remove disk and press any key to reboot . . .\r\n"
223 - .byte 0
224 +# This procedure turns off the floppy drive motor, so
225 +# that we enter the kernel in a known state, and
226 +# don't have to worry about it later.
228 +#if 1
229 +kill_motor:
230 + xchgw %ax, %bx # reset FDC
231 + int $0x13
232 +#else
233 +kill_motor:
234 + movw $0x3f2, %dx
235 + xchgw %ax, %bx
236 + outb %al, %dx
237 +#endif
238 +
239 +# After that (everything loaded), we jump to the setup-routine
240 +# loaded directly after the bootblock:
241 +# Segments are as follows: %ds = %ss = INITSEG
242 +
243 + ljmp $SETUPSEG, $0
244 +
245 +# read_sectors reads %di sectors into %es:0 buffer.
246 +# %es:0 is updated to the next memory location.
247 +# First, sectors are read sector by sector until
248 +# sector per track count is known. Then they are
249 +# read track by track.
250 +# Assume no error on first track.
251 +
252 +#define FLOPPY_CYLINDERS 80 /* 80 cylinders minimum */
253 +#define FLOPPY_HEADS 2 /* 2 heads minimum */
254 +#define FLOPPY_SECTORS 18 /* 18 sectors minimum */
255 +
256 +#ifdef SHOW_REGS
257 +print_loop:
258 + movb $0x6 + 'A' - 1, %al
259 + subb %cl, %al
260 + movw $regs, %si # caller %si is saved
261 + call putcs # putc(%al) + puts(%si)
262 +# it will print out all of the registers.
263 + popw %bp # load word into %si
264 + jmp print_all # print %bp (status)
265 +#endif
266 +check_limits:
267 +#ifndef SHOW_REGS
268 + popw %dx
269 +#endif
270 + cmpb $FLOPPY_SECTORS+1, %cl # 18 sectors minimum
271 + jb check_head
272 + cmpb %al, %cl # max sector known ?
273 + ja next_head # no -> store it
274 +check_head:
275 + cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
276 + jb check_cylinder
277 + cmpb %ah, %dh # max head known ?
278 + ja next_cylinder # no -> store it
279 +check_cylinder:
280 + pushaw
281 +#ifdef SHOW_REGS
282 + cmpw $0x600,%bp # disk changed ?
283 + je reset_floppy
284 + pushw %es # print %es (named EX)
285 + pushw %dx # print %dx
286 + pushw %cx # print %cx
287 + pushw %bx # print %bx
288 + xchgw %ax, %si
289 + movb $2,%ah
290 + pushw %ax # print %ax
291 + movb $6,%cl
292 +print_all:
293 + movb $4, %ch # 4 hex digits
294 +print_digit:
295 + rolw $4, %bp # rotate to use low 4 bits
296 + movb $0x0f, %al
297 + andw %bp, %ax # %al = mask for nybble
298 + addb $0x90, %al # convert %al to ascii hex
299 + daa # in only four instructions!
300 + adcb $0x40, %al
301 + daa
302 + call putc # set %ah and %bx
303 + decb %ch
304 + jnz print_digit
305 + movb $0x20, %al # SPACE
306 + int $0x10
307 + loop print_loop
308 + call wait
309 + cbw # %ah = 0
310 +reset_floppy:
311 +#else
312 + cbw # %ah = 0
313 +#endif
314 + int $0x13 # reset controler
315 + popaw
316 +read_sectorslp:
317 + pushw %dx # some bios break dx...
318 + pushw %ax # limits
319 + subb %cl, %al # sectors remaining in track
320 + ja tolastsect
321 + movb $1, %al # 1 sector mini
322 +tolastsect:
323 + cbw
324 + cmpw %di, %ax
325 + jb more1trk
326 + movw %di, %ax # sectors to read
327 +more1trk:
328 + pushw %ax # save context
329 + movb $2, %ah # cmd: read chs
330 + int $0x13
331 +#ifdef SHOW_REGS
332 + xchgw %ax, %bp # status
333 +#endif
334 +# ifdef SHOW_REGS
335 + popw %si # save %ax
336 + popw %ax # limits
337 + popw %dx
338 +# else
339 + popw %dx # save %ax
340 + popw %ax # limits
341 +# endif
342 + jc check_limits
343 +# ifdef SHOW_REGS
344 +update_regs:
345 + decw %di # update sector counter
346 + incw %cx # next sector
347 + addb $2,%bh # next location
348 + decw %si
349 + jnz update_regs
350 +# else
351 + subw %dx,%di # update sector counter
352 + addw %dx,%cx # next sector
353 + addw %dx,%dx
354 + addb %dl,%bh # next location
355 + popw %dx
356 +# endif
357 + cmpb %al,%cl # reach sector limit ?
358 + jne bdendlp
359 +next_head:
360 + movb %cl,%al
361 + incb %dh # next head
362 + movb $1,%cl # first sector
363 + cmpb %ah, %dh # reach head limit ?
364 + jne bdendlp
365 +next_cylinder:
366 + movb %dh,%ah
367 +# NOTE : support 256 cylinders max
368 + incb %ch # next cylinder
369 +read_first_sectors:
370 + movb $0,%dh # first head
371 +cylinder_count = 496
372 + cmpb cylinder_count, %ch
373 + jb bdendlp
374 + cmpb $FLOPPY_CYLINDERS,%ch # reach cylinder limit ?
375 + jb bdendlp
376 +next_floppy:
377 + movb $0,%ch # first cylinder
378 + pushaw
379 + movw $swap_floppy,%si
380 + incb 12(%si)
381 + pushw %bx
382 + call puts
383 + popw %bx
384 +waitfloppy:
385 + call wait
386 + jne waitfloppydone
387 + pushw %dx # some bios break dx...
388 + cbw
389 + int $0x13 # reset FDC
390 + movw $0x201,%ax
391 +# cwd
392 +# movw $1,%cx
393 + int $0x13 # read first sector
394 + popw %dx
395 + rclb $1,%ah # floppy changed 06=>0D no error 00
396 + cmpb -2(%si), %ah # 0D then 00
397 + jne waitfloppy # no => try again
398 + incw %si
399 + orb %ah,%ah # was 00 ?
400 + jne waitfloppy
401 +waitfloppydone:
402 + popaw
403 +bdendlp:
404 + xchgw %ax, %bp
405 + movw %cx, %fs
406 +read_sectors:
407 + decw %di
408 +read_one_sector:
409 + movw %fs, %cx
410 +# al is last sector+1
411 +# ah is last cylinder+1
412 + movw %bp, %ax
413 + incw %di
414 + jnz read_sectorslp
415 + pushw %ss
416 + popw %es # restore es
417 + movb $0x2e+3, %al # loading... message 2e = .
418 +putclf:
419 + subb $3, %al
420 +putc:
421 + movb $0xe, %ah
422 + movw $7, %bx # one dot each 64k
423 + int $0x10
424 + cmp $0xd, %al # CR ?
425 + je putclf
426 + ret
427 +
428 +puts:
429 + movb $0xd, %al # CR
430 +putcs:
431 + call putc
432 + lodsb
433 + orb %al,%al # end of string is \0
434 + jnz putcs
435 + ret
436 +
437 +clock = 0x46C
438 +wait:
439 +wait4key:
440 + movw $clock, %di
441 +#define DELAY 5
442 + movb $(DELAY*182)/10,%cl
443 + addb %gs:(%di),%cl
444 +waitkbd:
445 + movw $0x10D, %ax # test keyboard, timeout => CR
446 + cmpb %gs:(%di),%cl
447 + je waitdone
448 + int $0x16
449 + jz waitkbd
450 + cbw
451 + int $0x16 # eat char
452 + movw %di, %gs # disable timeout
453 + incw %di # clear Z
454 +waitdone:
455 + ret
456 +
457 +#ifdef SHOW_REGS
458 +regs: .asciz "X:"
459 +#endif
460 +
461 +swap_floppy: .ascii "Insert disk 1"
462 + .ascii "."
463 + .byte 7,13,0
465 # Kernel attributes; used by setup. This is part 1 of the
466 # header, from the old boot sector.