diff options
-rw-r--r-- | cgpt/cgpt_common.c | 61 | ||||
-rw-r--r-- | cgpt/cgpt_show.c | 140 | ||||
-rw-r--r-- | firmware/include/gpt.h | 3 | ||||
-rw-r--r-- | firmware/include/gpt_misc.h | 2 | ||||
-rw-r--r-- | firmware/lib/cgptlib/cgptlib_internal.c | 16 | ||||
-rw-r--r-- | firmware/lib/gpt_misc.c | 66 | ||||
-rw-r--r-- | tests/cgptlib_test.c | 85 |
7 files changed, 249 insertions, 124 deletions
diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c index 2c21cdc2..29fe524a 100644 --- a/cgpt/cgpt_common.c +++ b/cgpt/cgpt_common.c @@ -184,7 +184,11 @@ static int GptLoad(struct drive *drive, uint32_t sector_bytes) { return -1; } } else { - Warning("Primary GPT header is invalid\n"); + 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, @@ -198,41 +202,48 @@ static int GptLoad(struct drive *drive, uint32_t sector_bytes) { return -1; } } else { - Warning("Secondary GPT header is invalid\n"); + 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; } static int GptSave(struct drive *drive) { int errors = 0; - if (drive->gpt.modified & GPT_MODIFIED_HEADER1) { - if (CGPT_OK != Save(drive, drive->gpt.primary_header, - GPT_PMBR_SECTORS, - drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) { - errors++; - Error("Cannot write primary header: %s\n", strerror(errno)); + + if (!(drive->gpt.ignored & MASK_PRIMARY)) { + if (drive->gpt.modified & GPT_MODIFIED_HEADER1) { + if (CGPT_OK != Save(drive, drive->gpt.primary_header, + GPT_PMBR_SECTORS, + drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) { + errors++; + Error("Cannot write primary header: %s\n", strerror(errno)); + } } - } - GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header; - if (drive->gpt.modified & GPT_MODIFIED_ENTRIES1) { - if (CGPT_OK != Save(drive, drive->gpt.primary_entries, - primary_header->entries_lba, - drive->gpt.sector_bytes, - CalculateEntriesSectors(primary_header))) { - errors++; - Error("Cannot write primary entries: %s\n", strerror(errno)); + GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header; + if (drive->gpt.modified & GPT_MODIFIED_ENTRIES1) { + if (CGPT_OK != Save(drive, drive->gpt.primary_entries, + primary_header->entries_lba, + drive->gpt.sector_bytes, + CalculateEntriesSectors(primary_header))) { + errors++; + Error("Cannot write primary entries: %s\n", strerror(errno)); + } } - } - // Sync primary GPT before touching secondary so one is always valid. - if (drive->gpt.modified & (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1)) - if (fsync(drive->fd) < 0 && errno == EIO) { - errors++; - Error("I/O error when trying to write primary GPT\n"); - } + // Sync primary GPT before touching secondary so one is always valid. + if (drive->gpt.modified & (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1)) + if (fsync(drive->fd) < 0 && errno == EIO) { + errors++; + Error("I/O error when trying to write primary GPT\n"); + } + } // Only start writing secondary GPT if primary was written correctly. - if (!errors) { + if (!errors && !(drive->gpt.ignored & MASK_SECONDARY)) { if (drive->gpt.modified & GPT_MODIFIED_HEADER2) { if(CGPT_OK != Save(drive, drive->gpt.secondary_header, drive->gpt.gpt_drive_sectors - GPT_PMBR_SECTORS, diff --git a/cgpt/cgpt_show.c b/cgpt/cgpt_show.c index 143b5fa1..638655bd 100644 --- a/cgpt/cgpt_show.c +++ b/cgpt/cgpt_show.c @@ -250,79 +250,91 @@ static int GptShow(struct drive *drive, CgptShowParams *params) { PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small printf(GPT_FMT, 0, GPT_PMBR_SECTORS, "", buf); - if (drive->gpt.valid_headers & MASK_PRIMARY) { + if (drive->gpt.ignored & MASK_PRIMARY) { printf(GPT_FMT, (int)GPT_PMBR_SECTORS, - (int)GPT_HEADER_SECTORS, "", "Pri GPT header"); + (int)GPT_HEADER_SECTORS, "IGNORED", "Pri GPT header"); } else { - printf(GPT_FMT, (int)GPT_PMBR_SECTORS, - (int)GPT_HEADER_SECTORS, "INVALID", "Pri GPT header"); - } - - if (params->debug || - ((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) { - GptHeader *header; - char indent[64]; + if (drive->gpt.valid_headers & MASK_PRIMARY) { + printf(GPT_FMT, (int)GPT_PMBR_SECTORS, + (int)GPT_HEADER_SECTORS, "", "Pri GPT header"); + } else { + printf(GPT_FMT, (int)GPT_PMBR_SECTORS, + (int)GPT_HEADER_SECTORS, "INVALID", "Pri GPT header"); + } - require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent)); - header = (GptHeader*)drive->gpt.primary_header; - entries = (GptEntry*)drive->gpt.primary_entries; - HeaderDetails(header, entries, indent, params->numeric); - } + if (params->debug || + ((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) { + GptHeader *header; + char indent[64]; - GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header; - printf(GPT_FMT, (int)primary_header->entries_lba, - (int)CalculateEntriesSectors(primary_header), - drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID", - "Pri GPT table"); + require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent)); + header = (GptHeader*)drive->gpt.primary_header; + entries = (GptEntry*)drive->gpt.primary_entries; + HeaderDetails(header, entries, indent, params->numeric); + } - if (params->debug || - (drive->gpt.valid_entries & MASK_PRIMARY)) - EntriesDetails(drive, PRIMARY, params->numeric); + GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header; + printf(GPT_FMT, (int)primary_header->entries_lba, + (int)CalculateEntriesSectors(primary_header), + drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID", + "Pri GPT table"); - /****************************** Secondary *************************/ - GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header; - printf(GPT_FMT, (int)secondary_header->entries_lba, - (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. - * 1. in debug mode. - * 2. only secondary is valid. - * 3. secondary is not identical to promary. - */ - if (params->debug || - ((drive->gpt.valid_entries & MASK_SECONDARY) && - (!(drive->gpt.valid_entries & MASK_PRIMARY) || - memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries, - secondary_header->number_of_entries * - secondary_header->size_of_entry)))) { - EntriesDetails(drive, SECONDARY, params->numeric); + if (params->debug || + (drive->gpt.valid_entries & MASK_PRIMARY)) + EntriesDetails(drive, PRIMARY, params->numeric); } - if (drive->gpt.valid_headers & MASK_SECONDARY) + /****************************** Secondary *************************/ + if (drive->gpt.ignored & MASK_SECONDARY) { printf(GPT_FMT, (int)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS), - (int)GPT_HEADER_SECTORS, "", "Sec GPT header"); - else - printf(GPT_FMT, (int)GPT_PMBR_SECTORS, - (int)GPT_HEADER_SECTORS, "INVALID", "Sec GPT header"); - /* We show secondary header if any of following is true: - * 1. in debug mode. - * 2. only secondary is valid. - * 3. secondary is not synonymous to primary. - */ - if (params->debug || - ((drive->gpt.valid_headers & MASK_SECONDARY) && - (!(drive->gpt.valid_headers & MASK_PRIMARY) || - !IsSynonymous((GptHeader*)drive->gpt.primary_header, - (GptHeader*)drive->gpt.secondary_header)) && - params->verbose)) { - GptHeader *header; - char indent[64]; - - require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent)); - header = (GptHeader*)drive->gpt.secondary_header; - entries = (GptEntry*)drive->gpt.secondary_entries; - HeaderDetails(header, entries, indent, params->numeric); + (int)GPT_HEADER_SECTORS, "IGNORED", "Sec GPT header"); + } else { + GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header; + printf(GPT_FMT, (int)secondary_header->entries_lba, + (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. + * 1. in debug mode. + * 2. primary table is being ignored + * 3. only secondary is valid. + * 4. secondary is not identical to promary. + */ + if (params->debug || (drive->gpt.ignored & MASK_PRIMARY) || + ((drive->gpt.valid_entries & MASK_SECONDARY) && + (!(drive->gpt.valid_entries & MASK_PRIMARY) || + memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries, + secondary_header->number_of_entries * + secondary_header->size_of_entry)))) { + EntriesDetails(drive, SECONDARY, params->numeric); + } + + if (drive->gpt.valid_headers & MASK_SECONDARY) { + printf(GPT_FMT, (int)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS), + (int)GPT_HEADER_SECTORS, "", "Sec GPT header"); + } else { + printf(GPT_FMT, (int)GPT_PMBR_SECTORS, + (int)GPT_HEADER_SECTORS, "INVALID", "Sec GPT header"); + } + /* We show secondary header if any of following is true: + * 1. in debug mode. + * 2. only secondary is valid. + * 3. secondary is not synonymous to primary and not ignored. + */ + if (params->debug || + ((drive->gpt.valid_headers & MASK_SECONDARY) && + (!(drive->gpt.valid_headers & MASK_PRIMARY) || + !IsSynonymous((GptHeader*)drive->gpt.primary_header, + (GptHeader*)drive->gpt.secondary_header)) && + params->verbose)) { + GptHeader *header; + char indent[64]; + + require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent)); + header = (GptHeader*)drive->gpt.secondary_header; + entries = (GptEntry*)drive->gpt.secondary_entries; + HeaderDetails(header, entries, indent, params->numeric); + } } } diff --git a/firmware/include/gpt.h b/firmware/include/gpt.h index ed8bfce7..275b3ae8 100644 --- a/firmware/include/gpt.h +++ b/firmware/include/gpt.h @@ -19,6 +19,9 @@ /* From https://chromium-review.googlesource.com/31264 */ #define GPT_HEADER_SIGNATURE2 "CHROMEOS" +/* From http://crosbug.com/p/52595 */ +#define GPT_HEADER_SIGNATURE_IGNORED "IGNOREME" + /* * The first 3 numbers should be stored in network-endian format according to * the GUID RFC. The UEFI spec appendix A claims they should be stored in diff --git a/firmware/include/gpt_misc.h b/firmware/include/gpt_misc.h index 9f442c49..0ecbba4b 100644 --- a/firmware/include/gpt_misc.h +++ b/firmware/include/gpt_misc.h @@ -108,7 +108,7 @@ typedef struct { int current_kernel; /* Internal variables */ - uint32_t valid_headers, valid_entries; + uint8_t valid_headers, valid_entries, ignored; int current_priority; } GptData; diff --git a/firmware/lib/cgptlib/cgptlib_internal.c b/firmware/lib/cgptlib/cgptlib_internal.c index 29756308..7d402dfb 100644 --- a/firmware/lib/cgptlib/cgptlib_internal.c +++ b/firmware/lib/cgptlib/cgptlib_internal.c @@ -245,6 +245,7 @@ int GptSanityCheck(GptData *gpt) gpt->valid_headers = 0; gpt->valid_entries = 0; + gpt->ignored = 0; retval = CheckParameters(gpt); if (retval != GPT_SUCCESS) @@ -255,12 +256,18 @@ int GptSanityCheck(GptData *gpt) gpt->gpt_drive_sectors, gpt->flags)) { gpt->valid_headers |= MASK_PRIMARY; goodhdr = header1; + } else if (header1 && !Memcmp(header1->signature, + GPT_HEADER_SIGNATURE_IGNORED, GPT_HEADER_SIGNATURE_SIZE)) { + gpt->ignored |= MASK_PRIMARY; } if (0 == CheckHeader(header2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, gpt->flags)) { gpt->valid_headers |= MASK_SECONDARY; if (!goodhdr) goodhdr = header2; + } else if (header2 && !Memcmp(header2->signature, + GPT_HEADER_SIGNATURE_IGNORED, GPT_HEADER_SIGNATURE_SIZE)) { + gpt->ignored |= MASK_SECONDARY; } if (!gpt->valid_headers) @@ -309,6 +316,15 @@ int GptSanityCheck(GptData *gpt) 0 != HeaderFieldsSame(header1, header2)) gpt->valid_headers &= ~MASK_SECONDARY; + /* + * When we're ignoring a GPT, make it look in memory like the other one + * and pretend that everything is fine (until we try to save). + */ + if (MASK_NONE != gpt->ignored) { + GptRepair(gpt); + gpt->modified = 0; + } + return GPT_SUCCESS; } diff --git a/firmware/lib/gpt_misc.c b/firmware/lib/gpt_misc.c index cff9221f..0bf09401 100644 --- a/firmware/lib/gpt_misc.c +++ b/firmware/lib/gpt_misc.c @@ -28,6 +28,8 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) /* No data to be written yet */ gptdata->modified = 0; + /* This should get overwritten by GptInit() */ + gptdata->ignored = 0; /* Allocate all buffers */ gptdata->primary_header = (uint8_t *)VbExMalloc(gptdata->sector_bytes); @@ -67,7 +69,11 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) primary_valid = 0; } } else { - VBDEBUG(("Primary GPT header invalid!\n")); + VBDEBUG(("Primary GPT header is %s\n", + Memcmp(primary_header->signature, + GPT_HEADER_SIGNATURE_IGNORED, + GPT_HEADER_SIGNATURE_SIZE) + ? "invalid" : "being ignored")); } /* Read secondary header from the end of the drive */ @@ -96,7 +102,11 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) secondary_valid = 0; } } else { - VBDEBUG(("Secondary GPT header invalid!\n")); + VBDEBUG(("Secondary GPT header is %s\n", + Memcmp(secondary_header->signature, + GPT_HEADER_SIGNATURE_IGNORED, + GPT_HEADER_SIGNATURE_SIZE) + ? "invalid" : "being ignored")); } /* Return 0 if least one GPT header was valid */ @@ -110,7 +120,7 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) */ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) { - int legacy = 0; + int skip_primary = 0; GptHeader *header = (GptHeader *)gptdata->primary_header; uint64_t entries_bytes = header->number_of_entries * header->size_of_entry; @@ -126,19 +136,16 @@ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) GptHeader *h = (GptHeader *)(gptdata->primary_header); entries_lba = h->entries_lba; - /* - * Avoid even looking at this data if we don't need to. We - * may in fact not have read it from disk if the read failed, - * and this avoids a valgrind complaint. - */ - if (gptdata->modified) { - legacy = !Memcmp(h->signature, GPT_HEADER_SIGNATURE2, - GPT_HEADER_SIGNATURE_SIZE); - } - if (gptdata->modified & GPT_MODIFIED_HEADER1) { - if (legacy) { - VBDEBUG(("Not updating GPT header 1: " + if (gptdata->ignored & MASK_PRIMARY) { + VBDEBUG(("Not updating primary GPT: " + "marked to be ignored.\n")); + skip_primary = 1; + } else if (gptdata->modified & GPT_MODIFIED_HEADER1) { + if (!Memcmp(h->signature, GPT_HEADER_SIGNATURE2, + GPT_HEADER_SIGNATURE_SIZE)) { + VBDEBUG(("Not updating primary GPT: " "legacy mode is enabled.\n")); + skip_primary = 1; } else { VBDEBUG(("Updating GPT header 1\n")); if (0 != VbExDiskWrite(disk_handle, 1, 1, @@ -148,28 +155,23 @@ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) } } - if (gptdata->primary_entries) { + if (gptdata->primary_entries && !skip_primary) { if (gptdata->modified & GPT_MODIFIED_ENTRIES1) { - if (legacy) { - VBDEBUG(("Not updating GPT entries 1: " - "legacy mode is enabled.\n")); - } else { - VBDEBUG(("Updating GPT entries 1\n")); - if (0 != VbExDiskWrite(disk_handle, entries_lba, - entries_sectors, - gptdata->primary_entries)) - goto fail; - } + VBDEBUG(("Updating GPT entries 1\n")); + if (0 != VbExDiskWrite(disk_handle, entries_lba, + entries_sectors, + gptdata->primary_entries)) + goto fail; } } entries_lba = (gptdata->gpt_drive_sectors - entries_sectors - GPT_HEADER_SECTORS); - if (gptdata->secondary_header) { + if (gptdata->secondary_header && !(gptdata->ignored & MASK_SECONDARY)) { GptHeader *h = (GptHeader *)(gptdata->secondary_header); entries_lba = h->entries_lba; if (gptdata->modified & GPT_MODIFIED_HEADER2) { - VBDEBUG(("Updating GPT entries 2\n")); + VBDEBUG(("Updating GPT header 2\n")); if (0 != VbExDiskWrite(disk_handle, gptdata->gpt_drive_sectors - 1, 1, gptdata->secondary_header)) @@ -177,12 +179,12 @@ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) } } - if (gptdata->secondary_entries) { + if (gptdata->secondary_entries && !(gptdata->ignored & MASK_SECONDARY)){ if (gptdata->modified & GPT_MODIFIED_ENTRIES2) { - VBDEBUG(("Updating GPT header 2\n")); + VBDEBUG(("Updating GPT entries 2\n")); if (0 != VbExDiskWrite(disk_handle, - entries_lba, entries_sectors, - gptdata->secondary_entries)) + entries_lba, entries_sectors, + gptdata->secondary_entries)) goto fail; } } diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c index 61747522..1e8df252 100644 --- a/tests/cgptlib_test.c +++ b/tests/cgptlib_test.c @@ -827,6 +827,7 @@ static int SanityCheckTest(void) { GptData *gpt = GetEmptyGptData(); GptHeader *h1 = (GptHeader *)gpt->primary_header; + GptHeader *h2 = (GptHeader *)gpt->secondary_header; GptEntry *e1 = (GptEntry *)gpt->primary_entries; uint8_t *tempptr; @@ -835,11 +836,13 @@ static int SanityCheckTest(void) EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_BOTH == gpt->valid_headers); EXPECT(MASK_BOTH == gpt->valid_entries); + EXPECT(MASK_NONE == gpt->ignored); /* Repair doesn't damage it */ GptRepair(gpt); EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_BOTH == gpt->valid_headers); EXPECT(MASK_BOTH == gpt->valid_entries); + EXPECT(0 == gpt->ignored); EXPECT(0 == gpt->modified); /* Invalid sector size should fail */ @@ -854,11 +857,13 @@ static int SanityCheckTest(void) EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt)); EXPECT(0 == gpt->valid_headers); EXPECT(0 == gpt->valid_entries); + EXPECT(0 == gpt->ignored); /* Repair can't fix completely busted headers */ GptRepair(gpt); EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt)); EXPECT(0 == gpt->valid_headers); EXPECT(0 == gpt->valid_entries); + EXPECT(0 == gpt->ignored); EXPECT(0 == gpt->modified); BuildTestGptData(gpt); @@ -866,10 +871,12 @@ static int SanityCheckTest(void) EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_SECONDARY == gpt->valid_headers); EXPECT(MASK_BOTH == 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); BuildTestGptData(gpt); @@ -877,10 +884,12 @@ static int SanityCheckTest(void) EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_PRIMARY == gpt->valid_headers); EXPECT(MASK_BOTH == 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); /* @@ -893,10 +902,12 @@ static int SanityCheckTest(void) EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_PRIMARY == gpt->valid_headers); EXPECT(MASK_BOTH == 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); /* Modify entries */ @@ -906,11 +917,13 @@ static int SanityCheckTest(void) EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt)); EXPECT(MASK_BOTH == gpt->valid_headers); EXPECT(MASK_NONE == gpt->valid_entries); + EXPECT(0 == gpt->ignored); /* Repair can't fix both copies of entries being bad, either. */ GptRepair(gpt); EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt)); EXPECT(MASK_BOTH == gpt->valid_headers); EXPECT(MASK_NONE == gpt->valid_entries); + EXPECT(0 == gpt->ignored); EXPECT(0 == gpt->modified); BuildTestGptData(gpt); @@ -918,10 +931,12 @@ static int SanityCheckTest(void) EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_BOTH == 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_ENTRIES1 == gpt->modified); BuildTestGptData(gpt); @@ -929,10 +944,12 @@ static int SanityCheckTest(void) EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_BOTH == 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_ENTRIES2 == gpt->modified); /* @@ -949,6 +966,7 @@ static int SanityCheckTest(void) EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_SECONDARY == gpt->valid_headers); EXPECT(MASK_BOTH == gpt->valid_entries); + EXPECT(0 == gpt->ignored); gpt->primary_entries = tempptr; /* Modify both header and entries */ @@ -958,10 +976,12 @@ static int SanityCheckTest(void) EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_SECONDARY == 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_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified); BuildTestGptData(gpt); @@ -970,10 +990,12 @@ static int SanityCheckTest(void) EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_PRIMARY == 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_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified); /* Test cross-correction (h1+e2, h2+e1) */ @@ -983,10 +1005,12 @@ static int SanityCheckTest(void) 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); @@ -995,10 +1019,12 @@ static int SanityCheckTest(void) 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); /* @@ -1011,35 +1037,90 @@ static int SanityCheckTest(void) EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_PRIMARY == 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_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified); /* Test unloaded entry array. */ - gpt = GetEmptyGptData(); BuildTestGptData(gpt); gpt->primary_entries = NULL; EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_SECONDARY == gpt->valid_entries); + EXPECT(0 == gpt->ignored); gpt = GetEmptyGptData(); BuildTestGptData(gpt); gpt->secondary_entries = NULL; EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_PRIMARY == gpt->valid_entries); + EXPECT(0 == gpt->ignored); + gpt = GetEmptyGptData(); /* Test unloaded header. */ - gpt = GetEmptyGptData(); BuildTestGptData(gpt); gpt->primary_header = NULL; EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_SECONDARY == gpt->valid_headers); + EXPECT(0 == gpt->ignored); gpt = GetEmptyGptData(); BuildTestGptData(gpt); gpt->secondary_header = NULL; EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); EXPECT(MASK_PRIMARY == gpt->valid_headers); + EXPECT(0 == gpt->ignored); + gpt = GetEmptyGptData(); + + /* Test correct recognition of IGNOREME in primary GPT. */ + BuildTestGptData(gpt); + Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE); + Memset(gpt->primary_header, 0, sizeof(GptHeader)); + Memcpy(h1->signature, GPT_HEADER_SIGNATURE_IGNORED, + GPT_HEADER_SIGNATURE_SIZE); + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); + EXPECT(MASK_BOTH == gpt->valid_headers); + EXPECT(MASK_BOTH == gpt->valid_entries); + EXPECT(MASK_PRIMARY == gpt->ignored); + EXPECT(0 == gpt->modified); + + /* Test correct recognition of IGNOREME in secondary GPT. */ + BuildTestGptData(gpt); + Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE); + Memset(gpt->secondary_header, 0, sizeof(GptHeader)); + Memcpy(h2->signature, GPT_HEADER_SIGNATURE_IGNORED, + GPT_HEADER_SIGNATURE_SIZE); + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt)); + EXPECT(MASK_BOTH == gpt->valid_headers); + EXPECT(MASK_BOTH == gpt->valid_entries); + EXPECT(MASK_SECONDARY == gpt->ignored); + EXPECT(0 == gpt->modified); + + /* Test that two IGNOREME GPTs are invalid. */ + ZeroHeadersEntries(gpt); + Memcpy(h1->signature, GPT_HEADER_SIGNATURE_IGNORED, + GPT_HEADER_SIGNATURE_SIZE); + Memcpy(h2->signature, GPT_HEADER_SIGNATURE_IGNORED, + GPT_HEADER_SIGNATURE_SIZE); + EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt)); + EXPECT(0 == gpt->valid_headers); + EXPECT(0 == gpt->valid_entries); + EXPECT(MASK_BOTH == gpt->ignored); + EXPECT(0 == gpt->modified); + + /* Test that one IGNOREME GPT and one corrupted one are invalid. */ + BuildTestGptData(gpt); + Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE); + Memset(gpt->primary_header, 0, sizeof(GptHeader)); + Memcpy(h1->signature, GPT_HEADER_SIGNATURE_IGNORED, + GPT_HEADER_SIGNATURE_SIZE); + gpt->secondary_entries[0]++; + EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt)); + EXPECT(MASK_SECONDARY == gpt->valid_headers); + EXPECT(0 == gpt->valid_entries); + EXPECT(MASK_PRIMARY == gpt->ignored); + EXPECT(0 == gpt->modified); return TEST_OK; } |