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 * ----------------------------------------------------------------------- */
34 /* Partition table header here */
35 phdr = stack /* Above the stack, overwritten by bootsect */
36 /* Partition table sector here */
37 /* To handle > 32K we need to play segment tricks... */
41 bootguid = _start + 0x1a8
42 /* Where we put DS:SI */
43 dssi_out = _start + 0x1be
47 /* gas/ld has issues with doing this as absolute addresses... */
48 .section ".bootsec", "a", @nobits
62 pushw %es /* 4(%bp) es:di -> $PnP header */
63 pushw %di /* 2(%bp) */
64 pushw %dx /* 0(%bp) = %dl -> drive number */
69 /* Copy down to 0:0x600 */
77 /* Check to see if we have EBIOS */
78 pushw %dx /* drive number */
79 movb $0x41, %ah /* %al == 0 already */
88 shrw %cx /* Bit 0 = fixed disk subset */
91 /* We have EBIOS; patch in the following code at
92 read_sector_cbios: movb $0x42, %ah ; jmp read_common */
93 movl $0xeb42b4+((read_common-read_sector_cbios-4) << 24), \
99 /* Get (C)HS geometry */
102 andw $0x3f, %cx /* Sector count */
103 movw %sp, %bp /* %bp -> frame pointer: LEAVE UNCHANGED */
104 pushw %cx /* -2(%bp) Save sectors on the stack */
105 movzbw %dh, %ax /* dh = max head */
106 incw %ax /* From 0-based max to count */
107 mulw %cx /* Heads*sectors -> sectors per cylinder */
109 /* Save sectors/cylinder on the stack */
110 pushw %dx /* -4(%bp) High word */
111 pushw %ax /* -6(%bp) Low word */
113 /* Load partition table header */
120 /* Number of partition sectors */
121 /* We assume the partition table is 32K or less, and that
122 the sector size is 512. */
123 /* Note: phdr == 6(%bp) */
124 movw (80+6)(%bp),%cx /* NumberOfPartitionEntries */
125 movw (84+6)(%bp),%ax /* SizeOfPartitionEntry */
133 /* Starting LBA of partition array */
134 movl (72+6)(%bp),%eax
135 movl (76+6)(%bp),%edx
143 /* Find the boot partition */
144 popw %si /* Partition table in memory */
145 popw %cx /* NumberOfPartitionEntries */
146 popw %ax /* SizeOfPartitionEntry */
161 .ascii "Boot partition not found\r\n"
164 xchgw %ax,%cx /* Set up %cx for rep movsb further down */
169 /* 80 00 00 00 ee 00 00 00
170 - bootable partition, type EFI (EE), no CHS information */
178 call saturate_stosl /* Partition start */
185 call saturate_stosl /* Partition length */
187 rep; movsb /* GPT entry follows MBR entry */
191 * boot: invoke the actual bootstrap. %ds:%si points to the
192 * partition information in memory.
195 movl (32+16)(%si),%eax
196 movl (36+16)(%si),%edx
199 cmpw $0xaa55, -2(%bx)
200 jne missing_os /* Not a valid boot sector */
201 movw %bp, %sp /* driveno == bootsec-6 */
202 popw %dx /* dl -> drive number */
203 popw %di /* es:di -> $PnP vector */
206 jmpw *%sp /* %sp == bootsec */
210 .ascii "Operating system not bootable\r\n"
227 * read_sector: read a single sector pointed to by %edx:%eax to
228 * %es:%bx. CF is set on error. All registers saved.
232 pushl %edx /* MSW of LBA */
233 pushl %eax /* LSW of LBA */
234 pushw %es /* Buffer segment */
235 pushw %bx /* Buffer offset */
236 pushw $1 /* Sector count */
237 pushw $16 /* Size of packet */
240 /* This chunk is skipped if we have ebios */
241 /* Do not clobber %es:%bx or %edx:%eax before this chunk! */
243 divl -6(%bp) /* secpercyl */
248 divb -2(%bp) /* sectors */
251 incw %cx /* Sectors are 1-based */
255 movb (%bp), %dl /* driveno */
257 addw $16, %sp /* Drop DAPA */
260 addb $2, %bh /* bx += 512: point to the next buffer */
265 .ascii "Disk error on boot\r\n"
268 * Print error messages. This is invoked with "call", with the
269 * error message at the return address.
276 movb (BIOS_page), %bh
278 int $0x10 /* May destroy %bp */
279 cmpb $10, %al /* Newline? */
282 int $0x18 /* Boot failure */