wok-current view etherboot/stuff/etherboot-prefix.u @ rev 8854
Up: cherokee to 1.2.1.
author | Christopher Rogers <slaxemulator@gmail.com> |
---|---|
date | Fri Feb 25 02:47:43 2011 +0000 (2011-02-25) |
parents | e0c2f4f235e9 |
children |
line source
1 --- etherboot-5.4.3/src/arch/i386/prefix/liloprefix.S
2 +++ etherboot-5.4.3/src/arch/i386/prefix/liloprefix.S
3 @@ -1,92 +1,377 @@
4 -/*
5 - Copyright (C) 2000, Entity Cyber, Inc.
6 -
7 - Authors: Gary Byers (gb@thinguin.org)
8 - Marty Connor (mdc@thinguin.org)
9 -
10 - This software may be used and distributed according to the terms
11 - of the GNU Public License (GPL), incorporated herein by reference.
12 -
13 - Description:
14 -
15 - This is just a little bit of code and data that can get prepended
16 - to an Etherboot ROM image in order to allow LILO to load the
17 - result as if it were a Linux kernel image.
18 -
19 - A real Linux kernel image consists of a one-sector boot loader
20 - (to load the image from a floppy disk), followed a few sectors
21 - of setup code, followed by the kernel code itself. There's
22 - a table in the first sector (starting at offset 497) that indicates
23 - how many sectors of setup code follow the first sector and which
24 - contains some other parameters that aren't interesting in this
25 - case.
26 -
27 - When LILO loads the sectors that comprise a kernel image, it doesn't
28 - execute the code in the first sector (since that code would try to
29 - load the image from a floppy disk.) The code in the first sector
30 - below doesn't expect to get executed (and prints an error message
31 - if it ever -is- executed.) LILO's only interested in knowing the
32 - number of setup sectors advertised in the table (at offset 497 in
33 - the first sector.)
34 -
35 - Etherboot doesn't require much in the way of setup code.
36 - Historically, the Linux kernel required at least 4 sectors of
37 - setup code. Current versions of LILO look at the byte at
38 - offset 497 in the first sector to indicate how many sectors
39 - of setup code are contained in the image.
40 -
41 -*/
42 +/* SYS_SIZE is the number of clicks (16 bytes) to be loaded. For Etherboot
43 + * purposes, we need to load everything but the boot sector itself, i.e. 32
44 + * clicks less than the size of the entire (verbatim) image. The image size
45 + * is practically limited only by the available base memory size.
46 + */
47 +.globl SYSSIZE
48 +.equ SYSSIZE, _verbatim_size_pgh - 32
49 +
50 +/* floppyload.S Copyright (C) 1991, 1992 Linus Torvalds
51 + * modified by Drew Eckhardt
52 + * modified by Bruce Evans (bde)
53 + *
54 + * floppyprefix.S is loaded at 0x0000:0x7c00 by the bios-startup routines.
55 + *
56 + * It then loads the system at SYSSEG<<4, using BIOS interrupts.
57 + *
58 + * The loader has been made as simple as possible, and continuous read errors
59 + * will result in a unbreakable loop. Reboot by hand. It loads pretty fast by
60 + * getting whole tracks at a time whenever possible.
61 + */
63 #define SETUPSECS 4 /* Minimal nr of setup-sectors */
64 #define PREFIXSIZE ((SETUPSECS+1)*512)
65 #define PREFIXPGH (PREFIXSIZE / 16 )
66 -#define BOOTSEG 0x07C0 /* original address of boot-sector */
67 #define INITSEG 0x9000 /* we move boot here - out of the way */
68 #define SETUPSEG 0x9020 /* setup starts here */
69 -#define SYSSEG 0x1000 /* system loaded at 0x10000 (65536). */
71 - .text
72 - .code16
73 - .arch i386
74 - .org 0
75 - .section ".prefix", "ax", @progbits
76 .globl _prefix
77 _prefix:
78 +.equ BOOTSEG, 0x07C0 /* original address of boot-sector */
80 -/*
81 - This is a minimal boot sector. If anyone tries to execute it (e.g., if
82 - a .lilo file is dd'ed to a floppy), print an error message.
83 -*/
84 +.equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */
85 +
86 + .org 0
87 + .arch i386
88 + .text
89 + .section ".prefix", "ax", @progbits
90 + .code16
91 +
92 + call here
93 +here:
94 + pop %ax
95 + cmpw $0x103, %ax /* COM entry point is cs:0x100 */
96 + jne bootsector
97 +
98 +/* We need a real mode stack that won't be stomped on by Etherboot
99 + which starts at 0x20000. Choose something that's sufficiently high,
100 + but not in DOC territory. Note that we couldn't do this in a real
101 + .com program since stack variables are in the same segment as the
102 + code and data, but this isn't really a .com program, it just looks
103 + like one to make DOS load it into memory. It still has the 64kB
104 + limitation of .com files though. */
105 +#define STACK_SEG 0x7000
106 +#define STACK_SIZE 0x4000
107 + /* Set up temporary stack */
108 + movw $STACK_SEG, %ax
109 + movw %ax, %ss
110 + movw $STACK_SIZE, %sp
111 +
112 + /* Calculate segment address of image start */
113 + pushw %cs
114 + popw %ax
115 + addw $(0x100/16), %ax
116 + jmp go_setup_code
118 -bootsector:
119 - jmp $BOOTSEG, $go - _prefix /* reload cs:ip to match relocation addr */
120 +bootsector:
121 + jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */
122 go:
123 - movw $0x2000, %di /* 0x2000 is arbitrary value >= length
124 - of bootsect + room for stack */
125 + movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */
126 + /* of bootsect + room for stack + 12 for */
127 + /* saved disk parm block */
129 movw $BOOTSEG, %ax
130 movw %ax,%ds
131 movw %ax,%es
132 -
133 - cli
134 - movw %ax, %ss /* put stack at BOOTSEG:0x2000. */
135 + movw %ax,%ss /* put stack at initial position */
136 movw %di,%sp
137 - sti
139 - movw $why_end-why, %cx
140 - movw $why - _prefix, %si
141 +/* Many BIOS's default disk parameter tables will not recognize multi-sector
142 + * reads beyond the maximum sector number specified in the default diskette
143 + * parameter tables - this may mean 7 sectors in some cases.
144 + *
145 + * Since single sector reads are slow and out of the question, we must take care
146 + * of this by creating new parameter tables (for the first disk) in RAM. We
147 + * will set the maximum sector count to 36 - the most we will encounter on an
148 + * ED 2.88. High doesn't hurt. Low does.
149 + *
150 + * Segments are as follows: ds=es=ss=cs - BOOTSEG
151 + */
152 +
153 + xorw %cx,%cx
154 + movw %cx,%es /* access segment 0 */
155 + movw $0x78, %bx /* 0:bx is parameter table address */
156 + pushw %ds /* save ds */
157 +/* 0:bx is parameter table address */
158 + ldsw %es:(%bx),%si /* loads ds and si */
159 +
160 + movw %ax,%es /* ax is BOOTSECT (loaded above) */
161 + movb $6, %cl /* copy 12 bytes */
162 + cld
163 + pushw %di /* keep a copy for later */
164 + rep
165 + movsw /* ds:si is source, es:di is dest */
166 + popw %di
167 +
168 + movb $36,%es:4(%di)
169 +
170 + movw %cx,%ds /* access segment 0 */
171 + xchgw %di,(%bx)
172 + movw %es,%si
173 + xchgw %si,2(%bx)
174 + popw %ds /* restore ds */
175 + movw %di, dpoff /* save old parameters */
176 + movw %si, dpseg /* to restore just before finishing */
177 + pushw %ds
178 + popw %es /* reload es */
179 +
180 +/* Note that es is already set up. Also cx is 0 from rep movsw above. */
181 +
182 + xorb %ah,%ah /* reset FDC */
183 + xorb %dl,%dl
184 + int $0x13
185 +
186 +/* Get disk drive parameters, specifically number of sectors/track.
187 + *
188 + * It seems that there is no BIOS call to get the number of sectors. Guess
189 + * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
190 + * 15 if sector 15 can be read. Otherwise guess 9.
191 + */
193 - movw $0x0007, %bx /* page 0, attribute 7 (normal) */
194 - movb $0x0e, %ah /* write char, tty mode */
195 -prloop:
196 + movw $disksizes, %si /* table of sizes to try */
197 +
198 +probe_loop:
199 lodsb
200 + orb %al, %al
201 + je got_sectors /* if all else fails, try 9 */
202 + cbtw /* extend to word */
203 + movw %ax, sectors
204 + xchgw %cx,%ax /* cx = track and sector */
205 + xorw %dx,%dx /* drive 0, head 0 */
206 + movw $0x0200, %bx /* address after boot sector */
207 + /* (512 bytes from origin, es = cs) */
208 + movw $0x0201, %ax /* service 2, 1 sector */
209 + int $0x13
210 + jc probe_loop /* try next value */
211 +
212 +got_sectors:
213 + movw $msg1end-msg1, %cx
214 + movw $msg1, %si
215 + call print_str
216 +
217 +/* ok, we've written the Loading... message, now we want to load the system */
218 +
219 + pushw %es /* = ds */
220 + movw $SYSSEG, %ax
221 + movw %ax,%es /* segment of SYSSEG<<4 */
222 + pushw %es
223 + call read_it
224 +
225 +/* This turns off the floppy drive motor, so that we enter the kernel in a
226 + * known state, and don't have to worry about it later.
227 + */
228 + movw $0x3f2, %dx
229 + xorb %al,%al
230 + outb %al,%dx
231 +
232 + call print_nl
233 + pop %es /* = SYSSEG */
234 + pop %es /* balance push/pop es */
235 +sigok:
236 +
237 +/* Restore original disk parameters */
238 + movw $0x78, %bx
239 + movw dpoff, %di
240 + movw dpseg, %si
241 + xorw %ax,%ax
242 + movw %ax,%ds
243 + movw %di,(%bx)
244 + movw %si,2(%bx)
245 +
246 +/* after that (everything loaded), we call to the .ROM file loaded. */
247 +
248 + movw $SYSSEG, %ax
249 + jmp go_setup_code
250 +
251 +/* This routine loads the system at address SYSSEG<<4, making sure no 64kB
252 + * boundaries are crossed. We try to load it as fast as possible, loading whole
253 + * tracks whenever we can.
254 + *
255 + * in: es - starting address segment (normally SYSSEG)
256 + */
257 +read_it:
258 + movw $0,sread /* read whole image incl boot sector */
259 + movw %es,%ax
260 + testw $0x0fff, %ax
261 +die: jne die /* es must be at 64kB boundary */
262 + xorw %bx,%bx /* bx is starting address within segment */
263 +rp_read:
264 + movw %es,%ax
265 + movw %bx,%dx
266 + movb $4, %cl
267 + shrw %cl,%dx /* bx is always divisible by 16 */
268 + addw %dx,%ax
269 + cmpw $SYSSEG+SYSSIZE, %ax /* have we loaded all yet? */
270 + jb ok1_read
271 + ret
272 +ok1_read:
273 + movw sectors, %ax
274 + subw sread, %ax
275 + movw %ax,%cx
276 + shlw $9, %cx /* 80186 opcode */
277 + addw %bx,%cx
278 + jnc ok2_read
279 + je ok2_read
280 + xorw %ax,%ax
281 + subw %bx,%ax
282 + shrw $9, %ax /* 80186 opcode */
283 +ok2_read:
284 + call read_track
285 + movw %ax,%cx
286 + addw sread, %ax
287 + cmpw sectors, %ax
288 + jne ok3_read
289 + movw $1, %ax
290 + subw head, %ax
291 + jne ok4_read
292 + incw track
293 +ok4_read:
294 + movw %ax, head
295 + xorw %ax,%ax
296 +ok3_read:
297 + movw %ax, sread
298 + shlw $9, %cx /* 80186 opcode */
299 + addw %cx,%bx
300 + jnc rp_read
301 + movw %es,%ax
302 + addb $0x10, %ah
303 + movw %ax,%es
304 + xorw %bx,%bx
305 + jmp rp_read
306 +
307 +read_track:
308 + pusha /* 80186 opcode */
309 + pushw %ax
310 + pushw %bx
311 + pushw %bp /* just in case the BIOS is buggy */
312 + movb $0x2e, %al /* 0x2e = . */
313 + call print_char
314 + popw %bp
315 + popw %bx
316 + popw %ax
317 +
318 + movw sread, %cx
319 + incw %cx
320 + movb track, %ch
321 + movw $0x0100, %dx
322 + andb head, %dh
323 + movb $2, %ah
324 +
325 + pushw %dx /* save for error dump */
326 + pushw %cx
327 + pushw %bx
328 + pushw %ax
329 +
330 + int $0x13
331 + jc bad_rt
332 + addw $8, %sp
333 + popa /* 80186 opcode */
334 + ret
335 +
336 +bad_rt: pushw %ax /* save error code */
337 + call print_all /* ah = error, al = read */
338 +
339 + xorb %ah,%ah
340 + xorb %dl,%dl
341 + int $0x13
342 +
343 + addw $10, %sp
344 + popa /* 80186 opcode */
345 + jmp read_track
346 +
347 +/* print_all is for debugging purposes. It will print out all of the registers.
348 + * The assumption is that this is called from a routine, with a stack frame like
349 + * dx
350 + * cx
351 + * bx
352 + * ax
353 + * error
354 + * ret <- sp
355 + */
356 +
357 +print_all:
358 + call print_nl /* nl for readability */
359 + /* print_nl update ah and bx */
360 + movw $5, %cx /* error code + 4 registers */
361 + movw %sp,%bp
362 +
363 +print_loop:
364 + pushw %cx /* save count left */
365 +
366 + cmpb $5, %cl
367 + jae no_reg /* see if register name is needed */
368 +
369 + movb $0x5+0x41-1, %al
370 + subb %cl,%al
371 + int $0x10
372 +
373 + movb $0x58, %al /* 'X' */
374 + int $0x10
375 +
376 + movb $0x3A, %al /* ':' */
377 + int $0x10
378 +
379 +no_reg:
380 + addw $2, %bp /* next register */
381 + call print_hex /* print it */
382 + movb $0x20, %al /* print a space */
383 int $0x10
384 + popw %cx
385 + loop print_loop
386 + /* nl for readability */
387 +print_nl:
388 + movb $0xd, %al /* CR */
389 + call print_char
390 + movb $0xa, %al /* LF */
391 + jmp print_char
392 +
393 +
394 +print_str:
395 +prloop:
396 + lodsb
397 + call print_char
398 loop prloop
399 -freeze: jmp freeze
400 + ret
401 +
402 +/* print_hex prints the word pointed to by ss:bp in hexadecimal. */
403 +
404 +print_hex:
405 + movw (%bp),%dx /* load word into dx */
406 + movb $4, %cl
407 + call print_2digits
408 +print_2digits:
409 + call print_digit
410 +/* fall through */
411 +print_digit:
412 + rol %cl,%dx /* rotate to use lowest 4 bits */
413 + movb $0x0f, %al /* mask for nybble */
414 + andb %dl,%al
415 + addb $0x90, %al /* convert al to ascii hex */
416 + daa /* (four instructions) */
417 + adcb $0x40, %al
418 + daa
419 +print_char:
420 + movb $0x0e, %ah /* write char, tty mode */
421 + movw $0x0007, %bx /* page 0, attribute 7 (normal) */
422 + int $0x10
423 + ret
424 +
425 +sread: .word 0 /* sectors read of current track */
426 +head: .word 0 /* current head */
427 +track: .word 0 /* current track */
428 +
429 +sectors:
430 + .word 0
431 +
432 +dpseg: .word 0
433 +dpoff: .word 0
435 -why: .ascii "This image cannot be loaded from a floppy disk.\r\n"
436 -why_end:
437 +disksizes:
438 + .byte 36,18,15,9,0
440 +msg1:
441 + .ascii "Loading ROM image"
442 +msg1end:
444 .org 497
445 setup_sects:
446 @@ -117,15 +402,22 @@
447 whose entry point is SYSSEG:0.
448 */
449 setup_code:
450 - pushl $0 /* No parameters to preserve for exit path */
451 - pushw $0 /* Use prefix exit path mechanism */
452 + movw $(SYSSEG-(PREFIXSIZE/16)), %ax
453 /* Etherboot expects to be contiguous in memory once loaded.
454 * LILO doesn't do this, but since we don't need any
455 * information that's left in the prefix, it doesn't matter:
456 * we just have to ensure that %cs:0000 is where the start of
457 * the Etherboot image *would* be.
458 */
459 - ljmp $(SYSSEG-(PREFIXSIZE/16)), $_start
460 +go_setup_code:
461 + xorw %cx, %cx
462 + pushw %cx
463 + pushw %cx /* No parameters to preserve for exit path */
464 + pushw %cx /* Use prefix exit path mechanism */
465 + pushw %ax
466 + pushw $_start
467 + /* Calculated lcall to _start with %cs:0000 = image start */
468 + lret
470 .section ".text16", "ax", @progbits
471 .globl prefix_exit
473 --- etherboot-5.4.3/src/arch/i386/prefix/bImageprefix.S
474 +++ etherboot-5.4.3/src/arch/i386/prefix/bImageprefix.S
475 @@ -82,6 +82,14 @@
476 #define SIG1 0xAA55
477 #define SIG2 0x5A5A
479 +/* SYS_SIZE is the number of clicks (16 bytes) to be loaded. For Etherboot
480 + * purposes, we need to load everything but the boot sector itself, i.e. 32
481 + * clicks less than the size of the entire (verbatim) image. The image size
482 + * is practically limited only by the available base memory size.
483 + */
484 +.globl SYSSIZE
485 +.equ SYSSIZE, _verbatim_size_pgh - 32
486 +
487 .text
488 .code16
489 .arch i386
490 @@ -90,40 +98,349 @@
491 .globl _prefix
492 _prefix:
494 -/*
495 - This is a minimal boot sector. If anyone tries to execute it (e.g., if
496 - a .lilo file is dd'ed to a floppy), print an error message.
497 -*/
498 + call here
499 +here:
500 + pop %ax
501 + cmpw $0x103, %ax /* COM entry point is cs:0x100 */
502 + jne bootsector
503 +
504 +/* We need a real mode stack that won't be stomped on by Etherboot
505 + which starts at 0x20000. Choose something that's sufficiently high,
506 + but not in DOC territory. Note that we couldn't do this in a real
507 + .com program since stack variables are in the same segment as the
508 + code and data, but this isn't really a .com program, it just looks
509 + like one to make DOS load it into memory. It still has the 64kB
510 + limitation of .com files though. */
511 +#define STACK_SEG 0x7000
512 +#define STACK_SIZE 0x4000
513 + /* Set up temporary stack */
514 + movw $STACK_SEG, %ax
515 + movw %ax, %ss
516 + movw $STACK_SIZE, %sp
517 +
518 + /* Calculate segment address of image start */
519 + pushw %cs
520 + popw %ax
521 + addw $(0x100/16), %ax
522 + jmp go_setup_code
524 -bootsector:
525 - jmp $BOOTSEG, $go - _prefix /* reload cs:ip to match relocation addr */
526 +bootsector:
527 + jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */
528 go:
529 - movw $0x2000, %di /* 0x2000 is arbitrary value >= length
530 - of bootsect + room for stack */
531 + movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */
532 + /* of bootsect + room for stack + 12 for */
533 + /* saved disk parm block */
535 movw $BOOTSEG, %ax
536 movw %ax,%ds
537 movw %ax,%es
538 -
539 - cli
540 - movw %ax, %ss /* put stack at BOOTSEG:0x2000. */
541 + movw %ax,%ss /* put stack at initial position */
542 movw %di,%sp
543 - sti
545 - movw $why_end-why, %cx
546 - movw $why - _prefix, %si
547 +/* Many BIOS's default disk parameter tables will not recognize multi-sector
548 + * reads beyond the maximum sector number specified in the default diskette
549 + * parameter tables - this may mean 7 sectors in some cases.
550 + *
551 + * Since single sector reads are slow and out of the question, we must take care
552 + * of this by creating new parameter tables (for the first disk) in RAM. We
553 + * will set the maximum sector count to 36 - the most we will encounter on an
554 + * ED 2.88. High doesn't hurt. Low does.
555 + *
556 + * Segments are as follows: ds=es=ss=cs - BOOTSEG
557 + */
558 +
559 + xorw %cx,%cx
560 + movw %cx,%es /* access segment 0 */
561 + movw $0x78, %bx /* 0:bx is parameter table address */
562 + pushw %ds /* save ds */
563 +/* 0:bx is parameter table address */
564 + ldsw %es:(%bx),%si /* loads ds and si */
565 +
566 + movw %ax,%es /* ax is BOOTSECT (loaded above) */
567 + movb $6, %cl /* copy 12 bytes */
568 + cld
569 + pushw %di /* keep a copy for later */
570 + rep
571 + movsw /* ds:si is source, es:di is dest */
572 + popw %di
574 - movw $0x0007, %bx /* page 0, attribute 7 (normal) */
575 - movb $0x0e, %ah /* write char, tty mode */
576 -prloop:
577 + movb $36,%es:4(%di)
578 +
579 + movw %cx,%ds /* access segment 0 */
580 + xchgw %di,(%bx)
581 + movw %es,%si
582 + xchgw %si,2(%bx)
583 + popw %ds /* restore ds */
584 + movw %di, dpoff /* save old parameters */
585 + movw %si, dpseg /* to restore just before finishing */
586 + pushw %ds
587 + popw %es /* reload es */
588 +
589 +/* Note that es is already set up. Also cx is 0 from rep movsw above. */
590 +
591 + xorb %ah,%ah /* reset FDC */
592 + xorb %dl,%dl
593 + int $0x13
594 +
595 +/* Get disk drive parameters, specifically number of sectors/track.
596 + *
597 + * It seems that there is no BIOS call to get the number of sectors. Guess
598 + * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
599 + * 15 if sector 15 can be read. Otherwise guess 9.
600 + */
601 +
602 + movw $disksizes, %si /* table of sizes to try */
603 +
604 +probe_loop:
605 lodsb
606 + orb %al, %al
607 + je got_sectors /* if all else fails, try 9 */
608 + cbtw /* extend to word */
609 + movw %ax, sectors
610 + xchgw %cx,%ax /* cx = track and sector */
611 + xorw %dx,%dx /* drive 0, head 0 */
612 + movw $0x0200, %bx /* address after boot sector */
613 + /* (512 bytes from origin, es = cs) */
614 + movw $0x0201, %ax /* service 2, 1 sector */
615 + int $0x13
616 + jc probe_loop /* try next value */
617 +
618 +got_sectors:
619 + movw $msg1end-msg1, %cx
620 + movw $msg1, %si
621 + call print_str
622 +
623 +/* ok, we've written the Loading... message, now we want to load the system */
624 +
625 + pushw %es /* = ds */
626 + movw $SYSSEG, %ax
627 + movw %ax,%es /* segment of SYSSEG<<4 */
628 + pushw %es
629 + call read_it
630 +
631 +/* This turns off the floppy drive motor, so that we enter the kernel in a
632 + * known state, and don't have to worry about it later.
633 + */
634 + movw $0x3f2, %dx
635 + xorb %al,%al
636 + outb %al,%dx
637 +
638 + call print_nl
639 + pop %es /* = SYSSEG */
640 + pop %es /* balance push/pop es */
641 +sigok:
642 +
643 +/* Restore original disk parameters */
644 + movw $0x78, %bx
645 + movw dpoff, %di
646 + movw dpseg, %si
647 + xorw %ax,%ax
648 + movw %ax,%ds
649 + movw %di,(%bx)
650 + movw %si,2(%bx)
651 +
652 +/* after that (everything loaded), we call to the .ROM file loaded. */
653 +
654 + movw $SYSSEG, %ax
655 +go_setup_code:
656 + xorw %cx, %cx
657 + pushw %cx
658 + pushw %cx /* No parameters to preserve for exit path */
659 + pushw %cx /* Use prefix exit path mechanism */
660 + pushw %ax
661 + pushw $_start
662 + /* Calculated lcall to _start with %cs:0000 = image start */
663 + lret
664 +
665 +/* This routine loads the system at address SYSSEG<<4, making sure no 64kB
666 + * boundaries are crossed. We try to load it as fast as possible, loading whole
667 + * tracks whenever we can.
668 + *
669 + * in: es - starting address segment (normally SYSSEG)
670 + */
671 +read_it:
672 + movw $0,sread /* read whole image incl boot sector */
673 + movw %es,%ax
674 + testw $0x0fff, %ax
675 +die: jne die /* es must be at 64kB boundary */
676 + xorw %bx,%bx /* bx is starting address within segment */
677 +rp_read:
678 + movw %es,%ax
679 + movw %bx,%dx
680 + movb $4, %cl
681 + shrw %cl,%dx /* bx is always divisible by 16 */
682 + addw %dx,%ax
683 + cmpw $SYSSEG+SYSSIZE, %ax /* have we loaded all yet? */
684 + jb ok1_read
685 + ret
686 +ok1_read:
687 + movw sectors, %ax
688 + subw sread, %ax
689 + movw %ax,%cx
690 + shlw $9, %cx /* 80186 opcode */
691 + addw %bx,%cx
692 + jnc ok2_read
693 + je ok2_read
694 + xorw %ax,%ax
695 + subw %bx,%ax
696 + shrw $9, %ax /* 80186 opcode */
697 +ok2_read:
698 + call read_track
699 + movw %ax,%cx
700 + addw sread, %ax
701 + cmpw sectors, %ax
702 + jne ok3_read
703 + movw $1, %ax
704 + subw head, %ax
705 + jne ok4_read
706 + incw track
707 +ok4_read:
708 + movw %ax, head
709 + xorw %ax,%ax
710 +ok3_read:
711 + movw %ax, sread
712 + shlw $9, %cx /* 80186 opcode */
713 + addw %cx,%bx
714 + jnc rp_read
715 + movw %es,%ax
716 + addb $0x10, %ah
717 + movw %ax,%es
718 + xorw %bx,%bx
719 + jmp rp_read
720 +
721 +read_track:
722 + pusha /* 80186 opcode */
723 + pushw %ax
724 + pushw %bx
725 + pushw %bp /* just in case the BIOS is buggy */
726 + movb $0x2e, %al /* 0x2e = . */
727 + call print_char
728 + popw %bp
729 + popw %bx
730 + popw %ax
731 +
732 + movw sread, %cx
733 + incw %cx
734 + movb track, %ch
735 + movw $0x0100, %dx
736 + andb head, %dh
737 + movb $2, %ah
738 +
739 + pushw %dx /* save for error dump */
740 + pushw %cx
741 + pushw %bx
742 + pushw %ax
743 +
744 + int $0x13
745 + jc bad_rt
746 + addw $8, %sp
747 + popa /* 80186 opcode */
748 + ret
749 +
750 +bad_rt: pushw %ax /* save error code */
751 + call print_all /* ah = error, al = read */
752 +
753 + xorb %ah,%ah
754 + xorb %dl,%dl
755 + int $0x13
756 +
757 + addw $10, %sp
758 + popa /* 80186 opcode */
759 + jmp read_track
760 +
761 +/* print_all is for debugging purposes. It will print out all of the registers.
762 + * The assumption is that this is called from a routine, with a stack frame like
763 + * dx
764 + * cx
765 + * bx
766 + * ax
767 + * error
768 + * ret <- sp
769 + */
770 +
771 +print_all:
772 + call print_nl /* nl for readability */
773 + /* print_nl update ah and bx */
774 + movw $5, %cx /* error code + 4 registers */
775 + movw %sp,%bp
776 +
777 +print_loop:
778 + pushw %cx /* save count left */
779 +
780 + cmpb $5, %cl
781 + jae no_reg /* see if register name is needed */
782 +
783 + movb $0x5+0x41-1, %al
784 + subb %cl,%al
785 int $0x10
786 +
787 + movb $0x58, %al /* 'X' */
788 + int $0x10
789 +
790 + movb $0x3A, %al /* ':' */
791 + int $0x10
792 +
793 +no_reg:
794 + addw $2, %bp /* next register */
795 + call print_hex /* print it */
796 + movb $0x20, %al /* print a space */
797 + int $0x10
798 + popw %cx
799 + loop print_loop
800 + /* nl for readability */
801 +print_nl:
802 + movb $0xd, %al /* CR */
803 + call print_char
804 + movb $0xa, %al /* LF */
805 + jmp print_char
806 +
807 +
808 +print_str:
809 +prloop:
810 + lodsb
811 + call print_char
812 loop prloop
813 -freeze: jmp freeze
814 + ret
816 -why: .ascii "This image cannot be loaded from a floppy disk.\r\n"
817 -why_end:
818 +/* print_hex prints the word pointed to by ss:bp in hexadecimal. */
819 +
820 +print_hex:
821 + movw (%bp),%dx /* load word into dx */
822 + movb $4, %cl
823 + call print_2digits
824 +print_2digits:
825 + call print_digit
826 +/* fall through */
827 +print_digit:
828 + rol %cl,%dx /* rotate to use lowest 4 bits */
829 + movb $0x0f, %al /* mask for nybble */
830 + andb %dl,%al
831 + addb $0x90, %al /* convert al to ascii hex */
832 + daa /* (four instructions) */
833 + adcb $0x40, %al
834 + daa
835 +print_char:
836 + movb $0x0e, %ah /* write char, tty mode */
837 + movw $0x0007, %bx /* page 0, attribute 7 (normal) */
838 + int $0x10
839 + ret
841 +sread: .word 0 /* sectors read of current track */
842 +head: .word 0 /* current head */
843 +track: .word 0 /* current track */
844 +
845 +sectors:
846 + .word 0
847 +
848 +dpseg: .word 0
849 +dpoff: .word 0
850 +
851 +disksizes:
852 + .byte 36,18,15,9,0
853 +
854 +msg1:
855 + .ascii "Loading ROM image"
856 +msg1end:
858 .org 497
859 setup_sects: