summaryrefslogtreecommitdiff
path: root/cgpt
diff options
context:
space:
mode:
authorNam T. Nguyen <namnguyen@chromium.org>2014-12-12 09:38:35 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-12-12 23:15:08 +0000
commit3200401242aec1521e7c4a8b1906366fcabfb1a2 (patch)
tree9e26df71f99eb92a09871ad64d66236d133cbe4d /cgpt
parent32a999d2c0e5bf8a1c0f6141d3db77a1dcc6f5af (diff)
downloadvboot-3200401242aec1521e7c4a8b1906366fcabfb1a2.tar.gz
cgpt: Support non-standard (smaller) entries table
The standard says that entries table must be at least 16384 bytes. On some of our devices, the NOR section is only 8 KiB and used to store both primary and secondary tables. On this device, we can only store 24 entries. Therefore, this CL adds support for non-standard entry table. It adjusts the MIN_NUMBER_OF_ENTRIES to 16, and replaces GPT_ENTRIES_SECTORS with CalculateEntriesSectors. BUG=chromium:441812 BRANCH=none TEST=unittest Change-Id: I6b85b35ce5612c7abb22142f8252bd0d45b676c5 Reviewed-on: https://chromium-review.googlesource.com/234996 Reviewed-by: Bill Richardson <wfrichar@chromium.org> Commit-Queue: Nam Nguyen <namnguyen@chromium.org> Tested-by: Nam Nguyen <namnguyen@chromium.org>
Diffstat (limited to 'cgpt')
-rw-r--r--cgpt/cgpt_common.c41
-rw-r--r--cgpt/cgpt_create.c35
-rw-r--r--cgpt/cgpt_show.c7
3 files changed, 52 insertions, 31 deletions
diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c
index b580e33a..ffaa3090 100644
--- a/cgpt/cgpt_common.c
+++ b/cgpt/cgpt_common.c
@@ -176,7 +176,8 @@ static int GptLoad(struct drive *drive, uint32_t sector_bytes) {
drive->gpt.flags) == 0) {
if (CGPT_OK != Load(drive, &drive->gpt.primary_entries,
primary_header->entries_lba,
- drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
+ drive->gpt.sector_bytes,
+ CalculateEntriesSectors(primary_header))) {
Error("Cannot read primary partition entry array\n");
return -1;
}
@@ -189,7 +190,8 @@ static int GptLoad(struct drive *drive, uint32_t sector_bytes) {
drive->gpt.flags) == 0) {
if (CGPT_OK != Load(drive, &drive->gpt.secondary_entries,
secondary_header->entries_lba,
- drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
+ drive->gpt.sector_bytes,
+ CalculateEntriesSectors(secondary_header))) {
Error("Cannot read secondary partition entry array\n");
return -1;
}
@@ -222,7 +224,8 @@ static int GptSave(struct drive *drive) {
if (drive->gpt.modified & GPT_MODIFIED_ENTRIES1) {
if (CGPT_OK != Save(drive, drive->gpt.primary_entries,
primary_header->entries_lba,
- drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
+ drive->gpt.sector_bytes,
+ CalculateEntriesSectors(primary_header))) {
errors++;
Error("Cannot write primary entries: %s\n", strerror(errno));
}
@@ -231,7 +234,8 @@ static int GptSave(struct drive *drive) {
if (drive->gpt.modified & GPT_MODIFIED_ENTRIES2) {
if (CGPT_OK != Save(drive, drive->gpt.secondary_entries,
secondary_header->entries_lba,
- drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
+ drive->gpt.sector_bytes,
+ CalculateEntriesSectors(secondary_header))) {
errors++;
Error("Cannot write secondary entries: %s\n", strerror(errno));
}
@@ -808,12 +812,16 @@ void UpdateCrc(GptData *gpt) {
if (gpt->modified & GPT_MODIFIED_ENTRIES1 &&
memcmp(primary_header, GPT_HEADER_SIGNATURE2,
GPT_HEADER_SIGNATURE_SIZE)) {
+ size_t entries_size = primary_header->size_of_entry *
+ primary_header->number_of_entries;
primary_header->entries_crc32 =
- Crc32(gpt->primary_entries, TOTAL_ENTRIES_SIZE);
+ Crc32(gpt->primary_entries, entries_size);
}
if (gpt->modified & GPT_MODIFIED_ENTRIES2) {
+ size_t entries_size = secondary_header->size_of_entry *
+ secondary_header->number_of_entries;
secondary_header->entries_crc32 =
- Crc32(gpt->secondary_entries, TOTAL_ENTRIES_SIZE);
+ Crc32(gpt->secondary_entries, entries_size);
}
if (gpt->modified & GPT_MODIFIED_HEADER1) {
primary_header->header_crc32 = 0;
@@ -867,17 +875,26 @@ uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) {
if (!memcmp(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE))
return 0;
+ if (gpt->valid_headers & MASK_PRIMARY) {
+ h = (GptHeader*)gpt->primary_header;
+ } else if (gpt->valid_headers & MASK_SECONDARY) {
+ h = (GptHeader*)gpt->secondary_header;
+ } else {
+ /* We cannot trust any header, don't update entries. */
+ return 0;
+ }
+
+ size_t entries_size = h->number_of_entries * h->size_of_entry;
if (valid_entries == MASK_BOTH) {
- if (memcmp(gpt->primary_entries, gpt->secondary_entries,
- TOTAL_ENTRIES_SIZE)) {
- memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE);
+ if (memcmp(gpt->primary_entries, gpt->secondary_entries, entries_size)) {
+ memcpy(gpt->secondary_entries, gpt->primary_entries, entries_size);
return GPT_MODIFIED_ENTRIES2;
}
} else if (valid_entries == MASK_PRIMARY) {
- memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE);
+ memcpy(gpt->secondary_entries, gpt->primary_entries, entries_size);
return GPT_MODIFIED_ENTRIES2;
} else if (valid_entries == MASK_SECONDARY) {
- memcpy(gpt->primary_entries, gpt->secondary_entries, TOTAL_ENTRIES_SIZE);
+ memcpy(gpt->primary_entries, gpt->secondary_entries, entries_size);
return GPT_MODIFIED_ENTRIES1;
}
@@ -922,7 +939,7 @@ uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) {
secondary_header->my_lba = gpt->gpt_drive_sectors - 1; /* the last sector */
secondary_header->alternate_lba = primary_header->my_lba;
secondary_header->entries_lba = secondary_header->my_lba -
- GPT_ENTRIES_SECTORS;
+ CalculateEntriesSectors(primary_header);
return GPT_MODIFIED_HEADER2;
} else if (valid_headers == MASK_SECONDARY) {
memcpy(primary_header, secondary_header, sizeof(GptHeader));
diff --git a/cgpt/cgpt_create.c b/cgpt/cgpt_create.c
index 2265c8f9..64f3f4d2 100644
--- a/cgpt/cgpt_create.c
+++ b/cgpt/cgpt_create.c
@@ -29,10 +29,6 @@ static int GptCreate(struct drive *drive, CgptCreateParams *params) {
drive->gpt.sector_bytes * GPT_HEADER_SECTORS);
AllocAndClear(&drive->gpt.secondary_header,
drive->gpt.sector_bytes * GPT_HEADER_SECTORS);
- AllocAndClear(&drive->gpt.primary_entries,
- drive->gpt.sector_bytes * GPT_ENTRIES_SECTORS);
- AllocAndClear(&drive->gpt.secondary_entries,
- drive->gpt.sector_bytes * GPT_ENTRIES_SECTORS);
drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
@@ -45,21 +41,12 @@ static int GptCreate(struct drive *drive, CgptCreateParams *params) {
h->size = sizeof(GptHeader);
h->my_lba = GPT_PMBR_SECTORS; /* The second sector on drive. */
h->alternate_lba = drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS;
- h->entries_lba = h->my_lba + GPT_HEADER_SECTORS;
- if (!(drive->gpt.flags & GPT_FLAG_EXTERNAL)) {
- h->entries_lba += params->padding;
- h->first_usable_lba = h->entries_lba + GPT_ENTRIES_SECTORS;
- h->last_usable_lba = (drive->gpt.streaming_drive_sectors -
- GPT_HEADER_SECTORS -
- GPT_ENTRIES_SECTORS - 1);
- } else {
- h->first_usable_lba = params->padding;
- h->last_usable_lba = (drive->gpt.streaming_drive_sectors - 1);
- }
if (CGPT_OK != GenerateGuid(&h->disk_uuid)) {
Error("Unable to generate new GUID.\n");
return -1;
}
+
+ /* Calculate number of entries */
h->size_of_entry = sizeof(GptEntry);
h->number_of_entries = TOTAL_ENTRIES_SIZE / h->size_of_entry;
if (drive->gpt.flags & GPT_FLAG_EXTERNAL) {
@@ -69,7 +56,7 @@ static int GptCreate(struct drive *drive, CgptCreateParams *params) {
Error("Not enough space for a GPT header.\n");
return -1;
}
- half_size_sectors -= GPT_HEADER_SECTORS;
+ half_size_sectors -= (GPT_HEADER_SECTORS + GPT_PMBR_SECTORS);
size_t half_size = half_size_sectors * drive->gpt.sector_bytes;
if (half_size < (MIN_NUMBER_OF_ENTRIES * h->size_of_entry)) {
Error("Not enough space for minimum number of entries.\n");
@@ -80,6 +67,22 @@ static int GptCreate(struct drive *drive, CgptCreateParams *params) {
}
}
+ /* Then use number of entries to calculate entries_lba. */
+ h->entries_lba = h->my_lba + GPT_HEADER_SECTORS;
+ if (!(drive->gpt.flags & GPT_FLAG_EXTERNAL)) {
+ h->entries_lba += params->padding;
+ h->first_usable_lba = h->entries_lba + CalculateEntriesSectors(h);
+ h->last_usable_lba = (drive->gpt.streaming_drive_sectors - GPT_HEADER_SECTORS -
+ CalculateEntriesSectors(h) - 1);
+ } else {
+ h->first_usable_lba = params->padding;
+ h->last_usable_lba = (drive->gpt.streaming_drive_sectors - 1);
+ }
+
+ size_t entries_size = h->number_of_entries * h->size_of_entry;
+ AllocAndClear(&drive->gpt.primary_entries, entries_size);
+ AllocAndClear(&drive->gpt.secondary_entries, entries_size);
+
// Copy to secondary
RepairHeader(&drive->gpt, MASK_PRIMARY);
diff --git a/cgpt/cgpt_show.c b/cgpt/cgpt_show.c
index 68a185cb..143b5fa1 100644
--- a/cgpt/cgpt_show.c
+++ b/cgpt/cgpt_show.c
@@ -271,7 +271,7 @@ static int GptShow(struct drive *drive, CgptShowParams *params) {
GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header;
printf(GPT_FMT, (int)primary_header->entries_lba,
- (int)GPT_ENTRIES_SECTORS,
+ (int)CalculateEntriesSectors(primary_header),
drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
"Pri GPT table");
@@ -282,7 +282,7 @@ static int GptShow(struct drive *drive, CgptShowParams *params) {
/****************************** Secondary *************************/
GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
printf(GPT_FMT, (int)secondary_header->entries_lba,
- (int)GPT_ENTRIES_SECTORS,
+ (int)CalculateEntriesSectors(secondary_header),
drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
"Sec GPT table");
/* We show secondary table details if any of following is true.
@@ -294,7 +294,8 @@ static int GptShow(struct drive *drive, CgptShowParams *params) {
((drive->gpt.valid_entries & MASK_SECONDARY) &&
(!(drive->gpt.valid_entries & MASK_PRIMARY) ||
memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries,
- TOTAL_ENTRIES_SIZE)))) {
+ secondary_header->number_of_entries *
+ secondary_header->size_of_entry)))) {
EntriesDetails(drive, SECONDARY, params->numeric);
}