summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-06-11 17:03:24 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2010-06-11 17:03:24 -0700
commitd4c1eecb7c6e37432ba9ef0624e29129d9b8be24 (patch)
tree8ad5fadb1d6796e22df420365f5f599a6a70f603
parentb0ff6613d593ee88790a9299afd20ebd66c65b3c (diff)
downloadsyslinux-d4c1eecb7c6e37432ba9ef0624e29129d9b8be24.tar.gz
gptmbr: implement the new T13-approved GPT protocol
My GPT-based protocol was modified by the UEFI and T13 committees (the former responsible for the GPT format, the latter for EDD and therefore for the disk-related part of the BIOS specification.) This is thus now on its way to become an official protocol, so change the implementation to match. This still needs testing, and the Syslinux core needs to be adjusted to leverage the extended information. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--doc/gpt.txt45
-rwxr-xr-xmbr/checksize.pl2
-rw-r--r--mbr/gptmbr.S44
3 files changed, 39 insertions, 52 deletions
diff --git a/doc/gpt.txt b/doc/gpt.txt
index 14c1ee8e..b17322d0 100644
--- a/doc/gpt.txt
+++ b/doc/gpt.txt
@@ -1,13 +1,10 @@
GPT boot protocol
-There is no official MBR-to-partition handover protocol defined for
-booting from disks partitioned using GPT partition tables with
-BIOS-style firmware. This is because the GPT partition format comes
-from the EFI spec, which thinks the universe is all going to be EFI.
-Sigh.
+There are two ways to boot a GPT-formatted disk on a BIOS system.
+Hybrid booting, and the new GPT-only booting protocol originally
+proposed by the author, and later adopted by the T13 committee in
+slightly modified form.
-There are thus two alternatives: hybrid booting, and defining a new
-protocol.
*** Hybrid booting ***
@@ -29,31 +26,16 @@ GPT disk with BIOS firmware.
*** New protocol ***
-This defines an alternative (experimental) booting protocol for GPT
-partitions with BIOS firmware. It maintains backwards compatibility
-to the extent possible. It is implemented by the file mbr/gptmbr.bin.
+This defines the T13-approved protocol for GPT partitions with BIOS
+firmware. It maintains backwards compatibility to the extent
+possible. It is implemented by the file mbr/gptmbr.bin.
- -> The PMBR
+The (P)MBR format is the normal PMBR specified in the UEFI
+documentation, with the first 440 bytes used for the boot code. The
+partition to be booted is marked by setting bit 2 in the GPT Partition
+Entry Attributes field (offset 48); this bit is reserved by the UEFI
+Forum for "Legacy BIOS Bootable".
-The PMBR (the first 512-byte sector of the disk) is divided up as
-follows:
-
- Offset Size Contents
- ---------------------------------------------------------
- 0 424 PMBR boot code
- 424 16 GUID of the boot partition
- 440 4 MBR-compatible disk ID
- 444 2 Magic number: 1D 9A
- 446 16 PMBR protective entry
- 462 48 PMBR null entries
- 510 2 Boot signature: 55 AA
-
-To change the bootable partition, verify that the magic number is
-present (to avoid corrupting software not compatible with this
-specification) and enter the GUID of the boot partition at offset
-424. It might be wise to verify that the data already there is a
-valid partition GUID already, or at least warn the user if that is not
-the case.
-> The handover protocol
@@ -70,7 +52,8 @@ form:
5 3 CHS of partition end
8 4 Partition start LBA
12 4 Partition end LBA
- 16 varies GPT partition entry
+ 16 4 Length of the GPT entry
+ 20 varies GPT partition entry
The CHS information is optional; gptmbr.bin currently does *NOT*
calculate them, and just leaves them as zero.
diff --git a/mbr/checksize.pl b/mbr/checksize.pl
index c1984dbf..4b42327f 100755
--- a/mbr/checksize.pl
+++ b/mbr/checksize.pl
@@ -26,7 +26,7 @@ if (!defined($maxsize)) {
if ($file =~ /^mbr[^0-9a-z]/) {
$maxsize = $padsize = 440;
} elsif ($file =~ /^gptmbr[^0-9a-z]/) {
- $maxsize = $padsize = 424;
+ $maxsize = $padsize = 440;
} elsif ($file =~ /^isohdp[fp]x[^0-9a-z]/) {
$maxsize = $padsize = 432;
} elsif ($file =~ /^altmbr[^0-9a-z]/) {
diff --git a/mbr/gptmbr.S b/mbr/gptmbr.S
index 8d42e8b8..20741acb 100644
--- a/mbr/gptmbr.S
+++ b/mbr/gptmbr.S
@@ -40,8 +40,6 @@ phdr = stack /* Above the stack, overwritten by bootsect */
/* To handle > 32K we need to play segment tricks... */
psec = _phdr + 512
-/* BootGUID */
-bootguid = _start + 0x1a8
/* Where we put DS:SI */
dssi_out = _start + 0x1be
@@ -148,24 +146,31 @@ get_ptab:
loopw get_ptab
/* Find the boot partition */
- popw %si /* Partition table in memory */
+ xorw %si,%si /* Nothing found yet */
+ popw %di /* Partition table in memory */
popw %cx /* NumberOfPartitionEntries */
popw %ax /* SizeOfPartitionEntry */
+
find_part:
- pushw %cx
- pushw %si
- addw $16,%si
- movw $bootguid,%di
- movw $8,%cx
- repe; cmpsw
- popw %si
- popw %cx
- je found_part
- addw %ax,%si
+ testb $0x04,48(%di)
+ jz not_this
+ andw %si,%si
+ jnz found_multiple
+ movw %di,%si
+not_this:
+ addw %ax,%di
loopw find_part
+ andw %si,%si
+ jnz found_part
+
+missing_os:
call error
- .ascii "Boot partition not found\r\n"
+ .ascii "Missing OS\r\n"
+
+found_multiple:
+ call error
+ .ascii "Multiple active partitions\r\n"
found_part:
xchgw %ax,%cx /* Set up %cx for rep movsb further down */
@@ -191,6 +196,9 @@ found_part:
call inc64
call saturate_stosl /* Partition length */
+ movzwl %cx,%eax /* Length of GPT entry */
+ stosl
+
rep; movsb /* GPT entry follows MBR entry */
popw %si
@@ -200,8 +208,8 @@ found_part:
* is phdr == 0x7c00 == the address of the boot sector.
*/
boot:
- movl (32+16)(%si),%eax
- movl (36+16)(%si),%edx
+ movl (32+20)(%si),%eax
+ movl (36+20)(%si),%edx
popw %bx
call read_sector
cmpw $0xaa55, -2(%bx)
@@ -214,10 +222,6 @@ boot:
cli
jmpw *%sp /* %sp == bootsec */
-missing_os:
- call error
- .ascii "OS not bootable\r\n"
-
saturate_stosl:
pushl %eax
andl %edx,%edx