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