From d4c1eecb7c6e37432ba9ef0624e29129d9b8be24 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 11 Jun 2010 17:03:24 -0700 Subject: [PATCH] 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 --- doc/gpt.txt | 45 ++++++++++++++------------------------------- mbr/checksize.pl | 2 +- mbr/gptmbr.S | 44 ++++++++++++++++++++++++-------------------- 3 files changed, 39 insertions(+), 52 deletions(-) diff --git a/doc/gpt.txt b/doc/gpt.txt index 14c1ee8..b17322d 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 c1984db..4b42327 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 8d42e8b..20741ac 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 -- 2.7.4