summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@chromium.org>2016-09-07 16:45:48 -0400
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-02-02 04:09:53 +0000
commitd6c687b0cd889261dd96a8fe4b53d07e7daaa7d9 (patch)
tree9d0f3ce35ce125f4b5ce7896d95b342930b9a195
parent79dcfc138e0a37e269e907e471892c6fe72fe8eb (diff)
downloadvboot-factory-gale-8743.19.B.tar.gz
cgpt: add support for managing the legacy boot gpt bitfactory-gale-8743.19.B
Bit 2 in the GPT partition attributes has been allocated as the legacy bios boot (equivalent to the "active" or "boot" flag in MBR). If we try to boot images on newer x86 systems, syslinux dies because it can't find any GPT partition marked bootable. Update the various parts of cgpt add & show to manage this bit. Now we can run: cgpt add -i 12 -B 1 chromiumos_image.bin And the EFI partition will be marked bootable. BUG=chromium:644845 TEST=vboot_reference unittests pass TEST=booted an amd64-generic disk image via USB on a generic laptop BRANCH=None Change-Id: I78e17b8df5b0c61e9e2d8a3c703e6d5ad230fe92 Reviewed-on: https://chromium-review.googlesource.com/382411 Commit-Ready: Mike Frysinger <vapier@chromium.org> Tested-by: Mike Frysinger <vapier@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/897390 Reviewed-by: Mike Frysinger <vapier@chromium.org> Commit-Queue: Wei-Han Chen <stimim@chromium.org> Tested-by: Wei-Han Chen <stimim@chromium.org>
-rw-r--r--cgpt/cgpt.h3
-rw-r--r--cgpt/cgpt_add.c6
-rw-r--r--cgpt/cgpt_common.c14
-rw-r--r--cgpt/cgpt_show.c38
-rw-r--r--cgpt/cmd_add.c9
-rw-r--r--cgpt/cmd_show.c4
-rw-r--r--firmware/include/gpt.h7
-rw-r--r--firmware/include/gpt_misc.h2
-rw-r--r--firmware/lib/cgptlib/cgptlib_internal.c10
-rw-r--r--firmware/lib/cgptlib/include/cgptlib_internal.h6
-rw-r--r--host/include/cgpt_params.h2
-rw-r--r--tests/cgptlib_test.c20
12 files changed, 107 insertions, 14 deletions
diff --git a/cgpt/cgpt.h b/cgpt/cgpt.h
index c4edd954..1216a72c 100644
--- a/cgpt/cgpt.h
+++ b/cgpt/cgpt.h
@@ -149,6 +149,9 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw);
uint32_t GetNumberOfEntries(const struct drive *drive);
GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index);
+void SetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index,
+ int legacy_boot);
+int GetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index);
void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
int priority);
int GetPriority(struct drive *drive, int secondary, uint32_t entry_index);
diff --git a/cgpt/cgpt_add.c b/cgpt/cgpt_add.c
index d6b3cabd..3808255a 100644
--- a/cgpt/cgpt_add.c
+++ b/cgpt/cgpt_add.c
@@ -55,6 +55,10 @@ static const char* DumpCgptAddParams(const CgptAddParams *params) {
snprintf(tmp, sizeof(tmp), "-P %d ", params->priority);
StrnAppend(buf, tmp, sizeof(buf));
}
+ if (params->set_legacy_boot) {
+ snprintf(tmp, sizeof(tmp), "-B %d ", params->legacy_boot);
+ StrnAppend(buf, tmp, sizeof(buf));
+ }
if (params->set_raw) {
snprintf(tmp, sizeof(tmp), "-A 0x%x ", params->raw_value);
StrnAppend(buf, tmp, sizeof(buf));
@@ -109,6 +113,8 @@ static int SetEntryAttributes(struct drive *drive,
SetTries(drive, PRIMARY, index, params->tries);
if (params->set_priority)
SetPriority(drive, PRIMARY, index, params->priority);
+ if (params->set_legacy_boot)
+ SetLegacyBoot(drive, PRIMARY, index, params->legacy_boot);
}
// New partitions must specify type, begin, and size.
diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c
index 29906d40..1a6bd3cb 100644
--- a/cgpt/cgpt_common.c
+++ b/cgpt/cgpt_common.c
@@ -763,6 +763,20 @@ GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index) {
return (GptEntry*)(&entries[stride * entry_index]);
}
+void SetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index,
+ int legacy_boot) {
+ require(legacy_boot >= 0 && legacy_boot <= CGPT_ATTRIBUTE_MAX_LEGACY_BOOT);
+ GptEntry *entry;
+ entry = GetEntry(&drive->gpt, secondary, entry_index);
+ SetEntryLegacyBoot(entry, legacy_boot);
+}
+
+int GetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index) {
+ GptEntry *entry;
+ entry = GetEntry(&drive->gpt, secondary, entry_index);
+ return GetEntryLegacyBoot(entry);
+}
+
void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
int priority) {
require(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
diff --git a/cgpt/cgpt_show.c b/cgpt/cgpt_show.c
index 638655bd..81b499c7 100644
--- a/cgpt/cgpt_show.c
+++ b/cgpt/cgpt_show.c
@@ -100,6 +100,7 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
char contents[256]; // scratch buffer for formatting output
uint8_t label[GPT_PARTNAME_LEN];
char type[GUID_STRLEN], unique[GUID_STRLEN];
+ int clen;
UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
label, sizeof(label));
@@ -118,6 +119,7 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
GuidToStr(&entry->unique, unique, GUID_STRLEN);
printf(PARTITION_MORE, "UUID: ", unique);
+ clen = 0;
if (!raw) {
if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
int tries = (entry->attrs.fields.gpt_att &
@@ -129,16 +131,35 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
int priority = (entry->attrs.fields.gpt_att &
CGPT_ATTRIBUTE_PRIORITY_MASK) >>
CGPT_ATTRIBUTE_PRIORITY_OFFSET;
- require(snprintf(contents, sizeof(contents),
- "priority=%d tries=%d successful=%d",
- priority, tries, successful) < sizeof(contents));
- printf(PARTITION_MORE, "Attr: ", contents);
+ clen = snprintf(contents, sizeof(contents),
+ "priority=%d tries=%d successful=%d ",
+ priority, tries, successful);
+ }
+
+ if (entry->attrs.fields.system) {
+ clen += snprintf(contents + clen, sizeof(contents) - clen,
+ "system=%d ", entry->attrs.fields.system);
+ require(clen < sizeof(contents));
+ }
+
+ if (entry->attrs.fields.efi_ignore) {
+ clen += snprintf(contents + clen, sizeof(contents) - clen,
+ "efi_ignore=%d ", entry->attrs.fields.efi_ignore);
+ require(clen < sizeof(contents));
+ }
+
+ if (entry->attrs.fields.legacy_boot) {
+ clen += snprintf(contents + clen, sizeof(contents) - clen,
+ "legacy_boot=%d ", entry->attrs.fields.legacy_boot);
+ require(clen < sizeof(contents));
}
} else {
- require(snprintf(contents, sizeof(contents),
- "[%x]", entry->attrs.fields.gpt_att) < sizeof(contents));
- printf(PARTITION_MORE, "Attr: ", contents);
+ clen = snprintf(contents, sizeof(contents),
+ "[%x]", entry->attrs.fields.gpt_att);
}
+ require(clen < sizeof(contents));
+ if (clen)
+ printf(PARTITION_MORE, "Attr: ", contents);
}
void EntriesDetails(struct drive *drive, const int secondary, int raw) {
@@ -209,6 +230,9 @@ static int GptShow(struct drive *drive, CgptShowParams *params) {
case 'P':
printf("%d\n", GetPriority(drive, ANY_VALID, index));
break;
+ case 'B':
+ printf("%d\n", GetLegacyBoot(drive, ANY_VALID, index));
+ break;
case 'A':
printf("0x%x\n", entry->attrs.fields.gpt_att);
break;
diff --git a/cgpt/cmd_add.c b/cgpt/cmd_add.c
index ca379a22..3c7741b8 100644
--- a/cgpt/cmd_add.c
+++ b/cgpt/cmd_add.c
@@ -27,6 +27,7 @@ static void Usage(void)
" -S NUM set Successful flag (0|1)\n"
" -T NUM set Tries flag (0-15)\n"
" -P NUM set Priority flag (0-15)\n"
+ " -B NUM set Legacy Boot flag (0|1)\n"
" -A NUM set raw 16-bit attribute value (bits 48-63)\n"
"\n"
"Use the -i option to modify an existing partition.\n"
@@ -45,7 +46,7 @@ int cmd_add(int argc, char *argv[]) {
char *e = 0;
opterr = 0; // quiet, you
- while ((c=getopt(argc, argv, ":hi:b:s:t:u:l:S:T:P:A:D:")) != -1)
+ while ((c=getopt(argc, argv, ":hi:b:s:t:u:l:S:T:P:B:A:D:")) != -1)
{
switch (c)
{
@@ -103,6 +104,12 @@ int cmd_add(int argc, char *argv[]) {
errorcnt += check_int_parse(c, e);
errorcnt += check_int_limit(c, params.priority, 0, 15);
break;
+ case 'B':
+ params.set_legacy_boot = 1;
+ params.legacy_boot = (uint32_t)strtoul(optarg, &e, 0);
+ errorcnt += check_int_parse(c, e);
+ errorcnt += check_int_limit(c, params.legacy_boot, 0, 1);
+ break;
case 'A':
params.set_raw = 1;
params.raw_value = strtoull(optarg, &e, 0);
diff --git a/cgpt/cmd_show.c b/cgpt/cmd_show.c
index 860d80e7..b9e64818 100644
--- a/cgpt/cmd_show.c
+++ b/cgpt/cmd_show.c
@@ -32,6 +32,7 @@ static void Usage(void)
" -S Successful flag\n"
" -T Tries flag\n"
" -P Priority flag\n"
+ " -B Legacy Boot flag\n"
" -A raw 16-bit attribute value (bits 48-63)\n"
" -d Debug output (including invalid headers)\n"
"\n", progname);
@@ -46,7 +47,7 @@ int cmd_show(int argc, char *argv[]) {
char *e = 0;
opterr = 0; // quiet, you
- while ((c=getopt(argc, argv, ":hnvqi:bstulSTPAdD:")) != -1)
+ while ((c=getopt(argc, argv, ":hnvqi:bstulSTPBAdD:")) != -1)
{
switch (c)
{
@@ -75,6 +76,7 @@ int cmd_show(int argc, char *argv[]) {
case 'S':
case 'T':
case 'P':
+ case 'B':
case 'A':
params.single_item = c;
break;
diff --git a/firmware/include/gpt.h b/firmware/include/gpt.h
index 275b3ae8..ae957cf7 100644
--- a/firmware/include/gpt.h
+++ b/firmware/include/gpt.h
@@ -108,7 +108,12 @@ typedef struct {
uint64_t ending_lba;
union {
struct {
- uint16_t reserved[3];
+ uint8_t system:1;
+ uint8_t efi_ignore:1;
+ uint8_t legacy_boot:1;
+ uint8_t reserved1:5;
+ uint8_t reserved2;
+ uint16_t reserved[2];
uint16_t gpt_att;
} __attribute__((packed)) fields;
uint64_t whole;
diff --git a/firmware/include/gpt_misc.h b/firmware/include/gpt_misc.h
index 0ecbba4b..58ce83fa 100644
--- a/firmware/include/gpt_misc.h
+++ b/firmware/include/gpt_misc.h
@@ -198,9 +198,11 @@ int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type);
/* Getters and setters for partition attribute fields. */
+int GetEntryLegacyBoot(const GptEntry *e);
int GetEntrySuccessful(const GptEntry *e);
int GetEntryPriority(const GptEntry *e);
int GetEntryTries(const GptEntry *e);
+void SetEntryLegacyBoot(GptEntry *e, int legacy_boot);
void SetEntrySuccessful(GptEntry *e, int successful);
void SetEntryPriority(GptEntry *e, int priority);
void SetEntryTries(GptEntry *e, int tries);
diff --git a/firmware/lib/cgptlib/cgptlib_internal.c b/firmware/lib/cgptlib/cgptlib_internal.c
index 7d402dfb..24b7ba15 100644
--- a/firmware/lib/cgptlib/cgptlib_internal.c
+++ b/firmware/lib/cgptlib/cgptlib_internal.c
@@ -378,6 +378,11 @@ void GptRepair(GptData *gpt)
gpt->valid_entries = MASK_BOTH;
}
+int GetEntryLegacyBoot(const GptEntry *e)
+{
+ return e->attrs.fields.legacy_boot;
+}
+
int GetEntrySuccessful(const GptEntry *e)
{
return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
@@ -402,6 +407,11 @@ int GetEntryTries(const GptEntry *e)
CGPT_ATTRIBUTE_TRIES_OFFSET;
}
+void SetEntryLegacyBoot(GptEntry *e, int legacy_boot)
+{
+ e->attrs.fields.legacy_boot = legacy_boot;
+}
+
void SetEntrySuccessful(GptEntry *e, int successful)
{
if (successful)
diff --git a/firmware/lib/cgptlib/include/cgptlib_internal.h b/firmware/lib/cgptlib/include/cgptlib_internal.h
index b13c4916..cd616e5c 100644
--- a/firmware/lib/cgptlib/include/cgptlib_internal.h
+++ b/firmware/lib/cgptlib/include/cgptlib_internal.h
@@ -26,7 +26,8 @@
* 56 -- success
* 55-52 -- tries
* 51-48 -- priority
- * 47-2 -- UEFI: reserved for future use
+ * 47-3 -- UEFI: reserved for future use
+ * 2 -- UEFI: Legacy BIOS bootable
* 1 -- UEFI: partition is not mapped
* 0 -- UEFI: partition is required
*/
@@ -45,6 +46,9 @@
#define CGPT_ATTRIBUTE_PRIORITY_MASK (CGPT_ATTRIBUTE_MAX_PRIORITY << \
CGPT_ATTRIBUTE_PRIORITY_OFFSET)
+#define CGPT_ATTRIBUTE_LEGACY_BOOT_OFFSET (2)
+#define CGPT_ATTRIBUTE_MAX_LEGACY_BOOT (1ULL)
+
/* Defines ChromeOS-specific limitation on GPT */
#define MIN_SIZE_OF_HEADER 92
#define MAX_SIZE_OF_HEADER 512
diff --git a/host/include/cgpt_params.h b/host/include/cgpt_params.h
index 3f0a71bd..92f0d3a4 100644
--- a/host/include/cgpt_params.h
+++ b/host/include/cgpt_params.h
@@ -32,6 +32,7 @@ typedef struct CgptAddParams {
int successful;
int tries;
int priority;
+ int legacy_boot;
uint32_t raw_value;
int set_begin;
int set_size;
@@ -40,6 +41,7 @@ typedef struct CgptAddParams {
int set_successful;
int set_tries;
int set_priority;
+ int set_legacy_boot;
int set_raw;
} CgptAddParams;
diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c
index 1e8df252..f736fd9a 100644
--- a/tests/cgptlib_test.c
+++ b/tests/cgptlib_test.c
@@ -1131,6 +1131,15 @@ static int EntryAttributeGetSetTest(void)
GptEntry *e = (GptEntry *)(gpt->primary_entries);
e->attrs.whole = 0x0000000000000000ULL;
+ SetEntryLegacyBoot(e, 1);
+ EXPECT(0x0000000000000004ULL == e->attrs.whole);
+ EXPECT(1 == GetEntryLegacyBoot(e));
+ e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
+ SetEntryLegacyBoot(e, 0);
+ EXPECT(0xFFFFFFFFFFFFFFFBULL == e->attrs.whole);
+ EXPECT(0 == GetEntryLegacyBoot(e));
+
+ e->attrs.whole = 0x0000000000000000ULL;
SetEntrySuccessful(e, 1);
EXPECT(0x0100000000000000ULL == e->attrs.whole);
EXPECT(1 == GetEntrySuccessful(e));
@@ -1169,24 +1178,28 @@ static int EntryAttributeGetSetTest(void)
override_priority = 0;
e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
+ EXPECT(1 == GetEntryLegacyBoot(e));
EXPECT(1 == GetEntrySuccessful(e));
EXPECT(15 == GetEntryPriority(e));
EXPECT(15 == GetEntryTries(e));
override_priority = 10;
e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
+ EXPECT(1 == GetEntryLegacyBoot(e));
EXPECT(1 == GetEntrySuccessful(e));
EXPECT(10 == GetEntryPriority(e));
EXPECT(15 == GetEntryTries(e));
override_priority = 0;
- e->attrs.whole = 0x0123000000000000ULL;
+ e->attrs.whole = 0x0123000000000004ULL;
+ EXPECT(1 == GetEntryLegacyBoot(e));
EXPECT(1 == GetEntrySuccessful(e));
EXPECT(2 == GetEntryTries(e));
EXPECT(3 == GetEntryPriority(e));
override_priority = 10;
- e->attrs.whole = 0x0123000000000000ULL;
+ e->attrs.whole = 0x0123000000000004ULL;
+ EXPECT(1 == GetEntryLegacyBoot(e));
EXPECT(1 == GetEntrySuccessful(e));
EXPECT(2 == GetEntryTries(e));
EXPECT(10 == GetEntryPriority(e));
@@ -1194,7 +1207,8 @@ static int EntryAttributeGetSetTest(void)
/* Invalid priority */
override_priority = 100;
- e->attrs.whole = 0x0123000000000000ULL;
+ e->attrs.whole = 0x0123000000000004ULL;
+ EXPECT(1 == GetEntryLegacyBoot(e));
EXPECT(1 == GetEntrySuccessful(e));
EXPECT(2 == GetEntryTries(e));
EXPECT(3 == GetEntryPriority(e));