wok view linux/stuff/linux-header-2.6.30.6.u @ rev 4504

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