gptmbr: implement the new T13-approved GPT protocol
authorH. Peter Anvin <hpa@linux.intel.com>
Sat, 12 Jun 2010 00:03:24 +0000 (17:03 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Sat, 12 Jun 2010 00:03:24 +0000 (17:03 -0700)
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>
doc/gpt.txt
mbr/checksize.pl
mbr/gptmbr.S

index 14c1ee8..b17322d 100644 (file)
@@ -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.
index c1984db..4b42327 100755 (executable)
@@ -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]/) {
index 8d42e8b..20741ac 100644 (file)
@@ -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