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