Make __free_tagged actually free memory
[syslinux.git] / mbr / isohdpfx.S
blob0bf807e91cca39f5bc90211aa222b56faa57d618
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  * ----------------------------------------------------------------------- */
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  */
37 #include "adjust.h"
39         .code16
40         .text
42 HYBRID_MAGIC                    = 0x7078c0fb
43 isolinux_hybrid_signature       = 0x7c00+64
44 isolinux_start_hybrid           = 0x7c00+64+4
46         .globl  bootsec
47 /* Important: the top 6 words on the stack are passed to isolinux.bin */
48 stack           = 0x7c00
49 partoffset      = (stack-8)
50 driveno         = (stack-14)
51 heads           = (stack-16)
52 sectors         = (stack-18)
53 ebios_flag      = (stack-20)
54 secpercyl       = (stack-24)
56 BIOS_kbdflags   = 0x417
57 BIOS_page       = 0x462
59         /* gas/ld has issues with doing this as absolute addresses... */
60         .section ".bootsec", "a", @nobits
61         .globl  bootsec
62 bootsec:
63         .space  512
65         .text
66         .globl  _start
67 _start:
69         cli
70         xorw    %bp, %bp
71         movw    %bp, %ss
72         movw    $stack, %sp
73         sti
74         cld
76         /* Check to see if we have a partition table entry */
77         xorl    %ebx, %ebx
78         xorl    %ecx, %ecx
79 #ifdef PARTITION_SUPPORT
80         andw    %si, %si                /* %si == 0 -> no partition data */
81         jz      1f
82         testb   $0x7f, (%si)            /* Invalid active flag field? */
83         jnz     1f
84         cmpb    %cl, 4(%si)             /* Partition type zero == invalid? */
85         je      1f
86         cmpl    $0x58504721, %eax       /* !GPT signature in EAX? */
87         jne     2f
88         cmpb    $0xed, 4(%si)           /* EFI partition type? */
89         jne     2f
90         
91         /* We have GPT partition information */
92         movl    (32+20)(%si), %ecx
93         movl    (36+20)(%si), %ebx
94         jmp     1f
96         /* We have non-GPT partition information */
98         movl    8(%si), %ecx
99 #endif
101         /* We have no partition information */
102         pushl   %ebx                    /*  -4: partoffset_hi */
103         pushl   %ecx                    /*  -8: partoffset_lo */
104         pushw   %es                     /* -10: es:di -> $PnP header */
105         pushw   %di                     /* -12: es:di -> $PnP header */
107         movw    %bp, %ds
108         movw    %bp, %es
109         
110         ADJUST_DRIVE
111         pushw   %dx                     /* -14: dl -> drive number */
113         /* Copy down to 0:0x600 */
114         movw    $0x7c00, %si
115         movw    $_start, %di
116         movw    $(512/2), %cx
117         rep; movsw
119         ljmpw   $0, $next
120 next:
122         /* Check to see if we have EBIOS */
123         pushw   %dx             /* drive number */
124         movb    $0x41, %ah      /* %al == 0 already */
125         movw    $0x55aa, %bx
126         xorw    %cx, %cx
127         xorb    %dh, %dh
128         stc
129         int     $0x13
130         jc      1f
131         cmpw    $0xaa55, %bx
132         jne     1f
133         andw    $1,%cx          /* Bit 0 = fixed disk subset */
134         jz      1f
136         /* We have EBIOS; patch in the following code at
137            read_sector_cbios: movb $0x42, %ah ;  jmp read_common */
138         movl    $0xeb42b4+((read_common-read_sector_cbios-4) << 24), \
139                 (read_sector_cbios)
140         jmp     1f
142         popw    %dx
143         pushw   %cx             /* EBIOS flag */
145         /* Get (C)HS geometry */
146         movb    $0x08, %ah
147         int     $0x13
148         andw    $0x3f, %cx      /* Sector count */
149         popw    %bx             /* EBIOS flag */
150         pushw   %cx             /* -16: Save sectors on the stack */
151         movzbw  %dh, %ax        /* dh = max head */
152         incw    %ax             /* From 0-based max to count */
153         pushw   %ax             /* -18: Save heads on the stack */
154         mulw    %cx             /* Heads*sectors -> sectors per cylinder */
156         pushw   %bx             /* -20: EBIOS flag */
157         
158         /* Save sectors/cylinder on the stack */
159         pushw   %dx             /* -22: High word */
160         pushw   %ax             /* -24: Low word */
162         /*
163          * Load sectors.  We do this one at a time mostly to avoid
164          * pitfalls and to share code with the stock MBR code.
165          */
166         movw    $0x7c00, %bx
167         movw    $4, %cx         /* Sector count */
168         movl    (lba_offset), %eax
171         call    read_sector
172         jc      disk_error
173         incl    %eax
174         addb    $(512 >> 8), %bh
175         loopw   2b
177         /*
178          * Okay, that actually worked... update the stack pointer
179          * and jump into isolinux.bin...
180          */
181         cmpl    $HYBRID_MAGIC,(isolinux_hybrid_signature)
182         jne     bad_signature
184         cli
185         movw    $ebios_flag, %sp
187         /*
188          * Use a ljmpw here to work around a bug in some unknown version
189          * of gas or ld when it comes to jumping to an absolute symbol...
190          *
191          * Look more closely into it if we ever are short on space.
192          */
193         ljmpw   $0, $isolinux_start_hybrid
195 bad_signature:
196         call    error
197         .ascii  "isolinux.bin missing or corrupt.\r\n"
200  * read_sector: read a single sector pointed to by %eax to %es:%bx.
201  * CF is set on error.  All registers saved.
202  */
203 read_sector:
204         pushal
205         xorl    %edx, %edx
206         addl    (partoffset), %eax
207         adcl    (partoffset+4), %edx
208         pushl   %edx    /* MSW of LBA */
209         pushl   %eax    /* LSW of LBA */
210         pushw   %es     /* Buffer segment */
211         pushw   %bx     /* Buffer offset */
212         pushw   $1      /* Sector count */
213         pushw   $16     /* Size of packet */
214         movw    %sp, %si
216         /* This chunk is skipped if we have ebios */
217         /* Do not clobber %eax before this chunk! */
218         /* This also relies on %bx and %edx as set up above. */
219 read_sector_cbios:
220         divl    (secpercyl)
221         shlb    $6, %ah
222         movb    %ah, %cl
223         movb    %al, %ch
224         xchgw   %dx, %ax
225         divb    (sectors)
226         movb    %al, %dh
227         orb     %ah, %cl
228         incw    %cx     /* Sectors are 1-based */
229         movw    $0x0201, %ax
231 read_common:
232         movb    (driveno), %dl
233         int     $0x13
234         leaw    16(%si), %sp    /* Drop DAPA */
235         popal
236         ret
238 disk_error:
239         call    error
240         .ascii  "Operating system load error.\r\n"
243  * Print error messages.  This is invoked with "call", with the
244  * error message at the return address.
245  */
246 error:
247         popw    %si
249         lodsb
250         movb    $0x0e, %ah
251         movb    (BIOS_page), %bh
252         movb    $0x07, %bl
253         int     $0x10           /* May destroy %bp */
254         cmpb    $10, %al        /* Newline? */
255         jne     2b
257         int     $0x18           /* Boot failure */
258 die:
259         hlt
260         jmp     die
262         /* Address of pointer to isolinux.bin */
263 lba_offset = _start+432