summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgpt/cgpt.h6
-rw-r--r--cgpt/cgpt_common.c35
-rw-r--r--cgpt/cgpt_repair.c18
-rw-r--r--firmware/lib/cgptlib/cgptlib_internal.c17
-rw-r--r--firmware/lib/cgptlib/include/cgptlib_internal.h3
-rw-r--r--firmware/lib/gpt_misc.c13
-rw-r--r--tests/cgptlib_test.c39
7 files changed, 38 insertions, 93 deletions
diff --git a/cgpt/cgpt.h b/cgpt/cgpt.h
index 2cf9ef5a..23f2f90c 100644
--- a/cgpt/cgpt.h
+++ b/cgpt/cgpt.h
@@ -65,18 +65,16 @@ int DriveClose(struct drive *drive, int update_as_needed);
int CheckValid(const struct drive *drive);
/* Loads sectors from 'drive'.
- * *buf is pointed to an allocated memory when returned, and should be
- * freed.
*
* drive -- open drive.
- * buf -- pointer to buffer pointer
+ * buf -- pointer to buffer of at least (sector_bytes * sector_count) size
* sector -- offset of starting sector (in sectors)
* sector_bytes -- bytes per sector
* sector_count -- number of sectors to load
*
* Returns CGPT_OK for successful. Aborts if any error occurs.
*/
-int Load(struct drive *drive, uint8_t **buf,
+int Load(struct drive *drive, uint8_t *buf,
const uint64_t sector,
const uint64_t sector_bytes,
const uint64_t sector_count);
diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c
index 04eab333..6d3dcdb9 100644
--- a/cgpt/cgpt_common.c
+++ b/cgpt/cgpt_common.c
@@ -76,7 +76,7 @@ int CheckValid(const struct drive *drive) {
return CGPT_OK;
}
-int Load(struct drive *drive, uint8_t **buf,
+int Load(struct drive *drive, uint8_t *buf,
const uint64_t sector,
const uint64_t sector_bytes,
const uint64_t sector_count) {
@@ -96,26 +96,19 @@ int Load(struct drive *drive, uint8_t **buf,
return CGPT_FAILED;
}
count = sector_bytes * sector_count;
- *buf = malloc(count);
- require(*buf);
if (-1 == lseek(drive->fd, sector * sector_bytes, SEEK_SET)) {
Error("Can't seek: %s\n", strerror(errno));
- goto error_free;
+ return CGPT_FAILED;
}
- nread = read(drive->fd, *buf, count);
+ nread = read(drive->fd, buf, count);
if (nread < count) {
Error("Can't read enough: %d, not %d\n", nread, count);
- goto error_free;
+ return CGPT_FAILED;
}
return CGPT_OK;
-
-error_free:
- free(*buf);
- *buf = 0;
- return CGPT_FAILED;
}
@@ -170,19 +163,27 @@ static int GptLoad(struct drive *drive, uint32_t sector_bytes) {
}
drive->gpt.streaming_drive_sectors = drive->size / drive->gpt.sector_bytes;
+ drive->gpt.primary_header = malloc(drive->gpt.sector_bytes);
+ drive->gpt.secondary_header = malloc(drive->gpt.sector_bytes);
+ drive->gpt.primary_entries = malloc(GPT_ENTRIES_ALLOC_SIZE);
+ drive->gpt.secondary_entries = malloc(GPT_ENTRIES_ALLOC_SIZE);
+ if (!drive->gpt.primary_header || !drive->gpt.secondary_header ||
+ !drive->gpt.primary_entries || !drive->gpt.secondary_entries)
+ return -1;
+
/* TODO(namnguyen): Remove this and totally trust gpt_drive_sectors. */
if (!(drive->gpt.flags & GPT_FLAG_EXTERNAL)) {
drive->gpt.gpt_drive_sectors = drive->gpt.streaming_drive_sectors;
} /* Else, we trust gpt.gpt_drive_sectors. */
// Read the data.
- if (CGPT_OK != Load(drive, &drive->gpt.primary_header,
+ if (CGPT_OK != Load(drive, drive->gpt.primary_header,
GPT_PMBR_SECTORS,
drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
Error("Cannot read primary GPT header\n");
return -1;
}
- if (CGPT_OK != Load(drive, &drive->gpt.secondary_header,
+ if (CGPT_OK != Load(drive, drive->gpt.secondary_header,
drive->gpt.gpt_drive_sectors - GPT_PMBR_SECTORS,
drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
Error("Cannot read secondary GPT header\n");
@@ -193,7 +194,7 @@ static int GptLoad(struct drive *drive, uint32_t sector_bytes) {
drive->gpt.gpt_drive_sectors,
drive->gpt.flags,
drive->gpt.sector_bytes) == 0) {
- if (CGPT_OK != Load(drive, &drive->gpt.primary_entries,
+ if (CGPT_OK != Load(drive, drive->gpt.primary_entries,
primary_header->entries_lba,
drive->gpt.sector_bytes,
CalculateEntriesSectors(primary_header,
@@ -205,15 +206,13 @@ static int GptLoad(struct drive *drive, uint32_t sector_bytes) {
Warning("Primary GPT header is %s\n",
memcmp(primary_header->signature, GPT_HEADER_SIGNATURE_IGNORED,
GPT_HEADER_SIGNATURE_SIZE) ? "invalid" : "being ignored");
- drive->gpt.primary_entries = calloc(MAX_NUMBER_OF_ENTRIES,
- sizeof(GptEntry));
}
GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
if (CheckHeader(secondary_header, 1, drive->gpt.streaming_drive_sectors,
drive->gpt.gpt_drive_sectors,
drive->gpt.flags,
drive->gpt.sector_bytes) == 0) {
- if (CGPT_OK != Load(drive, &drive->gpt.secondary_entries,
+ if (CGPT_OK != Load(drive, drive->gpt.secondary_entries,
secondary_header->entries_lba,
drive->gpt.sector_bytes,
CalculateEntriesSectors(secondary_header,
@@ -225,8 +224,6 @@ static int GptLoad(struct drive *drive, uint32_t sector_bytes) {
Warning("Secondary GPT header is %s\n",
memcmp(primary_header->signature, GPT_HEADER_SIGNATURE_IGNORED,
GPT_HEADER_SIGNATURE_SIZE) ? "invalid" : "being ignored");
- drive->gpt.secondary_entries = calloc(MAX_NUMBER_OF_ENTRIES,
- sizeof(GptEntry));
}
return 0;
}
diff --git a/cgpt/cgpt_repair.c b/cgpt/cgpt_repair.c
index fc650883..f06d118e 100644
--- a/cgpt/cgpt_repair.c
+++ b/cgpt/cgpt_repair.c
@@ -24,24 +24,6 @@ int CgptRepair(CgptRepairParams *params) {
printf("GptSanityCheck() returned %d: %s\n",
gpt_retval, GptError(gpt_retval));
- GptHeader *header;
- if (MASK_PRIMARY == drive.gpt.valid_headers ||
- MASK_BOTH == drive.gpt.valid_headers) {
- header = (GptHeader *)(drive.gpt.primary_header);
- } else {
- header = (GptHeader *)(drive.gpt.secondary_header);
- }
-
- if (MASK_PRIMARY == drive.gpt.valid_entries) {
- free(drive.gpt.secondary_entries);
- drive.gpt.secondary_entries =
- malloc(header->size_of_entry * header->number_of_entries);
- } else if (MASK_SECONDARY == drive.gpt.valid_entries) {
- free(drive.gpt.primary_entries);
- drive.gpt.primary_entries =
- malloc(header->size_of_entry * header->number_of_entries);
- }
-
GptRepair(&drive.gpt);
if (drive.gpt.modified & GPT_MODIFIED_HEADER1)
printf("Primary Header is updated.\n");
diff --git a/firmware/lib/cgptlib/cgptlib_internal.c b/firmware/lib/cgptlib/cgptlib_internal.c
index 50ad936a..f4d1c1ec 100644
--- a/firmware/lib/cgptlib/cgptlib_internal.c
+++ b/firmware/lib/cgptlib/cgptlib_internal.c
@@ -261,6 +261,8 @@ int GptSanityCheck(GptData *gpt)
gpt->sector_bytes)) {
gpt->valid_headers |= MASK_PRIMARY;
goodhdr = header1;
+ if (0 == CheckEntries(entries1, goodhdr))
+ gpt->valid_entries |= MASK_PRIMARY;
} else if (header1 && !memcmp(header1->signature,
GPT_HEADER_SIGNATURE_IGNORED, GPT_HEADER_SIGNATURE_SIZE)) {
gpt->ignored |= MASK_PRIMARY;
@@ -271,6 +273,9 @@ int GptSanityCheck(GptData *gpt)
gpt->valid_headers |= MASK_SECONDARY;
if (!goodhdr)
goodhdr = header2;
+ /* Check header1+entries2 if it was good, to catch mismatch. */
+ if (0 == CheckEntries(entries2, goodhdr))
+ gpt->valid_entries |= MASK_SECONDARY;
} else if (header2 && !memcmp(header2->signature,
GPT_HEADER_SIGNATURE_IGNORED, GPT_HEADER_SIGNATURE_SIZE)) {
gpt->ignored |= MASK_SECONDARY;
@@ -280,18 +285,6 @@ int GptSanityCheck(GptData *gpt)
return GPT_ERROR_INVALID_HEADERS;
/*
- * Check if entries are valid.
- *
- * Note that we use the same header in both checks. This way we'll
- * catch the case where (header1,entries1) and (header2,entries2) are
- * both valid, but (entries1 != entries2).
- */
- if (0 == CheckEntries(entries1, goodhdr))
- gpt->valid_entries |= MASK_PRIMARY;
- if (0 == CheckEntries(entries2, goodhdr))
- gpt->valid_entries |= MASK_SECONDARY;
-
- /*
* If both headers are good but neither entries were good, check the
* entries with the secondary header.
*/
diff --git a/firmware/lib/cgptlib/include/cgptlib_internal.h b/firmware/lib/cgptlib/include/cgptlib_internal.h
index d58a35f6..cc01f4ca 100644
--- a/firmware/lib/cgptlib/include/cgptlib_internal.h
+++ b/firmware/lib/cgptlib/include/cgptlib_internal.h
@@ -60,6 +60,9 @@
#define MIN_NUMBER_OF_ENTRIES 16
#define MAX_NUMBER_OF_ENTRIES 128
+/* All GptData.(primary|secondary)_entries must be allocated to this size! */
+#define GPT_ENTRIES_ALLOC_SIZE (MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry))
+
/* Defines GPT sizes */
#define GPT_PMBR_SECTORS 1 /* size (in sectors) of PMBR */
#define GPT_HEADER_SECTORS 1
diff --git a/firmware/lib/gpt_misc.c b/firmware/lib/gpt_misc.c
index dfe9084b..6d91ec15 100644
--- a/firmware/lib/gpt_misc.c
+++ b/firmware/lib/gpt_misc.c
@@ -22,7 +22,6 @@
*/
int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
{
- uint64_t max_entries_bytes = MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry);
int primary_valid = 0, secondary_valid = 0;
/* No data to be written yet */
@@ -34,8 +33,8 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
gptdata->primary_header = (uint8_t *)malloc(gptdata->sector_bytes);
gptdata->secondary_header =
(uint8_t *)malloc(gptdata->sector_bytes);
- gptdata->primary_entries = (uint8_t *)malloc(max_entries_bytes);
- gptdata->secondary_entries = (uint8_t *)malloc(max_entries_bytes);
+ gptdata->primary_entries = (uint8_t *)malloc(GPT_ENTRIES_ALLOC_SIZE);
+ gptdata->secondary_entries = (uint8_t *)malloc(GPT_ENTRIES_ALLOC_SIZE);
if (gptdata->primary_header == NULL ||
gptdata->secondary_header == NULL ||
@@ -60,8 +59,9 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
uint64_t entries_bytes =
(uint64_t)primary_header->number_of_entries
* primary_header->size_of_entry;
- uint64_t entries_sectors = entries_bytes
- / gptdata->sector_bytes;
+ uint64_t entries_sectors =
+ (entries_bytes + gptdata->sector_bytes - 1)
+ / gptdata->sector_bytes;
if (0 != VbExDiskRead(disk_handle,
primary_header->entries_lba,
entries_sectors,
@@ -95,7 +95,8 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
uint64_t entries_bytes =
(uint64_t)secondary_header->number_of_entries
* secondary_header->size_of_entry;
- uint64_t entries_sectors = entries_bytes
+ uint64_t entries_sectors =
+ (entries_bytes + gptdata->sector_bytes - 1)
/ gptdata->sector_bytes;
if (0 != VbExDiskRead(disk_handle,
secondary_header->entries_lba,
diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c
index 669f7969..821ffb13 100644
--- a/tests/cgptlib_test.c
+++ b/tests/cgptlib_test.c
@@ -41,7 +41,7 @@
#define DEFAULT_SECTOR_SIZE 512
#define MAX_SECTOR_SIZE 4096
#define DEFAULT_DRIVE_SECTORS 467
-#define TOTAL_ENTRIES_SIZE (MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry)) /* 16384 */
+#define TOTAL_ENTRIES_SIZE GPT_ENTRIES_ALLOC_SIZE /* 16384 */
#define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
@@ -911,27 +911,27 @@ static int SanityCheckTest(void)
gpt->primary_header[0]++;
EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
EXPECT(MASK_SECONDARY == gpt->valid_headers);
- EXPECT(MASK_BOTH == gpt->valid_entries);
+ EXPECT(MASK_SECONDARY == gpt->valid_entries);
EXPECT(0 == gpt->ignored);
GptRepair(gpt);
EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
EXPECT(MASK_BOTH == gpt->valid_headers);
EXPECT(MASK_BOTH == gpt->valid_entries);
EXPECT(0 == gpt->ignored);
- EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
+ EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
BuildTestGptData(gpt);
gpt->secondary_header[0]++;
EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
EXPECT(MASK_PRIMARY == gpt->valid_headers);
- EXPECT(MASK_BOTH == gpt->valid_entries);
+ EXPECT(MASK_PRIMARY == gpt->valid_entries);
EXPECT(0 == gpt->ignored);
GptRepair(gpt);
EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
EXPECT(MASK_BOTH == gpt->valid_headers);
EXPECT(MASK_BOTH == gpt->valid_entries);
EXPECT(0 == gpt->ignored);
- EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
+ EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
/*
* Modify header1 and update its CRC. Since header2 is now different
@@ -1039,35 +1039,6 @@ static int SanityCheckTest(void)
EXPECT(0 == gpt->ignored);
EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
- /* Test cross-correction (h1+e2, h2+e1) */
- BuildTestGptData(gpt);
- gpt->primary_header[0]++;
- gpt->secondary_entries[0]++;
- EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
- EXPECT(MASK_SECONDARY == gpt->valid_headers);
- EXPECT(MASK_PRIMARY == gpt->valid_entries);
- EXPECT(0 == gpt->ignored);
- GptRepair(gpt);
- EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
- EXPECT(MASK_BOTH == gpt->valid_headers);
- EXPECT(MASK_BOTH == gpt->valid_entries);
- EXPECT(0 == gpt->ignored);
- EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
-
- BuildTestGptData(gpt);
- gpt->secondary_header[0]++;
- gpt->primary_entries[0]++;
- EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
- EXPECT(MASK_PRIMARY == gpt->valid_headers);
- EXPECT(MASK_SECONDARY == gpt->valid_entries);
- EXPECT(0 == gpt->ignored);
- GptRepair(gpt);
- EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
- EXPECT(MASK_BOTH == gpt->valid_headers);
- EXPECT(MASK_BOTH == gpt->valid_entries);
- EXPECT(0 == gpt->ignored);
- EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
-
/*
* Test mismatched pairs (h1+e1 valid, h2+e2 valid but different. This
* simulates a partial update of the drive.