VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/Etherboot-src/arch/i386/prefix/floppyprefix.S@ 16444

Last change on this file since 16444 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.2 KB
Line 
1/* NOTE: this boot sector contains instructions that need at least an 80186.
2 * Yes, as86 has a bug somewhere in the valid instruction set checks.
3 *
4 * SYS_SIZE is the number of clicks (16 bytes) to be loaded. For Etherboot
5 * purposes, we need to load everything but the boot sector itself, i.e. 32
6 * clicks less than the size of the entire (verbatim) image. The image size
7 * is practically limited only by the available base memory size.
8 */
9.globl SYSSIZE
10.equ SYSSIZE, _verbatim_size_pgh - 32
11
12/* floppyload.S Copyright (C) 1991, 1992 Linus Torvalds
13 * modified by Drew Eckhardt
14 * modified by Bruce Evans (bde)
15 *
16 * floppyprefix.S is loaded at 0x0000:0x7c00 by the bios-startup routines.
17 *
18 * It then loads the system at SYSSEG<<4, using BIOS interrupts.
19 *
20 * The loader has been made as simple as possible, and continuous read errors
21 * will result in a unbreakable loop. Reboot by hand. It loads pretty fast by
22 * getting whole tracks at a time whenever possible.
23 */
24
25.equ BOOTSEG, 0x07C0 /* original address of boot-sector */
26
27.equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */
28
29 .org 0
30 .arch i386
31 .text
32 .section ".prefix", "ax", @progbits
33 .code16
34
35 jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */
36go:
37 movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */
38 /* of bootsect + room for stack + 12 for */
39 /* saved disk parm block */
40
41 movw $BOOTSEG, %ax
42 movw %ax,%ds
43 movw %ax,%es
44 movw %ax,%ss /* put stack at initial position */
45 movw %di,%sp
46
47/* Many BIOS's default disk parameter tables will not recognize multi-sector
48 * reads beyond the maximum sector number specified in the default diskette
49 * parameter tables - this may mean 7 sectors in some cases.
50 *
51 * Since single sector reads are slow and out of the question, we must take care
52 * of this by creating new parameter tables (for the first disk) in RAM. We
53 * will set the maximum sector count to 36 - the most we will encounter on an
54 * ED 2.88. High doesn't hurt. Low does.
55 *
56 * Segments are as follows: ds=es=ss=cs - BOOTSEG
57 */
58
59 xorw %cx,%cx
60 movw %cx,%es /* access segment 0 */
61 movw $0x78, %bx /* 0:bx is parameter table address */
62 pushw %ds /* save ds */
63/* 0:bx is parameter table address */
64 ldsw %es:(%bx),%si /* loads ds and si */
65
66 movw %ax,%es /* ax is BOOTSECT (loaded above) */
67 movb $6, %cl /* copy 12 bytes */
68 cld
69 pushw %di /* keep a copy for later */
70 rep
71 movsw /* ds:si is source, es:di is dest */
72 popw %di
73
74 movb $36,%es:4(%di)
75
76 movw %cx,%ds /* access segment 0 */
77 xchgw %di,(%bx)
78 movw %es,%si
79 xchgw %si,2(%bx)
80 popw %ds /* restore ds */
81 movw %di, dpoff /* save old parameters */
82 movw %si, dpseg /* to restore just before finishing */
83 pushw %ds
84 popw %es /* reload es */
85
86/* Note that es is already set up. Also cx is 0 from rep movsw above. */
87
88 xorb %ah,%ah /* reset FDC */
89 xorb %dl,%dl
90 int $0x13
91
92/* Get disk drive parameters, specifically number of sectors/track.
93 *
94 * It seems that there is no BIOS call to get the number of sectors. Guess
95 * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
96 * 15 if sector 15 can be read. Otherwise guess 9.
97 */
98
99 movw $disksizes, %si /* table of sizes to try */
100
101probe_loop:
102 lodsb
103 cbtw /* extend to word */
104 movw %ax, sectors
105 cmpw $disksizes+4, %si
106 jae got_sectors /* if all else fails, try 9 */
107 xchgw %cx,%ax /* cx = track and sector */
108 xorw %dx,%dx /* drive 0, head 0 */
109 movw $0x0200, %bx /* address after boot sector */
110 /* (512 bytes from origin, es = cs) */
111 movw $0x0201, %ax /* service 2, 1 sector */
112 int $0x13
113 jc probe_loop /* try next value */
114
115got_sectors:
116 movw $msg1end-msg1, %cx
117 movw $msg1, %si
118 call print_str
119
120/* ok, we've written the Loading... message, now we want to load the system */
121
122 pushw %es /* = ds */
123 movw $SYSSEG, %ax
124 movw %ax,%es /* segment of SYSSEG<<4 */
125 pushw %es
126 call read_it
127
128/* This turns off the floppy drive motor, so that we enter the kernel in a
129 * known state, and don't have to worry about it later.
130 */
131 movw $0x3f2, %dx
132 xorb %al,%al
133 outb %al,%dx
134
135 call print_nl
136 pop %es /* = SYSSEG */
137 pop %es /* balance push/pop es */
138sigok:
139
140/* Restore original disk parameters */
141 movw $0x78, %bx
142 movw dpoff, %di
143 movw dpseg, %si
144 xorw %ax,%ax
145 movw %ax,%ds
146 movw %di,(%bx)
147 movw %si,2(%bx)
148
149/* after that (everything loaded), we call to the .ROM file loaded. */
150
151 pushl $0 /* No parameters to preserve for exit path */
152 pushw $0 /* Use prefix exit path mechanism */
153 ljmp $SYSSEG, $_start
154
155 .section ".text16", "ax", @progbits
156 .globl prefix_exit
157prefix_exit:
158 xchgw %bx, %bx
159 int $0x18 /* should try to boot machine */
160 .globl prefix_exit_end
161prefix_exit_end:
162 .previous
163
164/* This routine loads the system at address SYSSEG<<4, making sure no 64kB
165 * boundaries are crossed. We try to load it as fast as possible, loading whole
166 * tracks whenever we can.
167 *
168 * in: es - starting address segment (normally SYSSEG)
169 */
170read_it:
171 movw $0,sread /* read whole image incl boot sector */
172 movw %es,%ax
173 testw $0x0fff, %ax
174die: jne die /* es must be at 64kB boundary */
175 xorw %bx,%bx /* bx is starting address within segment */
176rp_read:
177 movw %es,%ax
178 movw %bx,%dx
179 movb $4, %cl
180 shrw %cl,%dx /* bx is always divisible by 16 */
181 addw %dx,%ax
182 cmpw $SYSSEG+SYSSIZE, %ax /* have we loaded all yet? */
183 jb ok1_read
184 ret
185ok1_read:
186 movw sectors, %ax
187 subw sread, %ax
188 movw %ax,%cx
189 shlw $9, %cx
190 addw %bx,%cx
191 jnc ok2_read
192 je ok2_read
193 xorw %ax,%ax
194 subw %bx,%ax
195 shrw $9, %ax
196ok2_read:
197 call read_track
198 movw %ax,%cx
199 addw sread, %ax
200 cmpw sectors, %ax
201 jne ok3_read
202 movw $1, %ax
203 subw head, %ax
204 jne ok4_read
205 incw track
206ok4_read:
207 movw %ax, head
208 xorw %ax,%ax
209ok3_read:
210 movw %ax, sread
211 shlw $9, %cx
212 addw %cx,%bx
213 jnc rp_read
214 movw %es,%ax
215 addb $0x10, %ah
216 movw %ax,%es
217 xorw %bx,%bx
218 jmp rp_read
219
220read_track:
221 pusha
222 pushw %ax
223 pushw %bx
224 pushw %bp /* just in case the BIOS is buggy */
225 movw $0x0e2e, %ax /* 0x2e = . */
226 movw $0x0007, %bx
227 int $0x10
228 popw %bp
229 popw %bx
230 popw %ax
231
232 movw track, %dx
233 movw sread, %cx
234 incw %cx
235 movb %dl,%ch
236 movw head, %dx
237 movb %dl,%dh
238 andw $0x0100, %dx
239 movb $2, %ah
240
241 pushw %dx /* save for error dump */
242 pushw %cx
243 pushw %bx
244 pushw %ax
245
246 int $0x13
247 jc bad_rt
248 addw $8, %sp
249 popa
250 ret
251
252bad_rt: pushw %ax /* save error code */
253 call print_all /* ah = error, al = read */
254
255 xorb %ah,%ah
256 xorb %dl,%dl
257 int $0x13
258
259 addw $10, %sp
260 popa
261 jmp read_track
262
263/* print_all is for debugging purposes. It will print out all of the registers.
264 * The assumption is that this is called from a routine, with a stack frame like
265 * dx
266 * cx
267 * bx
268 * ax
269 * error
270 * ret <- sp
271 */
272
273print_all:
274 call print_nl /* nl for readability */
275 movw $5, %cx /* error code + 4 registers */
276 movw %sp,%bp
277
278print_loop:
279 pushw %cx /* save count left */
280
281 cmpb $5, %cl
282 jae no_reg /* see if register name is needed */
283
284 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
285 movw $0xe05+0x41-1, %ax
286 subb %cl,%al
287 int $0x10
288
289 movb $0x58, %al /* 'X' */
290 int $0x10
291
292 movb $0x3A, %al /* ':' */
293 int $0x10
294
295no_reg:
296 addw $2, %bp /* next register */
297 call print_hex /* print it */
298 movb $0x20, %al /* print a space */
299 int $0x10
300 popw %cx
301 loop print_loop
302 call print_nl /* nl for readability */
303 ret
304
305print_str:
306 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
307 movb $0x0e, %ah /* write char, tty mode */
308prloop:
309 lodsb
310 int $0x10
311 loop prloop
312 ret
313
314print_nl:
315 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
316 movw $0xe0d, %ax /* CR */
317 int $0x10
318 movb $0xa, %al /* LF */
319 int $0x10
320 ret
321
322/* print_hex prints the word pointed to by ss:bp in hexadecimal. */
323
324print_hex:
325 movw (%bp),%dx /* load word into dx */
326 movb $4, %cl
327 movb $0x0e, %ah /* write char, tty mode */
328 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
329 call print_digit
330 call print_digit
331 call print_digit
332/* fall through */
333print_digit:
334 rol %cl,%dx /* rotate so that lowest 4 bits are used */
335 movb $0x0f, %al /* mask for nybble */
336 andb %dl,%al
337 addb $0x90, %al /* convert al to ascii hex (four instructions) */
338 daa
339 adcb $0x40, %al
340 daa
341 int $0x10
342 ret
343
344sread: .word 0 /* sectors read of current track */
345head: .word 0 /* current head */
346track: .word 0 /* current track */
347
348sectors:
349 .word 0
350
351dpseg: .word 0
352dpoff: .word 0
353
354disksizes:
355 .byte 36,18,15,9
356
357msg1:
358 .ascii "Loading ROM image"
359msg1end:
360
361 .org 510, 0
362 .word 0xAA55
363
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette