Andriy Gapon <a...@freebsd.org> wrote
  in <4f3e3000.9000...@freebsd.org>:

av> -----BEGIN PGP SIGNED MESSAGE-----
av> Hash: SHA1
av>
av> on 17/02/2012 09:04 Hiroki Sato said the following:
av> > No, the issue is our gptloader assumes the backup header is always located
av> > at the (physical) last sector while this is not mandatory in the UEFI
av> > specification.
av>
av> Are you sure?

 Yes, sure.  In the gm0->md0+md1 case, the last LBA of the "device" is
 changed (growed in size) but they can still have a valid backup
 header at "the last LBA - 1" before an attempt to grow the size of
 the volume as the last paragraph of your excerpts says.  If we
 *choose* to grow the device size permanently, the backup header must
 be relocated at the new last LBA.  However, before the relocation
 happens, the specification says both the primary and secondary header
 must be valid in the previous device size.  This is my understanding.

 This means software should assume the device size can grow and should
 not assume the backup header is always located at the last possible
 LBA on the device.  If AlternateLBA does not match "the device size -
 1", the software should recognize the location of the backup header
 based on the information in the primary header first.  The gptboot
 does not do so currently.  I didn't give it a try actually but the
 attached patch is what I want to say.

-- Hiroki
Index: sys/boot/common/gpt.c
===================================================================
--- sys/boot/common/gpt.c	(revision 230616)
+++ sys/boot/common/gpt.c	(working copy)
@@ -333,24 +333,26 @@
 	    gptread_table("primary", uuid, dskp, &hdr_primary,
 	    table_primary) == 0) {
 		hdr_primary_lba = hdr_primary.hdr_lba_self;
+		/* Use AlternateLBA if valid.  If not, use LastUsableLBA+34. */
+		if (hdr_primary_lba < hdr_primary.hdr_lba_alt)
+			altlba = hdr_primary.hdr_lba_alt;
+		else if (hdr_primary.hdr_lba_end != 0)
+			altlba = hdr_primary.hdr_lba_end + 34;
 		gpthdr = &hdr_primary;
 		gpttable = table_primary;
 	}

-	altlba = drvsize(dskp);
-	if (altlba > 0)
-		altlba--;
-	else if (hdr_primary_lba > 0) {
-		/*
-		 * If we cannot obtain disk size, but primary header
-		 * is valid, we can get backup header location from
-		 * there.
-		 */
-		altlba = hdr_primary.hdr_lba_alt;
+	/*
+	 * Try to locate the backup header from the media size if no primary
+	 * header found.
+	 */
+	if (hdr_primary_lba == 0) {
+		altlba = drvsize(dskp);
+		if (altlba > 0)
+			altlba--;
 	}
-	if (altlba == 0)
-		printf("%s: unable to locate backup GPT header\n", BOOTPROG);
-	else if (gptread_hdr("backup", dskp, &hdr_backup, altlba) == 0 &&
+	if (altlba != 0 &&
+	    gptread_hdr("backup", dskp, &hdr_backup, altlba) == 0 &&
 	    gptread_table("backup", uuid, dskp, &hdr_backup,
 	    table_backup) == 0) {
 		hdr_backup_lba = hdr_backup.hdr_lba_self;
@@ -359,7 +361,8 @@
 			gpttable = table_backup;
 			printf("%s: using backup GPT\n", BOOTPROG);
 		}
-	}
+	} else
+		printf("%s: unable to locate backup GPT header\n", BOOTPROG);

 	/*
 	 * Convert all BOOTONCE without BOOTME flags into BOOTFAILED.

Attachment: pgppi2XRbnX5b.pgp
Description: PGP signature

Reply via email to