1 /* -----------------------------------------------------------------------
3 * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
26 * ----------------------------------------------------------------------- */
29 * Modified MBR code used on an ISO image in hybrid mode.
31 * This doesn't follow the El Torito spec at all -- it is just a stub
32 * loader of a hard-coded offset, but that's good enough to load
39 HYBRID_MAGIC = 0x7078c0fb
40 isolinux_hybrid_signature = 0x7c00+64
41 isolinux_start_hybrid = 0x7c00+64+4
44 /* Important: the top 6 words on the stack are passed to isolinux.bin */
47 ebios_flag = (stack-8)
50 secpercyl = (stack-16)
54 /* gas/ld has issues with doing this as absolute addresses... */
55 .section ".bootsec", "a", @nobits
70 pushw %es /* es:di -> $PnP header */
72 pushw %dx /* dl -> drive number */
77 /* Copy down to 0:0x600 */
85 /* Check to see if we have EBIOS */
86 pushw %dx /* drive number */
87 movb $0x41, %ah /* %al == 0 already */
96 andw $1,%cx /* Bit 0 = fixed disk subset */
99 /* We have EBIOS; patch in the following code at
100 read_sector_cbios: movb $0x42, %ah ; jmp read_common */
101 movl $0xeb42b4+((read_common-read_sector_cbios-4) << 24), \
106 pushw %cx /* Save EBIOS flag */
108 /* Get (C)HS geometry */
111 andw $0x3f, %cx /* Sector count */
112 pushw %cx /* Save sectors on the stack */
113 movzbw %dh, %ax /* dh = max head */
114 incw %ax /* From 0-based max to count */
115 pushw %ax /* Save heads on the stack */
116 mulw %cx /* Heads*sectors -> sectors per cylinder */
118 /* Save sectors/cylinder on the stack */
119 pushw %dx /* High word */
120 pushw %ax /* Low word */
123 * Load sectors. We do this one at a time mostly to avoid
124 * pitfalls and to share code with the stock MBR code.
127 movw $4, %cx /* Sector count */
128 movl (lba_offset), %eax
138 * Okay, that actually worked... update the stack pointer
139 * and jump into isolinux.bin...
141 cmpl $HYBRID_MAGIC,(isolinux_hybrid_signature)
146 jmp isolinux_start_hybrid
150 .ascii "isolinux.bin missing or corrupt.\r\n"
153 * read_sector: read a single sector pointed to by %eax to %es:%bx.
154 * CF is set on error. All registers saved.
159 pushl %edx /* MSW of LBA */
160 pushl %eax /* LSW of LBA */
161 pushw %es /* Buffer segment */
162 pushw %bx /* Buffer offset */
163 pushw $1 /* Sector count */
164 pushw $16 /* Size of packet */
167 /* This chunk is skipped if we have ebios */
168 /* Do not clobber %eax before this chunk! */
169 /* This also relies on %bx and %edx as set up above. */
179 incw %cx /* Sectors are 1-based */
185 addw $16, %sp /* Drop DAPA */
191 .ascii "Operating system load error.\r\n"
194 * Print error messages. This is invoked with "call", with the
195 * error message at the return address.
202 movb (BIOS_page), %bh
204 int $0x10 /* May destroy %bp */
205 cmpb $10, %al /* Newline? */
208 int $0x18 /* Boot failure */
213 /* Address of pointer to isolinux.bin */
214 lba_offset = _start+432