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 */
49 secpercyl = (stack-14)
53 /* gas/ld has issues with doing this as absolute addresses... */
54 .section ".bootsec", "a", @nobits
69 pushw %es /* es:di -> $PnP header */
71 pushw %dx /* dl -> drive number */
76 /* Copy down to 0:0x600 */
84 /* Check to see if we have EBIOS */
85 pushw %dx /* drive number */
86 movb $0x41, %ah /* %al == 0 already */
95 shrw %cx /* Bit 0 = fixed disk subset */
98 /* We have EBIOS; patch in the following code at
99 read_sector_cbios: movb $0x42, %ah ; jmp read_common */
100 movl $0xeb42b4+((read_common-read_sector_cbios-4) << 24), \
106 /* Get (C)HS geometry */
109 andw $0x3f, %cx /* Sector count */
110 pushw %cx /* Save sectors on the stack */
111 movzbw %dh, %ax /* dh = max head */
112 incw %ax /* From 0-based max to count */
113 pushw %ax /* Save heads on the stack */
114 mulw %cx /* Heads*sectors -> sectors per cylinder */
116 /* Save sectors/cylinder on the stack */
117 pushw %dx /* High word */
118 pushw %ax /* Low word */
121 * Load sectors. We do this one at a time mostly to avoid
122 * pitfalls and to share code with the stock MBR code.
125 movw $4, %cx /* Sector count */
126 movl (lba_offset), %eax
136 * Okay, that actually worked... update the stack pointer
137 * and jump into isolinux.bin...
139 cmpl $HYBRID_MAGIC,(isolinux_hybrid_signature)
144 jmp isolinux_start_hybrid
148 .ascii "isolinux.bin missing or corrupt.\r\n"
151 * read_sector: read a single sector pointed to by %eax to %es:%bx.
152 * CF is set on error. All registers saved.
157 pushl %edx /* MSW of LBA */
158 pushl %eax /* LSW of LBA */
159 pushw %es /* Buffer segment */
160 pushw %bx /* Buffer offset */
161 pushw $1 /* Sector count */
162 pushw $16 /* Size of packet */
165 /* This chunk is skipped if we have ebios */
166 /* Do not clobber %eax before this chunk! */
167 /* This also relies on %bx and %edx as set up above. */
177 incw %cx /* Sectors are 1-based */
183 addw $16, %sp /* Drop DAPA */
189 .ascii "Operating system load error.\r\n"
192 * Print error messages. This is invoked with "call", with the
193 * error message at the return address.
200 movb (BIOS_page), %bh
202 int $0x10 /* May destroy %bp */
203 cmpb $10, %al /* Newline? */
206 int $0x18 /* Boot failure */
211 /* Address of pointer to isolinux.bin */
212 lba_offset = _start+432