source: bootcd/isolinux/syslinux-6.03/mbr/isohdpfx.S @ dd1be7c

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

bootstuff

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/* -----------------------------------------------------------------------
2 *
3 *   Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
4 *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
5 *
6 *   Permission is hereby granted, free of charge, to any person
7 *   obtaining a copy of this software and associated documentation
8 *   files (the "Software"), to deal in the Software without
9 *   restriction, including without limitation the rights to use,
10 *   copy, modify, merge, publish, distribute, sublicense, and/or
11 *   sell copies of the Software, and to permit persons to whom
12 *   the Software is furnished to do so, subject to the following
13 *   conditions:
14 *
15 *   The above copyright notice and this permission notice shall
16 *   be included in all copies or substantial portions of the Software.
17 *
18 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 *   OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * ----------------------------------------------------------------------- */
28
29/*
30 * Modified MBR code used on an ISO image in hybrid mode.
31 *
32 * This doesn't follow the El Torito spec at all -- it is just a stub
33 * loader of a hard-coded offset, but that's good enough to load
34 * ISOLINUX.
35 */
36
37#include "adjust.h"
38
39        .code16
40        .text
41
42HYBRID_MAGIC                    = 0x7078c0fb
43isolinux_hybrid_signature       = 0x7c00+64
44isolinux_start_hybrid           = 0x7c00+64+4
45
46        .globl  bootsec
47/* Important: the top 6 words on the stack are passed to isolinux.bin */
48stack           = 0x7c00
49partoffset      = (stack-8)
50driveno         = (stack-14)
51heads           = (stack-16)
52sectors         = (stack-18)
53ebios_flag      = (stack-20)
54secpercyl       = (stack-24)
55
56BIOS_kbdflags   = 0x417
57BIOS_page       = 0x462
58
59        /* gas/ld has issues with doing this as absolute addresses... */
60        .section ".bootsec", "a", @nobits
61        .globl  bootsec
62bootsec:
63        .space  512
64
65        .text
66        .globl  _start
67_start:
68        .byte   0x33, 0xed      /* xorw %bp, %bp */
69        nop
70        nop
71        nop
72        nop
73        nop
74        nop
75        nop
76        nop
77        nop
78        nop
79        nop
80        nop
81        nop
82        nop
83        nop
84        nop
85        nop
86        nop
87        nop
88        nop
89        nop
90        nop
91        nop
92        nop
93        nop
94        nop
95        nop
96        nop
97        nop
98        nop
99        .byte   0x33, 0xed      /* xorw %bp, %bp */
100        cli
101        movw    %bp, %ss
102        movw    $stack, %sp
103        sti
104        cld
105
106        /* Check to see if we have a partition table entry */
107        xorl    %ebx, %ebx
108        xorl    %ecx, %ecx
109#ifdef PARTITION_SUPPORT
110        andw    %si, %si                /* %si == 0 -> no partition data */
111        jz      1f
112        testb   $0x7f, (%si)            /* Invalid active flag field? */
113        jnz     1f
114        cmpb    %cl, 4(%si)             /* Partition type zero == invalid? */
115        je      1f
116        cmpl    $0x58504721, %eax       /* !GPT signature in EAX? */
117        jne     2f
118        cmpb    $0xed, 4(%si)           /* EFI partition type? */
119        jne     2f
120       
121        /* We have GPT partition information */
122        movl    (32+20)(%si), %ecx
123        movl    (36+20)(%si), %ebx
124        jmp     1f
125
126        /* We have non-GPT partition information */
1272:
128        movl    8(%si), %ecx
129#endif
1301:
131        /* We have no partition information */
132        pushl   %ebx                    /*  -4: partoffset_hi */
133        pushl   %ecx                    /*  -8: partoffset_lo */
134        pushw   %es                     /* -10: es:di -> $PnP header */
135        pushw   %di                     /* -12: es:di -> $PnP header */
136
137        movw    %bp, %ds
138        movw    %bp, %es
139       
140        ADJUST_DRIVE
141        pushw   %dx                     /* -14: dl -> drive number */
142
143        /* Copy down to 0:0x600 */
144        movw    $0x7c00, %si
145        movw    $_start, %di
146        movw    $(512/2), %cx
147        rep; movsw
148
149        ljmpw   $0, $next
150next:
151
152        /* Check to see if we have EBIOS */
153        pushw   %dx             /* drive number */
154        movb    $0x41, %ah      /* %al == 0 already */
155        movw    $0x55aa, %bx
156        xorw    %cx, %cx
157        xorb    %dh, %dh
158        stc
159        int     $0x13
160        jc      1f
161        cmpw    $0xaa55, %bx
162        jne     1f
163        andw    $1,%cx          /* Bit 0 = fixed disk subset */
164        jz      1f
165
166        /* We have EBIOS; patch in the following code at
167           read_sector_cbios: movb $0x42, %ah ;  jmp read_common */
168        movl    $0xeb42b4+((read_common-read_sector_cbios-4) << 24), \
169                (read_sector_cbios)
170        jmp     1f
1711:
172        popw    %dx
173        pushw   %cx             /* EBIOS flag */
174
175        /* Get (C)HS geometry */
176        movb    $0x08, %ah
177        int     $0x13
178        andw    $0x3f, %cx      /* Sector count */
179        popw    %bx             /* EBIOS flag */
180        pushw   %cx             /* -16: Save sectors on the stack */
181        movzbw  %dh, %ax        /* dh = max head */
182        incw    %ax             /* From 0-based max to count */
183        pushw   %ax             /* -18: Save heads on the stack */
184        mulw    %cx             /* Heads*sectors -> sectors per cylinder */
185
186        pushw   %bx             /* -20: EBIOS flag */
187       
188        /* Save sectors/cylinder on the stack */
189        pushw   %dx             /* -22: High word */
190        pushw   %ax             /* -24: Low word */
191
192        /*
193         * Load sectors.  We do this one at a time mostly to avoid
194         * pitfalls and to share code with the stock MBR code.
195         */
196        movw    $0x7c00, %bx
197        movw    $4, %cx         /* Sector count */
198        movl    (lba_offset), %eax
199
2002:
201        call    read_sector
202        jc      disk_error
203        incl    %eax
204        addb    $(512 >> 8), %bh
205        loopw   2b
206
207        /*
208         * Okay, that actually worked... update the stack pointer
209         * and jump into isolinux.bin...
210         */
211        cmpl    $HYBRID_MAGIC,(isolinux_hybrid_signature)
212        jne     bad_signature
213
214        cli
215        movw    $ebios_flag, %sp
216
217        /*
218         * Use a ljmpw here to work around a bug in some unknown version
219         * of gas or ld when it comes to jumping to an absolute symbol...
220         *
221         * Look more closely into it if we ever are short on space.
222         */
223        ljmpw   $0, $isolinux_start_hybrid
224
225bad_signature:
226        call    error
227        .ascii  "isolinux.bin missing or corrupt.\r\n"
228
229/*
230 * read_sector: read a single sector pointed to by %eax to %es:%bx.
231 * CF is set on error.  All registers saved.
232 */
233read_sector:
234        pushal
235        xorl    %edx, %edx
236        addl    (partoffset), %eax
237        adcl    (partoffset+4), %edx
238        pushl   %edx    /* MSW of LBA */
239        pushl   %eax    /* LSW of LBA */
240        pushw   %es     /* Buffer segment */
241        pushw   %bx     /* Buffer offset */
242        pushw   $1      /* Sector count */
243        pushw   $16     /* Size of packet */
244        movw    %sp, %si
245
246        /* This chunk is skipped if we have ebios */
247        /* Do not clobber %eax before this chunk! */
248        /* This also relies on %bx and %edx as set up above. */
249read_sector_cbios:
250        divl    (secpercyl)
251        shlb    $6, %ah
252        movb    %ah, %cl
253        movb    %al, %ch
254        xchgw   %dx, %ax
255        divb    (sectors)
256        movb    %al, %dh
257        orb     %ah, %cl
258        incw    %cx     /* Sectors are 1-based */
259        movw    $0x0201, %ax
260
261read_common:
262        movb    (driveno), %dl
263        int     $0x13
264        leaw    16(%si), %sp    /* Drop DAPA */
265        popal
266        ret
267
268disk_error:
269        call    error
270        .ascii  "Operating system load error.\r\n"
271
272/*
273 * Print error messages.  This is invoked with "call", with the
274 * error message at the return address.
275 */
276error:
277        popw    %si
2782:
279        lodsb
280        movb    $0x0e, %ah
281        movb    (BIOS_page), %bh
282        movb    $0x07, %bl
283        int     $0x10           /* May destroy %bp */
284        cmpb    $10, %al        /* Newline? */
285        jne     2b
286
287        int     $0x18           /* Boot failure */
288die:
289        hlt
290        jmp     die
291
292        /* Address of pointer to isolinux.bin */
293lba_offset = _start+432
Note: See TracBrowser for help on using the repository browser.