wok-current view gpxe/stuff/prefix.u @ rev 7658
Up: mysql to 5.1.54.
author | Christopher Rogers <slaxemulator@gmail.com> |
---|---|
date | Wed Dec 15 20:31:38 2010 +0000 (2010-12-15) |
parents | a9ff8c135e36 |
children |
line source
1 --- gpxe-0.9.3/src/arch/i386/prefix/lkrnprefix.S
2 +++ gpxe-0.9.3/src/arch/i386/prefix/lkrnprefix.S
3 @@ -3,6 +3,7 @@
5 Authors: Gary Byers (gb@thinguin.org)
6 Marty Connor (mdc@thinguin.org)
7 + Pascal Bellard (pascal.bellard@slitaz.org)
9 This software may be used and distributed according to the terms
10 of the GNU Public License (GPL), incorporated herein by reference.
11 @@ -50,40 +51,351 @@
12 .arch i386
13 .org 0
14 .section ".prefix", "ax", @progbits
15 -/*
16 - This is a minimal boot sector. If anyone tries to execute it (e.g., if
17 - a .lilo file is dd'ed to a floppy), print an error message.
18 -*/
20 -bootsector:
21 - jmp $BOOTSEG, $1f /* reload cs:ip to match relocation addr */
22 -1:
23 - movw $0x2000, %di /* 0x2000 is arbitrary value >= length
24 - of bootsect + room for stack */
25 + call here
26 +here:
27 + pop %ax
28 + cmpw $0x103, %ax /* COM entry point is cs:0x100 */
29 + jne bootsector
30 +
31 +/* We need a real mode stack that won't be stomped on by Etherboot
32 + which starts at 0x20000. Choose something that's sufficiently high,
33 + but not in DOC territory. Note that we couldn't do this in a real
34 + .com program since stack variables are in the same segment as the
35 + code and data, but this isn't really a .com program, it just looks
36 + like one to make DOS load it into memory. It still has the 64kB
37 + limitation of .com files though. */
38 +#define STACK_SEG 0x7000
39 +#define STACK_SIZE 0x4000
40 + /* Set up temporary stack */
41 + movw $STACK_SEG, %ax
42 + movw %ax, %ss
43 + movw $STACK_SIZE, %sp
44 +
45 + /* Calculate segment address of image start */
46 + pushw %cs
47 + popw %ax
48 + addw $(0x100/16), %ax /* Adjust cs */
49 + pushw %ax
50 + jmp go_setup_code
51 +
52 +bootsector:
53 + jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */
54 +go:
55 + movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */
56 + /* of bootsect + room for stack + 12 for */
57 + /* saved disk parm block */
59 movw $BOOTSEG, %ax
60 movw %ax,%ds
61 movw %ax,%es
62 -
63 - cli
64 - movw %ax, %ss /* put stack at BOOTSEG:0x2000. */
65 + movw %ax,%ss /* put stack at initial position */
66 movw %di,%sp
67 - sti
69 - movw $why_end-why, %cx
70 - movw $why, %si
71 +/* Many BIOS's default disk parameter tables will not recognize multi-sector
72 + * reads beyond the maximum sector number specified in the default diskette
73 + * parameter tables - this may mean 7 sectors in some cases.
74 + *
75 + * Since single sector reads are slow and out of the question, we must take care
76 + * of this by creating new parameter tables (for the first disk) in RAM. We
77 + * will set the maximum sector count to 36 - the most we will encounter on an
78 + * ED 2.88. High doesn't hurt. Low does.
79 + *
80 + * Segments are as follows: ds=es=ss=cs - BOOTSEG
81 + */
82 +
83 + xorw %cx,%cx
84 + movw %cx,%es /* access segment 0 */
85 + movw $0x78, %bx /* 0:bx is parameter table address */
86 + pushw %ds /* save ds */
87 +/* 0:bx is parameter table address */
88 + ldsw %es:(%bx),%si /* loads ds and si */
89 +
90 + movw %ax,%es /* ax is BOOTSECT (loaded above) */
91 + movb $6, %cl /* copy 12 bytes */
92 + cld
93 + pushw %di /* keep a copy for later */
94 + rep
95 + movsw /* ds:si is source, es:di is dest */
96 + popw %di
97 +
98 + movb $36,%es:4(%di)
99 +
100 + movw %cx,%ds /* access segment 0 */
101 + xchgw %di,(%bx)
102 + movw %es,%si
103 + xchgw %si,2(%bx)
104 + popw %ds /* restore ds */
105 + movw %di, dpoff /* save old parameters */
106 + movw %si, dpseg /* to restore just before finishing */
107 + pushw %ds
108 + popw %es /* reload es */
109 +
110 +/* Note that es is already set up. Also cx is 0 from rep movsw above. */
111 +
112 + xorb %ah,%ah /* reset FDC */
113 + xorb %dl,%dl
114 + int $0x13
115 +
116 +/* Get disk drive parameters, specifically number of sectors/track.
117 + *
118 + * It seems that there is no BIOS call to get the number of sectors. Guess
119 + * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
120 + * 15 if sector 15 can be read. Otherwise guess 9.
121 + */
123 - movw $0x0007, %bx /* page 0, attribute 7 (normal) */
124 - movb $0x0e, %ah /* write char, tty mode */
125 -prloop:
126 + movw $disksizes, %si /* table of sizes to try */
127 +
128 +probe_loop:
129 lodsb
130 + orb %al, %al
131 + je got_sectors /* if all else fails, try 9 */
132 + cbtw /* extend to word */
133 + movw %ax, sectors
134 + xchgw %cx,%ax /* cx = track and sector */
135 + xorw %dx,%dx /* drive 0, head 0 */
136 + movw $0x0200, %bx /* address after boot sector */
137 + /* (512 bytes from origin, es = cs) */
138 + movw $0x0201, %ax /* service 2, 1 sector */
139 + int $0x13
140 + jc probe_loop /* try next value */
141 +
142 +got_sectors:
143 + movw $msg1end-msg1, %cx
144 + movw $msg1, %si
145 + call print_str
146 +
147 +/* ok, we've written the Loading... message, now we want to load the system */
148 +
149 + movw $SYSSEG, %ax
150 + movw %ax,%es /* segment of SYSSEG<<4 */
151 + pushw %es
152 + call read_it
153 +
154 +/* This turns off the floppy drive motor, so that we enter the kernel in a
155 + * known state, and don't have to worry about it later.
156 + */
157 + movw $0x3f2, %dx
158 + xorb %al,%al
159 + outb %al,%dx
160 +
161 + call print_nl
162 + pop %es /* = SYSSEG */
163 +sigok:
164 +
165 +/* Restore original disk parameters */
166 + movw $0x78, %bx
167 + movw dpoff, %di
168 + movw dpseg, %si
169 + xorw %ax,%ax
170 + movw %ax,%ds
171 + movw %di,(%bx)
172 + movw %si,2(%bx)
173 +
174 + /* Everything now loaded. %es = SYSSEG, so %es:0000 points to
175 + * start of loaded image.
176 + */
177 +
178 + /* Jump to loaded copy */
179 + ljmp $SYSSEG, $run_etherboot
180 +
181 +endseg: .word SYSSEG + _load_size_pgh
182 + .section ".zinfo.fixup", "a" /* Compressor fixup information */
183 + .ascii "SUBW"
184 + .long endseg
185 + .long 16
186 + .long 0
187 + .previous
188 +
189 +/* This routine loads the system at address SYSSEG<<4, making sure no 64kB
190 + * boundaries are crossed. We try to load it as fast as possible, loading whole
191 + * tracks whenever we can.
192 + *
193 + * in: es - starting address segment (normally SYSSEG)
194 + */
195 +read_it:
196 + movw $0,sread /* read whole image incl boot sector */
197 + movw %es,%ax
198 + testw $0x0fff, %ax
199 +die: jne die /* es must be at 64kB boundary */
200 + xorw %bx,%bx /* bx is starting address within segment */
201 +rp_read:
202 + movw %es,%ax
203 + movw %bx,%dx
204 + movb $4, %cl
205 + shrw %cl,%dx /* bx is always divisible by 16 */
206 + addw %dx,%ax
207 + cmpw syssize, %ax /* have we loaded all yet? */
208 + jb ok1_read
209 + ret
210 +ok1_read:
211 + movw sectors, %ax
212 + subw sread, %ax
213 + movw %ax,%cx
214 + shlw $9, %cx /* 80186 opcode */
215 + addw %bx,%cx
216 + jnc ok2_read
217 + je ok2_read
218 + xorw %ax,%ax
219 + subw %bx,%ax
220 + shrw $9, %ax /* 80186 opcode */
221 +ok2_read:
222 + call read_track
223 + movw %ax,%cx
224 + addw sread, %ax
225 + cmpw sectors, %ax
226 + jne ok3_read
227 + movw $1, %ax
228 + subw head, %ax
229 + jne ok4_read
230 + incw track
231 +ok4_read:
232 + movw %ax, head
233 + xorw %ax,%ax
234 +ok3_read:
235 + movw %ax, sread
236 + shlw $9, %cx /* 80186 opcode */
237 + addw %cx,%bx
238 + jnc rp_read
239 + movw %es,%ax
240 + addb $0x10, %ah
241 + movw %ax,%es
242 + xorw %bx,%bx
243 + jmp rp_read
244 +
245 +read_track:
246 + pusha /* 80186 opcode */
247 + pushw %ax
248 + pushw %bx
249 + pushw %bp /* just in case the BIOS is buggy */
250 + movb $0x2e, %al /* 0x2e = . */
251 + call print_char
252 + popw %bp
253 + popw %bx
254 + popw %ax
255 +
256 + movw sread, %cx
257 + incw %cx
258 + movb track, %ch
259 + movw $0x0100, %dx
260 + andb head, %dh
261 + movb $2, %ah
262 +
263 + pushw %dx /* save for error dump */
264 + pushw %cx
265 + pushw %bx
266 + pushw %ax
267 +
268 + int $0x13
269 + jc bad_rt
270 + addw $8, %sp
271 + popa /* 80186 opcode */
272 + ret
273 +
274 +bad_rt: pushw %ax /* save error code */
275 + call print_all /* ah = error, al = read */
276 +
277 + xorb %ah,%ah
278 + xorb %dl,%dl
279 + int $0x13
280 +
281 + addw $10, %sp
282 + popa /* 80186 opcode */
283 + jmp read_track
284 +
285 +/* print_all is for debugging purposes. It will print out all of the registers.
286 + * The assumption is that this is called from a routine, with a stack frame like
287 + * dx
288 + * cx
289 + * bx
290 + * ax
291 + * error
292 + * ret <- sp
293 + */
294 +
295 +print_all:
296 + call print_nl /* nl for readability */
297 + /* print_nl update ah and bx */
298 + movw $5, %cx /* error code + 4 registers */
299 + movw %sp,%bp
300 +
301 +print_loop:
302 + pushw %cx /* save count left */
303 +
304 + cmpb $5, %cl
305 + jae no_reg /* see if register name is needed */
306 +
307 + movb $0x5+0x41-1, %al
308 + subb %cl,%al
309 + int $0x10
310 +
311 + movb $0x58, %al /* 'X' */
312 int $0x10
313 +
314 + movb $0x3A, %al /* ':' */
315 + int $0x10
316 +
317 +no_reg:
318 + addw $2, %bp /* next register */
319 + call print_hex /* print it */
320 + movb $0x20, %al /* print a space */
321 + int $0x10
322 + popw %cx
323 + loop print_loop
324 + /* nl for readability */
325 +print_nl:
326 + movb $0xd, %al /* CR */
327 + call print_char
328 + movb $0xa, %al /* LF */
329 + jmp print_char
330 +
331 +
332 +print_str:
333 +prloop:
334 + lodsb
335 + call print_char
336 loop prloop
337 -freeze: jmp freeze
338 + ret
340 -why: .ascii "This image cannot be loaded from a floppy disk.\r\n"
341 -why_end:
342 +/* print_hex prints the word pointed to by ss:bp in hexadecimal. */
344 +print_hex:
345 + movw (%bp),%dx /* load word into dx */
346 + movb $4, %cl
347 + call print_2digits
348 +print_2digits:
349 + call print_digit
350 +/* fall through */
351 +print_digit:
352 + rol %cl,%dx /* rotate to use lowest 4 bits */
353 + movb $0x0f, %al /* mask for nybble */
354 + andb %dl,%al
355 + addb $0x90, %al /* convert al to ascii hex */
356 + daa /* (four instructions) */
357 + adcb $0x40, %al
358 + daa
359 +print_char:
360 + movb $0x0e, %ah /* write char, tty mode */
361 + movw $0x0007, %bx /* page 0, attribute 7 (normal) */
362 + int $0x10
363 + ret
364 +
365 +sread: .word 0 /* sectors read of current track */
366 +head: .word 0 /* current head */
367 +track: .word 0 /* current track */
368 +
369 +sectors:
370 + .word 0
371 +
372 +dpseg: .word 0
373 +dpoff: .word 0
374 +
375 +disksizes:
376 + .byte 36,18,15,9,0
377 +
378 +msg1:
379 + .ascii "Loading ROM image"
380 +msg1end:
382 .org 497
383 setup_sects:
384 @@ -106,13 +418,6 @@
386 .org 512
388 - .section ".zinfo.fixup", "a" /* Compressor fixup information */
389 - .ascii "SUBW"
390 - .long syssize
391 - .long 16
392 - .long 0
393 - .previous
394 -
395 /*
396 We're now at the beginning of the second sector of the image -
397 where the setup code goes.
398 @@ -123,14 +428,18 @@
399 executing the Etherboot image that's loaded at SYSSEG:0 and
400 whose entry point is SYSSEG:0.
401 */
402 -setup_code:
403 +setup_code:
404 + pushw $(SYSSEG-(PREFIXSIZE/16))
405 /* Etherboot expects to be contiguous in memory once loaded.
406 * LILO doesn't do this, but since we don't need any
407 * information that's left in the prefix, it doesn't matter:
408 * we just have to ensure that %cs:0000 is where the start of
409 * the Etherboot image *would* be.
410 */
411 - ljmp $(SYSSEG-(PREFIXSIZE/16)), $run_etherboot
412 +go_setup_code:
413 + pushw $run_etherboot
414 + /* Calculated lcall to _start with %cs:0000 = image start */
415 + lret
418 .org PREFIXSIZE
419 @@ -140,6 +449,10 @@
420 run_etherboot:
421 call install
423 + /* Set up real-mode stack */
424 + movw %bx, %ss
425 + movw $_estack16, %sp
426 +
427 /* Jump to .text16 segment */
428 pushw %ax
429 pushw $1f