wok view gpxe/stuff/prefix.u @ rev 955

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