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 */
116 incw %ax /* %edx:%eax = 1 */
118 pushw %bx /* -8(%bp) phdr == bootsect */
121 /* Number of partition sectors */
122 /* We assume the partition table is 32K or less, and that
123 the sector size is 512. */
124 /* Note: phdr == 6(%bp) */
125 movw (80+6)(%bp),%cx /* NumberOfPartitionEntries */
126 movw (84+6)(%bp),%ax /* SizeOfPartitionEntry */
134 /* Starting LBA of partition array */
135 movl (72+6)(%bp),%eax
136 movl (76+6)(%bp),%edx
144 /* Find the boot partition */
145 popw %si /* Partition table in memory */
146 popw %cx /* NumberOfPartitionEntries */
147 popw %ax /* SizeOfPartitionEntry */
162 .ascii "Boot partition not found\r\n"
165 xchgw %ax,%cx /* Set up %cx for rep movsb further down */
170 /* 80 00 00 00 ee 00 00 00
171 - bootable partition, type EFI (EE), no CHS information */
179 call saturate_stosl /* Partition start */
186 call saturate_stosl /* Partition length */
188 rep; movsb /* GPT entry follows MBR entry */
192 * boot: invoke the actual bootstrap. %ds:%si points to the
193 * partition information in memory. The top word on the stack
194 * is phdr == 0x7c00 == the address of the boot sector.
197 movl (32+16)(%si),%eax
198 movl (36+16)(%si),%edx
201 cmpw $0xaa55, -2(%bx)
202 jne missing_os /* Not a valid boot sector */
203 movw %bp, %sp /* driveno == bootsec-6 */
204 popw %dx /* dl -> drive number */
205 popw %di /* es:di -> $PnP vector */
207 movl $0x54504721,%eax /* !GPT magic number */
209 jmpw *%sp /* %sp == bootsec */
213 .ascii "Operating system not bootable\r\n"
230 * read_sector: read a single sector pointed to by %edx:%eax to
231 * %es:%bx. CF is set on error. All registers saved.
235 pushl %edx /* MSW of LBA */
236 pushl %eax /* LSW of LBA */
237 pushw %es /* Buffer segment */
238 pushw %bx /* Buffer offset */
239 pushw $1 /* Sector count */
240 pushw $16 /* Size of packet */
243 /* This chunk is skipped if we have ebios */
244 /* Do not clobber %es:%bx or %edx:%eax before this chunk! */
246 divl -6(%bp) /* secpercyl */
251 divb -2(%bp) /* sectors */
254 incw %cx /* Sectors are 1-based */
258 movb (%bp), %dl /* driveno */
260 addw $16, %sp /* Drop DAPA */
263 addb $2, %bh /* bx += 512: point to the next buffer */
268 .ascii "Disk error on boot\r\n"
271 * Print error messages. This is invoked with "call", with the
272 * error message at the return address.
279 movb (BIOS_page), %bh
281 int $0x10 /* May destroy %bp */
282 cmpb $10, %al /* Newline? */
285 int $0x18 /* Boot failure */