source: bootcd/isolinux/syslinux-6.03/gpxe/src/arch/i386/prefix/dskprefix.S

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

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