summaryrefslogtreecommitdiff
path: root/firmware/lib/cgptlib/cgptlib_internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/lib/cgptlib/cgptlib_internal.c')
-rw-r--r--firmware/lib/cgptlib/cgptlib_internal.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/firmware/lib/cgptlib/cgptlib_internal.c b/firmware/lib/cgptlib/cgptlib_internal.c
index 4eea03df..e9f27c96 100644
--- a/firmware/lib/cgptlib/cgptlib_internal.c
+++ b/firmware/lib/cgptlib/cgptlib_internal.c
@@ -20,6 +20,16 @@ int CheckParameters(GptData *gpt)
return GPT_ERROR_INVALID_SECTOR_SIZE;
/*
+ * gpt_drive_sectors should be reasonable. It cannot be unset, and it cannot
+ * differ from drive_sectors if the GPT structs are stored on same device.
+ */
+ if (gpt->gpt_drive_sectors == 0 ||
+ (gpt->stored_on_device == GPT_STORED_ON_DEVICE &&
+ gpt->gpt_drive_sectors != gpt->drive_sectors)) {
+ return GPT_ERROR_INVALID_SECTOR_NUMBER;
+ }
+
+ /*
* Sector count of a drive should be reasonable. If the given value is
* too small to contain basic GPT structure (PMBR + Headers + Entries),
* the value is wrong.
@@ -43,7 +53,8 @@ uint32_t HeaderCrc(GptHeader *h)
return crc32;
}
-int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors)
+int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors,
+ uint8_t stored_on_device)
{
if (!h)
return 1;
@@ -80,7 +91,8 @@ int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors)
return 1;
if ((h->number_of_entries < MIN_NUMBER_OF_ENTRIES) ||
(h->number_of_entries > MAX_NUMBER_OF_ENTRIES) ||
- (h->number_of_entries * h->size_of_entry != TOTAL_ENTRIES_SIZE))
+ (stored_on_device == GPT_STORED_ON_DEVICE &&
+ h->number_of_entries * h->size_of_entry != TOTAL_ENTRIES_SIZE))
return 1;
/*
@@ -100,18 +112,27 @@ int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors)
return 1;
}
+ /* FirstUsableLBA <= LastUsableLBA. */
+ if (h->first_usable_lba > h->last_usable_lba)
+ return 1;
+
+ if (stored_on_device != GPT_STORED_ON_DEVICE) {
+ if (h->last_usable_lba >= drive_sectors) {
+ return 1;
+ }
+ return 0;
+ }
+
/*
* FirstUsableLBA must be after the end of the primary GPT table array.
* LastUsableLBA must be before the start of the secondary GPT table
- * array. FirstUsableLBA <= LastUsableLBA.
+ * array.
*/
/* TODO(namnguyen): Also check for padding between header & entries. */
if (h->first_usable_lba < 2 + GPT_ENTRIES_SECTORS)
return 1;
if (h->last_usable_lba >= drive_sectors - 1 - GPT_ENTRIES_SECTORS)
return 1;
- if (h->first_usable_lba > h->last_usable_lba)
- return 1;
/* Success */
return 0;
@@ -224,11 +245,11 @@ int GptSanityCheck(GptData *gpt)
return retval;
/* Check both headers; we need at least one valid header. */
- if (0 == CheckHeader(header1, 0, gpt->drive_sectors)) {
+ if (0 == CheckHeader(header1, 0, gpt->drive_sectors, gpt->stored_on_device)) {
gpt->valid_headers |= MASK_PRIMARY;
goodhdr = header1;
}
- if (0 == CheckHeader(header2, 1, gpt->drive_sectors)) {
+ if (0 == CheckHeader(header2, 1, gpt->drive_sectors, gpt->stored_on_device)) {
gpt->valid_headers |= MASK_SECONDARY;
if (!goodhdr)
goodhdr = header2;