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.
pgppi2XRbnX5b.pgp
Description: PGP signature