| Index: src/platform/vboot_reference/tests/cgptlib_test.c
|
| diff --git a/src/platform/vboot_reference/tests/cgptlib_test.c b/src/platform/vboot_reference/tests/cgptlib_test.c
|
| index 72fb5e6c21226a5c736e07e30f884bd6fe3600c6..11b44fb2d89744c59f50795b80e71dbfa89a89ed 100644
|
| --- a/src/platform/vboot_reference/tests/cgptlib_test.c
|
| +++ b/src/platform/vboot_reference/tests/cgptlib_test.c
|
| @@ -3,14 +3,14 @@
|
| * found in the LICENSE file.
|
| */
|
|
|
| -#include "cgptlib_test.h"
|
| #include <string.h>
|
| +
|
| #include "cgptlib.h"
|
| #include "cgptlib_internal.h"
|
| +#include "cgptlib_test.h"
|
| #include "crc32.h"
|
| #include "crc32_test.h"
|
| #include "gpt.h"
|
| -#include "quick_sort_test.h"
|
| #include "utility.h"
|
|
|
| /* Testing partition layout (sector_bytes=512)
|
| @@ -29,19 +29,26 @@
|
| * 467
|
| */
|
| #define KERNEL_A 0
|
| -#define ROOTFS_A 1
|
| -#define ROOTFS_B 2
|
| -#define KERNEL_B 3
|
| +#define KERNEL_B 1
|
| +#define ROOTFS_A 2
|
| +#define ROOTFS_B 3
|
| +#define KERNEL_X 2 /* Overload ROOTFS_A, for some GetNext tests */
|
| +#define KERNEL_Y 3 /* Overload ROOTFS_B, for some GetNext tests */
|
|
|
| #define DEFAULT_SECTOR_SIZE 512
|
| #define MAX_SECTOR_SIZE 4096
|
| #define DEFAULT_DRIVE_SECTORS 467
|
| #define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
|
|
|
| +static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
|
| +static const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
|
| +static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
|
| +
|
| +
|
| /* Given a GptData pointer, first re-calculate entries CRC32 value,
|
| * then reset header CRC32 value to 0, and calculate header CRC32 value.
|
| * Both primary and secondary are updated. */
|
| -void RefreshCrc32(GptData *gpt) {
|
| +static void RefreshCrc32(GptData* gpt) {
|
| GptHeader *header, *header2;
|
| GptEntry *entries, *entries2;
|
|
|
| @@ -62,25 +69,29 @@ void RefreshCrc32(GptData *gpt) {
|
| header2->header_crc32 = Crc32((uint8_t*)header2, header2->size);
|
| }
|
|
|
| -void ZeroHeaders(GptData* gpt) {
|
| +
|
| +static void ZeroHeaders(GptData* gpt) {
|
| Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
|
| Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
|
| }
|
|
|
| -void ZeroEntries(GptData* gpt) {
|
| +
|
| +static void ZeroEntries(GptData* gpt) {
|
| Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
|
| Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
|
| }
|
|
|
| -void ZeroHeadersEntries(GptData* gpt) {
|
| +
|
| +static void ZeroHeadersEntries(GptData* gpt) {
|
| ZeroHeaders(gpt);
|
| ZeroEntries(gpt);
|
| }
|
|
|
| +
|
| /* Returns a pointer to a static GptData instance (no free is required).
|
| * All fields are zero except 4 pointers linking to header and entries.
|
| * All content of headers and entries are zero. */
|
| -GptData* GetEmptyGptData() {
|
| +static GptData* GetEmptyGptData() {
|
| static GptData gpt;
|
| static uint8_t primary_header[MAX_SECTOR_SIZE];
|
| static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
|
| @@ -100,12 +111,13 @@ GptData* GetEmptyGptData() {
|
| return &gpt;
|
| }
|
|
|
| +
|
| /* Fills in most of fields and creates the layout described in the top of this
|
| * file. Before calling this function, primary/secondary header/entries must
|
| * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
|
| * This function returns a good (valid) copy of GPT layout described in top of
|
| * this file. */
|
| -void BuildTestGptData(GptData *gpt) {
|
| +static void BuildTestGptData(GptData* gpt) {
|
| GptHeader *header, *header2;
|
| GptEntry *entries, *entries2;
|
| Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
|
| @@ -116,15 +128,18 @@ void BuildTestGptData(GptData *gpt) {
|
| gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
|
| gpt->valid_headers = MASK_BOTH;
|
| gpt->valid_entries = MASK_BOTH;
|
| + gpt->modified = 0;
|
|
|
| /* build primary */
|
| header = (GptHeader*)gpt->primary_header;
|
| entries = (GptEntry*)gpt->primary_entries;
|
| - Memcpy(header->signature, GPT_HEADER_SIGNATURE, sizeof(GPT_HEADER_SIGNATURE));
|
| + Memcpy(header->signature, GPT_HEADER_SIGNATURE,
|
| + sizeof(GPT_HEADER_SIGNATURE));
|
| header->revision = GPT_HEADER_REVISION;
|
| header->size = sizeof(GptHeader) - sizeof(header->padding);
|
| header->reserved = 0;
|
| header->my_lba = 1;
|
| + header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
|
| header->first_usable_lba = 34;
|
| header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */
|
| header->entries_lba = 2;
|
| @@ -135,14 +150,14 @@ void BuildTestGptData(GptData *gpt) {
|
| entries[0].ending_lba = 133;
|
| Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
|
| entries[1].starting_lba = 134;
|
| - entries[1].ending_lba = 233;
|
| + entries[1].ending_lba = 232;
|
| Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
|
| entries[2].starting_lba = 234;
|
| - entries[2].ending_lba = 333;
|
| + entries[2].ending_lba = 331;
|
| Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
|
| entries[3].starting_lba = 334;
|
| - entries[3].ending_lba = 433;
|
| - header->padding = 0;
|
| + entries[3].ending_lba = 430;
|
| + Memset(header->padding, 0, sizeof(header->padding));
|
|
|
| /* build secondary */
|
| header2 = (GptHeader*)gpt->secondary_header;
|
| @@ -150,56 +165,30 @@ void BuildTestGptData(GptData *gpt) {
|
| Memcpy(header2, header, sizeof(GptHeader));
|
| Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
|
| header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */
|
| + header2->alternate_lba = 1;
|
| header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */
|
|
|
| RefreshCrc32(gpt);
|
| }
|
|
|
| -/* Dumps memory starting from [vp] with [len] bytes.
|
| - * Prints [memo] if not NULL. Example output:
|
| - *
|
| - * 00 01 02 03 04 05 06 07 - 08 09 0a 0b 0c 0d 0e 0f
|
| - * 10 11 12 13 14 15 16 17 - 18 19 1a 1b 1c 1d 1e 1f
|
| - * ...
|
| - */
|
| -static void Dump(void *vp, int len, char* memo) {
|
| - uint8_t *start = vp;
|
| - int i;
|
| - if (memo) printf("--[%s]----------\n", memo);
|
| - for (i = 0; i < len; ++i) {
|
| - printf("%02x%s", start[i],
|
| - (!(~i & 15) ? "\n" :
|
| - !(~i & 7) ? " - ": " "));
|
| - }
|
| - if (i&15) printf("\n");
|
| -}
|
| -
|
| -/* More formatted dump with GptData. */
|
| -void DumpGptData(GptData *gpt) {
|
| - printf("DumpGptData(%p)...\n", gpt);
|
| - Dump(gpt, sizeof(gpt), NULL);
|
| - Dump(gpt->primary_header, sizeof(GptHeader), "Primary header");
|
| - Dump(gpt->primary_entries, sizeof(GptEntry) * 8, "Primary entries");
|
| - Dump(gpt->secondary_header, sizeof(GptHeader), "Secondary header");
|
| - Dump(gpt->secondary_entries, sizeof(GptEntry) * 8,
|
| - "Secondary entries");
|
| -}
|
|
|
| /* Tests if the default structure returned by BuildTestGptData() is good. */
|
| -int TestBuildTestGptData() {
|
| - GptData *gpt;
|
| +static int TestBuildTestGptData() {
|
| + GptData* gpt;
|
| +
|
| gpt = GetEmptyGptData();
|
| BuildTestGptData(gpt);
|
| EXPECT(GPT_SUCCESS == GptInit(gpt));
|
| return TEST_OK;
|
| }
|
|
|
| +
|
| /* Tests if wrong sector_bytes or drive_sectors is detected by GptInit().
|
| * Currently we only support 512 bytes per sector.
|
| * In the future, we may support other sizes.
|
| * A too small drive_sectors should be rejected by GptInit(). */
|
| -int ParameterTests() {
|
| - GptData *gpt;
|
| +static int ParameterTests() {
|
| + GptData* gpt;
|
| struct {
|
| uint32_t sector_bytes;
|
| uint64_t drive_sectors;
|
| @@ -226,316 +215,287 @@ int ParameterTests() {
|
| return TEST_OK;
|
| }
|
|
|
| +
|
| +/* Tests if header CRC in two copies are calculated. */
|
| +static int HeaderCrcTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| +
|
| + BuildTestGptData(gpt);
|
| + EXPECT(HeaderCrc(h1) == h1->header_crc32);
|
| +
|
| + /* CRC covers first byte of header */
|
| + BuildTestGptData(gpt);
|
| + gpt->primary_header[0] ^= 0xa5;
|
| + EXPECT(HeaderCrc(h1) != h1->header_crc32);
|
| +
|
| + /* CRC covers last byte of header */
|
| + BuildTestGptData(gpt);
|
| + gpt->primary_header[h1->size - 1] ^= 0x5a;
|
| + EXPECT(HeaderCrc(h1) != h1->header_crc32);
|
| +
|
| + /* CRC only covers header */
|
| + BuildTestGptData(gpt);
|
| + gpt->primary_header[h1->size] ^= 0x5a;
|
| + EXPECT(HeaderCrc(h1) == h1->header_crc32);
|
| +
|
| + return TEST_OK;
|
| +}
|
| +
|
| +
|
| /* Tests if signature ("EFI PART") is checked. */
|
| -int SignatureTest() {
|
| +static int SignatureTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptHeader* h2 = (GptHeader*)gpt->secondary_header;
|
| int i;
|
| - GptData *gpt;
|
| - int test_mask;
|
| - GptHeader *headers[2];
|
|
|
| - gpt = GetEmptyGptData();
|
| - headers[PRIMARY] = (GptHeader*)gpt->primary_header;
|
| - headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
|
| -
|
| - for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
|
| - for (i = 0; i < 8; ++i) {
|
| - BuildTestGptData(gpt);
|
| - if (test_mask & MASK_PRIMARY)
|
| - headers[PRIMARY]->signature[i] ^= 0xff;
|
| - if (test_mask & MASK_SECONDARY)
|
| - headers[SECONDARY]->signature[i] ^= 0xff;
|
| - EXPECT((MASK_BOTH ^ test_mask) == CheckHeaderSignature(gpt));
|
| - }
|
| + for (i = 0; i < 8; ++i) {
|
| + BuildTestGptData(gpt);
|
| + h1->signature[i] ^= 0xff;
|
| + h2->signature[i] ^= 0xff;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
| }
|
|
|
| return TEST_OK;
|
| }
|
|
|
| +
|
| /* The revision we currently support is GPT_HEADER_REVISION.
|
| * If the revision in header is not that, we expect the header is invalid. */
|
| -int RevisionTest() {
|
| - GptData *gpt;
|
| +static int RevisionTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptHeader* h2 = (GptHeader*)gpt->secondary_header;
|
| + int i;
|
| +
|
| struct {
|
| uint32_t value_to_test;
|
| - int is_valid_value;
|
| + int expect_rv;
|
| } cases[] = {
|
| - {0x01000000, 0},
|
| - {0x00010000, 1}, /* GPT_HEADER_REVISION */
|
| - {0x00000100, 0},
|
| - {0x00000001, 0},
|
| - {0x23010456, 0},
|
| + {0x01000000, 1},
|
| + {0x00010000, 0}, /* GPT_HEADER_REVISION */
|
| + {0x00000100, 1},
|
| + {0x00000001, 1},
|
| + {0x23010456, 1},
|
| };
|
| - int i;
|
| - int test_mask;
|
| - GptHeader *headers[2];
|
| - uint32_t valid_headers;
|
| -
|
| - gpt = GetEmptyGptData();
|
| - headers[PRIMARY] = (GptHeader*)gpt->primary_header;
|
| - headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
|
|
|
| for (i = 0; i < ARRAY_SIZE(cases); ++i) {
|
| - for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
|
| - BuildTestGptData(gpt);
|
| - if (test_mask & MASK_PRIMARY)
|
| - headers[PRIMARY]->revision = cases[i].value_to_test;
|
| - if (test_mask & MASK_SECONDARY)
|
| - headers[SECONDARY]->revision = cases[i].value_to_test;
|
| - valid_headers = CheckRevision(gpt);
|
| - if (cases[i].is_valid_value)
|
| - EXPECT(MASK_BOTH == valid_headers);
|
| - else
|
| - EXPECT((MASK_BOTH ^ test_mask) == valid_headers);
|
| - }
|
| + BuildTestGptData(gpt);
|
| + h1->revision = cases[i].value_to_test;
|
| + h2->revision = cases[i].value_to_test;
|
| + RefreshCrc32(gpt);
|
| +
|
| + EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
|
| + EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
|
| }
|
| return TEST_OK;
|
| }
|
|
|
| -int SizeTest() {
|
| - GptData *gpt;
|
| +
|
| +static int SizeTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptHeader* h2 = (GptHeader*)gpt->secondary_header;
|
| + int i;
|
| +
|
| struct {
|
| uint32_t value_to_test;
|
| - int is_valid_value;
|
| + int expect_rv;
|
| } cases[] = {
|
| - {91, 0},
|
| - {92, 1},
|
| - {93, 1},
|
| - {511, 1},
|
| - {512, 1},
|
| - {513, 0},
|
| + {91, 1},
|
| + {92, 0},
|
| + {93, 0},
|
| + {511, 0},
|
| + {512, 0},
|
| + {513, 1},
|
| };
|
| - int i;
|
| - int test_mask;
|
| - GptHeader *headers[2];
|
| - uint32_t valid_headers;
|
| -
|
| - gpt = GetEmptyGptData();
|
| - headers[PRIMARY] = (GptHeader*)gpt->primary_header;
|
| - headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
|
|
|
| for (i = 0; i < ARRAY_SIZE(cases); ++i) {
|
| - for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
|
| - BuildTestGptData(gpt);
|
| - if (test_mask & MASK_PRIMARY)
|
| - headers[PRIMARY]->size = cases[i].value_to_test;
|
| - if (test_mask & MASK_SECONDARY)
|
| - headers[SECONDARY]->size = cases[i].value_to_test;
|
| - valid_headers = CheckSize(gpt);
|
| - if (cases[i].is_valid_value)
|
| - EXPECT(MASK_BOTH == valid_headers);
|
| - else
|
| - EXPECT((MASK_BOTH ^ test_mask) == valid_headers);
|
| - }
|
| + BuildTestGptData(gpt);
|
| + h1->size = cases[i].value_to_test;
|
| + h2->size = cases[i].value_to_test;
|
| + RefreshCrc32(gpt);
|
| +
|
| + EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
|
| + EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
|
| }
|
| return TEST_OK;
|
| }
|
|
|
| -/* Tests if reserved fields are checked.
|
| - * We'll try non-zero values to test. */
|
| -int ReservedFieldsTest() {
|
| - GptData *gpt;
|
| - GptHeader *primary_header, *secondary_header;
|
|
|
| - gpt = GetEmptyGptData();
|
| - primary_header = (GptHeader*)gpt->primary_header;
|
| - secondary_header = (GptHeader*)gpt->secondary_header;
|
| +/* Tests if CRC is checked. */
|
| +static int CrcFieldTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptHeader* h2 = (GptHeader*)gpt->secondary_header;
|
|
|
| - /* expect secondary is still valid. */
|
| BuildTestGptData(gpt);
|
| - primary_header->reserved ^= 0x12345678; /* whatever random */
|
| - EXPECT(MASK_SECONDARY == CheckReservedFields(gpt));
|
| + /* Modify a field that the header verification doesn't care about */
|
| + h1->entries_crc32++;
|
| + h2->entries_crc32++;
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
| + /* Refresh the CRC; should pass now */
|
| + RefreshCrc32(gpt);
|
| + EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
|
|
|
| - /* expect secondary is still valid. */
|
| - BuildTestGptData(gpt);
|
| - primary_header->padding ^= 0x12345678; /* whatever random */
|
| - EXPECT(MASK_SECONDARY == CheckReservedFields(gpt));
|
| + return TEST_OK;
|
| +}
|
| +
|
| +
|
| +/* Tests if reserved fields are checked.
|
| + * We'll try non-zero values to test. */
|
| +static int ReservedFieldsTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptHeader* h2 = (GptHeader*)gpt->secondary_header;
|
|
|
| - /* expect primary is still valid. */
|
| BuildTestGptData(gpt);
|
| - secondary_header->reserved ^= 0x12345678; /* whatever random */
|
| - EXPECT(MASK_PRIMARY == CheckReservedFields(gpt));
|
| + h1->reserved ^= 0x12345678; /* whatever random */
|
| + h2->reserved ^= 0x12345678; /* whatever random */
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
|
|
| - /* expect primary is still valid. */
|
| +#ifdef PADDING_CHECKED
|
| + /* TODO: padding check is currently disabled */
|
| BuildTestGptData(gpt);
|
| - secondary_header->padding ^= 0x12345678; /* whatever random */
|
| - EXPECT(MASK_PRIMARY == CheckReservedFields(gpt));
|
| + h1->padding[12] ^= 0x34; /* whatever random */
|
| + h2->padding[56] ^= 0x78; /* whatever random */
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
| +#endif
|
|
|
| return TEST_OK;
|
| }
|
|
|
| -/* Tests if myLBA field is checked (1 for primary, last for secondary). */
|
| -int MyLbaTest() {
|
| - GptData *gpt;
|
| - int test_mask;
|
| - GptHeader *headers[2];
|
| - uint32_t valid_headers;
|
|
|
| - gpt = GetEmptyGptData();
|
| - headers[PRIMARY] = (GptHeader*)gpt->primary_header;
|
| - headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
|
| -
|
| - for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
|
| - BuildTestGptData(gpt);
|
| - if (test_mask & MASK_PRIMARY)
|
| - ++headers[PRIMARY]->my_lba;
|
| - if (test_mask & MASK_SECONDARY)
|
| - --headers[SECONDARY]->my_lba;
|
| - valid_headers = CheckMyLba(gpt);
|
| - EXPECT((MASK_BOTH ^ test_mask) == valid_headers);
|
| - }
|
| - return TEST_OK;
|
| -}
|
| +/* Technically, any size which is 2^N where N > 6 should work, but our
|
| + * library only supports one size. */
|
| +static int SizeOfPartitionEntryTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptHeader* h2 = (GptHeader*)gpt->secondary_header;
|
| + int i;
|
|
|
| -/* Tests if SizeOfPartitionEntry is checked. SizeOfPartitionEntry must be
|
| - * between 128 and 512, and a multiple of 8. */
|
| -int SizeOfPartitionEntryTest() {
|
| - GptData *gpt;
|
| struct {
|
| uint32_t value_to_test;
|
| - int is_valid_value;
|
| + int expect_rv;
|
| } cases[] = {
|
| - {127, 0},
|
| - {128, 1},
|
| - {129, 0},
|
| - {130, 0},
|
| - {131, 0},
|
| - {132, 0},
|
| - {133, 0},
|
| - {134, 0},
|
| - {135, 0},
|
| - {136, 1},
|
| - {144, 1},
|
| - {160, 1},
|
| - {192, 1},
|
| + {127, 1},
|
| + {128, 0},
|
| + {129, 1},
|
| {256, 1},
|
| - {384, 1},
|
| - {504, 1},
|
| {512, 1},
|
| - {513, 0},
|
| - {520, 0},
|
| };
|
| - int i;
|
| - int test_mask;
|
| - GptHeader *headers[2];
|
| - uint32_t valid_headers;
|
| -
|
| - gpt = GetEmptyGptData();
|
| - headers[PRIMARY] = (GptHeader*)gpt->primary_header;
|
| - headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
|
|
|
| + /* Check size of entryes */
|
| for (i = 0; i < ARRAY_SIZE(cases); ++i) {
|
| - for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
|
| - BuildTestGptData(gpt);
|
| - if (test_mask & MASK_PRIMARY) {
|
| - headers[PRIMARY]->size_of_entry = cases[i].value_to_test;
|
| - headers[PRIMARY]->number_of_entries =
|
| - TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
|
| - }
|
| - if (test_mask & MASK_SECONDARY) {
|
| - headers[SECONDARY]->size_of_entry = cases[i].value_to_test;
|
| - headers[SECONDARY]->number_of_entries =
|
| - TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
|
| - }
|
| - valid_headers = CheckSizeOfPartitionEntry(gpt);
|
| - if (cases[i].is_valid_value)
|
| - EXPECT(MASK_BOTH == valid_headers);
|
| - else
|
| - EXPECT((MASK_BOTH ^ test_mask) == valid_headers);
|
| - }
|
| + BuildTestGptData(gpt);
|
| + h1->size_of_entry = cases[i].value_to_test;
|
| + h2->size_of_entry = cases[i].value_to_test;
|
| + h1->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
|
| + h2->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
|
| + RefreshCrc32(gpt);
|
| +
|
| + EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
|
| + EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
|
| }
|
| +
|
| return TEST_OK;
|
| }
|
|
|
| -/* Tests if NumberOfPartitionEntries is checes. NumberOfPartitionEntries must
|
| - * be between 32 and 512, and SizeOfPartitionEntry * NumberOfPartitionEntries
|
| - * must be 16384. */
|
| -int NumberOfPartitionEntriesTest() {
|
| - GptData *gpt;
|
| - struct {
|
| - uint32_t size_of_entry;
|
| - uint32_t number_of_entries;
|
| - int is_valid_value;
|
| - } cases[] = {
|
| - {111, 147, 0},
|
| - {111, 149, 0},
|
| - {128, 32, 0},
|
| - {128, 64, 0},
|
| - {128, 127, 0},
|
| - {128, 128, 1},
|
| - {128, 129, 0},
|
| - {128, 256, 0},
|
| - {256, 32, 0},
|
| - {256, 64, 1},
|
| - {256, 128, 0},
|
| - {256, 256, 0},
|
| - {512, 32, 1},
|
| - {512, 64, 0},
|
| - {512, 128, 0},
|
| - {512, 256, 0},
|
| - {1024, 128, 0},
|
| - };
|
| - int i;
|
| - int test_mask;
|
| - GptHeader *headers[2];
|
| - uint32_t valid_headers;
|
|
|
| - gpt = GetEmptyGptData();
|
| - headers[PRIMARY] = (GptHeader*)gpt->primary_header;
|
| - headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
|
| +/* Technically, any size which is 2^N where N > 6 should work, but our
|
| + * library only supports one size. */
|
| +static int NumberOfPartitionEntriesTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptHeader* h2 = (GptHeader*)gpt->secondary_header;
|
| +
|
| + BuildTestGptData(gpt);
|
| + h1->number_of_entries--;
|
| + h2->number_of_entries /= 2;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
|
|
| - for (i = 0; i < ARRAY_SIZE(cases); ++i) {
|
| - for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
|
| - BuildTestGptData(gpt);
|
| - if (test_mask & MASK_PRIMARY) {
|
| - headers[PRIMARY]->size_of_entry = cases[i].size_of_entry;
|
| - headers[PRIMARY]->number_of_entries = cases[i].number_of_entries;
|
| - }
|
| - if (test_mask & MASK_SECONDARY) {
|
| - headers[SECONDARY]->size_of_entry = cases[i].size_of_entry;
|
| - headers[SECONDARY]->number_of_entries = cases[i].number_of_entries;
|
| - }
|
| - valid_headers = CheckNumberOfEntries(gpt);
|
| - if (cases[i].is_valid_value)
|
| - EXPECT(MASK_BOTH == valid_headers);
|
| - else
|
| - EXPECT((MASK_BOTH ^ test_mask) == valid_headers);
|
| - }
|
| - }
|
| return TEST_OK;
|
| }
|
|
|
| -/* Tests if PartitionEntryLBA in primary/secondary headers is checked. */
|
| -int PartitionEntryLbaTest() {
|
| - GptData *gpt;
|
| - int test_mask;
|
| - GptHeader *headers[2];
|
| - uint32_t valid_headers;
|
|
|
| - gpt = GetEmptyGptData();
|
| - headers[PRIMARY] = (GptHeader*)gpt->primary_header;
|
| - headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
|
| +/* Tests if myLBA field is checked (1 for primary, last for secondary). */
|
| +static int MyLbaTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptHeader* h2 = (GptHeader*)gpt->secondary_header;
|
| +
|
| + /* myLBA depends on primary vs secondary flag */
|
| + BuildTestGptData(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 1, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 0, gpt->drive_sectors));
|
| +
|
| + BuildTestGptData(gpt);
|
| + h1->my_lba--;
|
| + h2->my_lba--;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
| +
|
| + BuildTestGptData(gpt);
|
| + h1->my_lba = 2;
|
| + h2->my_lba--;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
| +
|
| + BuildTestGptData(gpt);
|
| + h1->alternate_lba++;
|
| + h2->alternate_lba++;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
| +
|
| + BuildTestGptData(gpt);
|
| + h1->alternate_lba--;
|
| + h2->alternate_lba--;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
| +
|
| + BuildTestGptData(gpt);
|
| + h1->entries_lba++;
|
| + h2->entries_lba++;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
| +
|
| + BuildTestGptData(gpt);
|
| + h1->entries_lba--;
|
| + h2->entries_lba--;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
|
| + EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
|
|
|
| - for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
|
| - BuildTestGptData(gpt);
|
| - if (test_mask & MASK_PRIMARY)
|
| - headers[PRIMARY]->entries_lba = 0;
|
| - if (test_mask & MASK_SECONDARY)
|
| - headers[SECONDARY]->entries_lba = DEFAULT_DRIVE_SECTORS - 31 - 1;
|
| - valid_headers = CheckEntriesLba(gpt);
|
| - EXPECT((MASK_BOTH ^ test_mask) == valid_headers);
|
| - }
|
| return TEST_OK;
|
| }
|
|
|
| +
|
| /* Tests if FirstUsableLBA and LastUsableLBA are checked.
|
| * 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. */
|
| -int FirstUsableLbaAndLastUsableLbaTest() {
|
| - GptData *gpt;
|
| - GptHeader *primary_header, *secondary_header;
|
| - uint32_t valid_headers;
|
| +static int FirstUsableLbaAndLastUsableLbaTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptHeader* h2 = (GptHeader*)gpt->secondary_header;
|
| int i;
|
| +
|
| struct {
|
| uint64_t primary_entries_lba;
|
| uint64_t primary_first_usable_lba;
|
| @@ -543,197 +503,61 @@ int FirstUsableLbaAndLastUsableLbaTest() {
|
| uint64_t secondary_first_usable_lba;
|
| uint64_t secondary_last_usable_lba;
|
| uint64_t secondary_entries_lba;
|
| - int expected_masks;
|
| + int primary_rv;
|
| + int secondary_rv;
|
| } cases[] = {
|
| - {2, 34, 433, 34, 433, 434, MASK_BOTH},
|
| - {2, 34, 432, 34, 430, 434, MASK_BOTH},
|
| - {2, 33, 433, 33, 433, 434, MASK_NONE},
|
| - {3, 34, 433, 35, 433, 434, MASK_SECONDARY},
|
| - {3, 35, 433, 33, 433, 434, MASK_PRIMARY},
|
| - {2, 34, 434, 34, 433, 434, MASK_SECONDARY},
|
| - {2, 34, 433, 34, 434, 434, MASK_PRIMARY},
|
| - {2, 35, 433, 35, 433, 434, MASK_BOTH},
|
| - {2, 433, 433, 433, 433, 434, MASK_BOTH},
|
| - {2, 434, 433, 434, 434, 434, MASK_NONE},
|
| - {2, 433, 34, 34, 433, 434, MASK_SECONDARY},
|
| - {2, 34, 433, 433, 34, 434, MASK_PRIMARY},
|
| + {2, 34, 433, 34, 433, 434, 0, 0},
|
| + {2, 34, 432, 34, 430, 434, 0, 0},
|
| + {2, 33, 433, 33, 433, 434, 1, 1},
|
| + {2, 34, 434, 34, 433, 434, 1, 0},
|
| + {2, 34, 433, 34, 434, 434, 0, 1},
|
| + {2, 35, 433, 35, 433, 434, 0, 0},
|
| + {2, 433, 433, 433, 433, 434, 0, 0},
|
| + {2, 434, 433, 434, 434, 434, 1, 1},
|
| + {2, 433, 34, 34, 433, 434, 1, 0},
|
| + {2, 34, 433, 433, 34, 434, 0, 1},
|
| };
|
|
|
| - gpt = GetEmptyGptData();
|
| - primary_header = (GptHeader*)gpt->primary_header;
|
| - secondary_header = (GptHeader*)gpt->secondary_header;
|
| -
|
| for (i = 0; i < ARRAY_SIZE(cases); ++i) {
|
| BuildTestGptData(gpt);
|
| - primary_header->entries_lba = cases[i].primary_entries_lba;
|
| - primary_header->first_usable_lba = cases[i].primary_first_usable_lba;
|
| - primary_header->last_usable_lba = cases[i].primary_last_usable_lba;
|
| - secondary_header->entries_lba = cases[i].secondary_entries_lba;
|
| - secondary_header->first_usable_lba = cases[i].secondary_first_usable_lba;
|
| - secondary_header->last_usable_lba = cases[i].secondary_last_usable_lba;
|
| - valid_headers = CheckValidUsableLbas(gpt);
|
| - EXPECT(cases[i].expected_masks == valid_headers);
|
| + h1->entries_lba = cases[i].primary_entries_lba;
|
| + h1->first_usable_lba = cases[i].primary_first_usable_lba;
|
| + h1->last_usable_lba = cases[i].primary_last_usable_lba;
|
| + h2->entries_lba = cases[i].secondary_entries_lba;
|
| + h2->first_usable_lba = cases[i].secondary_first_usable_lba;
|
| + h2->last_usable_lba = cases[i].secondary_last_usable_lba;
|
| + RefreshCrc32(gpt);
|
| +
|
| + EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].primary_rv);
|
| + EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].secondary_rv);
|
| }
|
|
|
| return TEST_OK;
|
| }
|
|
|
| -/* Tests if header CRC in two copies are calculated. */
|
| -int HeaderCrcTest() {
|
| - GptData *gpt;
|
| - GptHeader *primary_header, *secondary_header;
|
| -
|
| - gpt = GetEmptyGptData();
|
| - primary_header = (GptHeader*)gpt->primary_header;
|
| - secondary_header = (GptHeader*)gpt->secondary_header;
|
| -
|
| - /* Modify the first byte of primary header, and expect the CRC is wrong. */
|
| - BuildTestGptData(gpt);
|
| - gpt->primary_header[0] ^= 0xa5; /* just XOR a non-zero value */
|
| - EXPECT(MASK_SECONDARY == CheckHeaderCrc(gpt));
|
| -
|
| - /* Modify the last byte of secondary header, and expect the CRC is wrong. */
|
| - BuildTestGptData(gpt);
|
| - gpt->secondary_header[secondary_header->size-1] ^= 0x5a;
|
| - EXPECT(MASK_PRIMARY == CheckHeaderCrc(gpt));
|
| -
|
| - /* Modify out of CRC range, expect CRC is still right. */
|
| - BuildTestGptData(gpt);
|
| - gpt->primary_header[primary_header->size] ^= 0x87;
|
| - EXPECT(MASK_BOTH == CheckHeaderCrc(gpt));
|
| -
|
| - /* Very long header (actually invalid header). Expect will be ignored. */
|
| - primary_header->size = 0x12345678;
|
| - secondary_header->size = 0x87654321;
|
| - gpt->valid_headers = MASK_NONE;
|
| - EXPECT(MASK_NONE == CheckHeaderCrc(gpt));
|
| -
|
| - return TEST_OK;
|
| -}
|
|
|
| /* Tests if PartitionEntryArrayCRC32 is checked.
|
| * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry *
|
| * NumberOfPartitionEntries bytes.
|
| */
|
| -int EntriesCrcTest() {
|
| - GptData *gpt;
|
| -
|
| - gpt = GetEmptyGptData();
|
| +static int EntriesCrcTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
|
| + GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
|
|
|
| /* Modify the first byte of primary entries, and expect the CRC is wrong. */
|
| BuildTestGptData(gpt);
|
| + EXPECT(0 == CheckEntries(e1, h1, gpt->drive_sectors));
|
| + EXPECT(0 == CheckEntries(e2, h1, gpt->drive_sectors));
|
| gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
|
| - EXPECT(MASK_SECONDARY == CheckEntriesCrc(gpt));
|
| -
|
| - /* Modify the last byte of secondary entries, and expect the CRC is wrong. */
|
| - BuildTestGptData(gpt);
|
| gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
|
| - EXPECT(MASK_PRIMARY == CheckEntriesCrc(gpt));
|
| -
|
| - return TEST_OK;
|
| -}
|
| -
|
| -/* Tests if GptInit() handles non-identical partition entries well.
|
| - * Two copies of partition table entries must be identical. If not, we trust the
|
| - * primary table entries, and mark secondary as modified. */
|
| -int IdenticalEntriesTest() {
|
| - GptData *gpt;
|
| -
|
| - gpt = GetEmptyGptData();
|
| -
|
| - /* Tests RepairEntries() first. */
|
| - BuildTestGptData(gpt);
|
| - EXPECT(0 == RepairEntries(gpt, MASK_BOTH));
|
| - gpt->secondary_entries[0] ^= 0xa5; /* XOR any number */
|
| - EXPECT(GPT_MODIFIED_ENTRIES2 == RepairEntries(gpt, MASK_BOTH));
|
| - EXPECT(GPT_MODIFIED_ENTRIES2 == RepairEntries(gpt, MASK_PRIMARY));
|
| - EXPECT(GPT_MODIFIED_ENTRIES1 == RepairEntries(gpt, MASK_SECONDARY));
|
| - EXPECT(0 == RepairEntries(gpt, MASK_NONE));
|
| -
|
| - /* The first byte is different. We expect secondary entries is marked as
|
| - * modified. */
|
| - BuildTestGptData(gpt);
|
| - gpt->primary_entries[0] ^= 0xff;
|
| - RefreshCrc32(gpt);
|
| - EXPECT(GPT_SUCCESS == GptInit(gpt));
|
| - EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
|
| - EXPECT(0 == Memcmp(gpt->primary_entries, gpt->secondary_entries,
|
| - TOTAL_ENTRIES_SIZE));
|
| -
|
| - /* The last byte is different, but the primary entries CRC is bad.
|
| - * We expect primary entries is marked as modified. */
|
| - BuildTestGptData(gpt);
|
| - gpt->primary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0xff;
|
| - EXPECT(GPT_SUCCESS == GptInit(gpt));
|
| - EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
|
| - EXPECT(0 == Memcmp(gpt->primary_entries, gpt->secondary_entries,
|
| - TOTAL_ENTRIES_SIZE));
|
| + EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
|
| + EXPECT(1 == CheckEntries(e2, h1, gpt->drive_sectors));
|
|
|
| return TEST_OK;
|
| }
|
|
|
| -/* Tests if GptInit() handles synonymous headers well.
|
| - * Note that two partition headers are NOT bit-swise identical.
|
| - * For exmaple, my_lba must be different (pointing to respective self).
|
| - * So in normal case, they are synonymous, not identical.
|
| - * If not synonymous, we trust the primary partition header, and
|
| - * overwrite secondary, then mark secondary as modified.*/
|
| -int SynonymousHeaderTest() {
|
| - GptData *gpt;
|
| - GptHeader *primary_header, *secondary_header;
|
| -
|
| - gpt = GetEmptyGptData();
|
| - primary_header = (GptHeader*)gpt->primary_header;
|
| - secondary_header = (GptHeader*)gpt->secondary_header;
|
| -
|
| - /* Tests RepairHeader() for synonymous cases first. */
|
| - BuildTestGptData(gpt);
|
| - EXPECT(0 == RepairHeader(gpt, MASK_BOTH));
|
| - EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_PRIMARY));
|
| - EXPECT(GPT_MODIFIED_HEADER1 == RepairHeader(gpt, MASK_SECONDARY));
|
| - EXPECT(0 == RepairHeader(gpt, MASK_NONE));
|
| - /* Then tests non-synonymous cases. */
|
| - BuildTestGptData(gpt);
|
| - ++secondary_header->first_usable_lba; /* chnage any bit */
|
| - EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH));
|
| - EXPECT(primary_header->first_usable_lba ==
|
| - secondary_header->first_usable_lba);
|
| - /* ---- */
|
| - BuildTestGptData(gpt);
|
| - --secondary_header->last_usable_lba;
|
| - EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH));
|
| - EXPECT(primary_header->last_usable_lba == secondary_header->last_usable_lba);
|
| - /* ---- */
|
| - BuildTestGptData(gpt);
|
| - ++secondary_header->number_of_entries;
|
| - EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH));
|
| - EXPECT(primary_header->number_of_entries ==
|
| - secondary_header->number_of_entries);
|
| - /* ---- */
|
| - BuildTestGptData(gpt);
|
| - --secondary_header->size_of_entry;
|
| - EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH));
|
| - EXPECT(primary_header->size_of_entry ==
|
| - secondary_header->size_of_entry);
|
| - /* ---- */
|
| - BuildTestGptData(gpt);
|
| - secondary_header->disk_uuid.u.raw[0] ^= 0x56;
|
| - EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH));
|
| - EXPECT(0 == Memcmp(&primary_header->disk_uuid,
|
| - &secondary_header->disk_uuid, sizeof(Guid)));
|
| -
|
| - /* Consider header repairing in GptInit(). */
|
| - BuildTestGptData(gpt);
|
| - ++secondary_header->first_usable_lba;
|
| - RefreshCrc32(gpt);
|
| - EXPECT(GPT_SUCCESS == GptInit(gpt));
|
| - EXPECT((gpt->modified & (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_HEADER2)) ==
|
| - GPT_MODIFIED_HEADER2);
|
| - EXPECT(primary_header->first_usable_lba ==
|
| - secondary_header->first_usable_lba);
|
| -
|
| - return TEST_OK;
|
| -}
|
|
|
| /* Tests if partition geometry is checked.
|
| * All active (non-zero PartitionTypeGUID) partition entries should have:
|
| @@ -741,53 +565,47 @@ int SynonymousHeaderTest() {
|
| * entry.EndingLBA <= header.LastUsableLBA
|
| * entry.StartingLBA <= entry.EndingLBA
|
| */
|
| -int ValidEntryTest() {
|
| - GptData *gpt;
|
| - GptHeader *primary_header, *secondary_header;
|
| - GptEntry *primary_entries, *secondary_entries;
|
| -
|
| - gpt = GetEmptyGptData();
|
| - primary_header = (GptHeader*)gpt->primary_header;
|
| - secondary_header = (GptHeader*)gpt->secondary_header;
|
| - primary_entries = (GptEntry*)gpt->primary_entries;
|
| - secondary_entries = (GptEntry*)gpt->secondary_entries;
|
| +static int ValidEntryTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
| + GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
|
|
|
| /* error case: entry.StartingLBA < header.FirstUsableLBA */
|
| BuildTestGptData(gpt);
|
| - primary_entries[0].starting_lba = primary_header->first_usable_lba - 1;
|
| - EXPECT(MASK_SECONDARY == CheckValidEntries(gpt));
|
| - secondary_entries[1].starting_lba = secondary_header->first_usable_lba - 1;
|
| - EXPECT(MASK_NONE == CheckValidEntries(gpt));
|
| + e1[0].starting_lba = h1->first_usable_lba - 1;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
|
|
|
| /* error case: entry.EndingLBA > header.LastUsableLBA */
|
| BuildTestGptData(gpt);
|
| - primary_entries[2].ending_lba = primary_header->last_usable_lba + 1;
|
| - EXPECT(MASK_SECONDARY == CheckValidEntries(gpt));
|
| - secondary_entries[3].ending_lba = secondary_header->last_usable_lba + 1;
|
| - EXPECT(MASK_NONE == CheckValidEntries(gpt));
|
| + e1[2].ending_lba = h1->last_usable_lba + 1;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
|
|
|
| /* error case: entry.StartingLBA > entry.EndingLBA */
|
| BuildTestGptData(gpt);
|
| - primary_entries[3].starting_lba = primary_entries[3].ending_lba + 1;
|
| - EXPECT(MASK_SECONDARY == CheckValidEntries(gpt));
|
| - secondary_entries[1].starting_lba = secondary_entries[1].ending_lba + 1;
|
| - EXPECT(MASK_NONE == CheckValidEntries(gpt));
|
| + e1[3].starting_lba = e1[3].ending_lba + 1;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
|
|
|
| /* case: non active entry should be ignored. */
|
| BuildTestGptData(gpt);
|
| - Memset(&primary_entries[1].type, 0, sizeof(primary_entries[1].type));
|
| - primary_entries[1].starting_lba = primary_entries[1].ending_lba + 1;
|
| - EXPECT(MASK_BOTH == CheckValidEntries(gpt));
|
| - Memset(&secondary_entries[2].type, 0, sizeof(secondary_entries[2].type));
|
| - secondary_entries[2].starting_lba = secondary_entries[2].ending_lba + 1;
|
| - EXPECT(MASK_BOTH == CheckValidEntries(gpt));
|
| + Memset(&e1[1].type, 0, sizeof(e1[1].type));
|
| + e1[1].starting_lba = e1[1].ending_lba + 1;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(0 == CheckEntries(e1, h1, gpt->drive_sectors));
|
|
|
| return TEST_OK;
|
| }
|
|
|
| +
|
| /* Tests if overlapped partition tables can be detected. */
|
| -int OverlappedPartitionTest() {
|
| - GptData *gpt;
|
| +static int OverlappedPartitionTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h = (GptHeader*)gpt->primary_header;
|
| + GptEntry* e = (GptEntry*)gpt->primary_entries;
|
| + int i, j;
|
| +
|
| struct {
|
| int overlapped;
|
| struct {
|
| @@ -796,337 +614,472 @@ int OverlappedPartitionTest() {
|
| uint64_t ending_lba;
|
| } entries[16]; /* enough for testing. */
|
| } cases[] = {
|
| - {0, {{0, 100, 199}, {0, 0, 0}}},
|
| - {0, {{1, 100, 199}, {0, 0, 0}}},
|
| - {0, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}, {0, 0, 0}}},
|
| - {1, {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}, {0, 0, 0}}},
|
| - {1, {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}, {0, 0, 0}}},
|
| - {0, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}, {0, 0, 0}}},
|
| - {1, {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}, {0, 0, 0}}},
|
| - {1, {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}, {0, 0, 0}}},
|
| - {1, {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}, {0, 0, 0}}},
|
| - {1, {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}, {0, 0, 0}}},
|
| - {1, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399},
|
| - {0, 0, 0}}},
|
| - {0, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399},
|
| - {0, 0, 0}}},
|
| - {1, {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400},
|
| - {0, 0, 0}}},
|
| - {1, {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400},
|
| - {0, 0, 0}}},
|
| - {0, {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400},
|
| - {0, 0, 0}}},
|
| - {1, {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}, {0, 0, 0}}},
|
| - {0, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}, {0, 0, 0}}},
|
| - {0, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}, {0, 0, 0}}},
|
| + {0, {{0, 100, 199}}},
|
| + {0, {{1, 100, 199}}},
|
| + {0, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
|
| + {1, {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
|
| + {1, {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
|
| + {0, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
|
| + {1, {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
|
| + {1, {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
|
| + {1, {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
|
| + {1, {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
|
| + {1, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
|
| + {0, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
|
| + {1, {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
|
| + {1, {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
|
| + {0, {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
|
| + {1, {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
|
| + {0, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
|
| + {0, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
|
| {1, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
|
| {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
|
| - {1, 207, 207}, {1, 208, 208}, {1, 199, 199}, {0, 0, 0}}},
|
| + {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
|
| {0, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
|
| {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
|
| - {1, 207, 207}, {1, 208, 208}, {0, 199, 199}, {0, 0, 0}}},
|
| + {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
|
| };
|
| - Guid any_type = GPT_ENT_TYPE_CHROMEOS_KERNEL;
|
| - int i, j;
|
| - int test_mask;
|
| - GptEntry *entries[2];
|
|
|
| - gpt = GetEmptyGptData();
|
| - entries[PRIMARY] = (GptEntry*)gpt->primary_entries;
|
| - entries[SECONDARY] = (GptEntry*)gpt->secondary_entries;
|
|
|
| for (i = 0; i < ARRAY_SIZE(cases); ++i) {
|
| - for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
|
| - BuildTestGptData(gpt);
|
| - ZeroEntries(gpt);
|
| - for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
|
| - if (!cases[i].entries[j].starting_lba) break;
|
| - if (test_mask & MASK_PRIMARY) {
|
| - if (cases[i].entries[j].active)
|
| - Memcpy(&entries[PRIMARY][j].type, &any_type, sizeof(any_type));
|
| - entries[PRIMARY][j].starting_lba = cases[i].entries[j].starting_lba;
|
| - entries[PRIMARY][j].ending_lba = cases[i].entries[j].ending_lba;
|
| - }
|
| - if (test_mask & MASK_SECONDARY) {
|
| - if (cases[i].entries[j].active)
|
| - Memcpy(&entries[SECONDARY][j].type, &any_type, sizeof(any_type));
|
| - entries[SECONDARY][j].starting_lba = cases[i].entries[j].starting_lba;
|
| - entries[SECONDARY][j].ending_lba = cases[i].entries[j].ending_lba;
|
| - }
|
| - }
|
| - EXPECT((cases[i].overlapped * test_mask) ==
|
| - (OverlappedEntries(entries[PRIMARY], j) |
|
| - (OverlappedEntries(entries[SECONDARY], j) << SECONDARY))
|
| - );
|
| -
|
| - EXPECT((MASK_BOTH ^ (cases[i].overlapped * test_mask)) ==
|
| - CheckOverlappedPartition(gpt));
|
| + BuildTestGptData(gpt);
|
| + ZeroEntries(gpt);
|
| + for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
|
| + if (!cases[i].entries[j].starting_lba)
|
| + break;
|
| +
|
| + if (cases[i].entries[j].active)
|
| + Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
|
| + e[j].starting_lba = cases[i].entries[j].starting_lba;
|
| + e[j].ending_lba = cases[i].entries[j].ending_lba;
|
| }
|
| + RefreshCrc32(gpt);
|
| +
|
| + EXPECT(cases[i].overlapped == CheckEntries(e, h, gpt->drive_sectors));
|
| }
|
| return TEST_OK;
|
| }
|
|
|
| -/* Tests if GptInit() can survive in different corrupt header/entries
|
| - * combinations, like:
|
| - * primary GPT header - valid
|
| - * primary partition table - invalid
|
| - * secondary GPT header - invalid
|
| - * secondary partition table - valid
|
| - */
|
| -int CorruptCombinationTest() {
|
| - GptData *gpt;
|
| - GptHeader *primary_header, *secondary_header;
|
| - GptEntry *primary_entries, *secondary_entries;
|
|
|
| - gpt = GetEmptyGptData();
|
| - primary_header = (GptHeader*)gpt->primary_header;
|
| - secondary_header = (GptHeader*)gpt->secondary_header;
|
| - primary_entries = (GptEntry*)gpt->primary_entries;
|
| - secondary_entries = (GptEntry*)gpt->secondary_entries;
|
| +/* Test both sanity checking and repair. */
|
| +static int SanityCheckTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptHeader* h1 = (GptHeader*)gpt->primary_header;
|
|
|
| - /* Make primary entries and secondary header invalid, we expect GptInit()
|
| - * can recover them (returns GPT_SUCCESS and MODIFIED flasgs). */
|
| + /* Unmodified test data is completely sane */
|
| BuildTestGptData(gpt);
|
| - primary_entries[0].type.u.raw[0] ^= 0x33;
|
| - secondary_header->header_crc32 ^= 0x55;
|
| - EXPECT(GPT_SUCCESS == GptInit(gpt));
|
| - EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
|
| - EXPECT(0 == Memcmp(primary_entries, secondary_entries, TOTAL_ENTRIES_SIZE));
|
| - /* We expect the modified header/entries can pass GptInit(). */
|
| - EXPECT(GPT_SUCCESS == GptInit(gpt));
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + /* 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->modified);
|
|
|
| - /* Make primary header invalid (the entries is not damaged actually). */
|
| + /* Modify headers */
|
| BuildTestGptData(gpt);
|
| - primary_header->entries_crc32 ^= 0x73;
|
| - EXPECT(GPT_SUCCESS == GptInit(gpt));
|
| - /* After header is repaired, the entries are valid actually. */
|
| - EXPECT((gpt->modified & (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_HEADER2)) ==
|
| - GPT_MODIFIED_HEADER1);
|
| - /* We expect the modified header/entries can pass GptInit(). */
|
| - EXPECT(GPT_SUCCESS == GptInit(gpt));
|
| + gpt->primary_header[0]++;
|
| + gpt->secondary_header[0]++;
|
| + EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
|
| + EXPECT(0 == gpt->valid_headers);
|
| + EXPECT(0 == gpt->valid_entries);
|
| + /* 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->modified);
|
|
|
| - return TEST_OK;
|
| -}
|
| + BuildTestGptData(gpt);
|
| + gpt->primary_header[0]++;
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_SECONDARY == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + GptRepair(gpt);
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
|
|
|
| -/* Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
|
| - * any usable kernel entry.
|
| - */
|
| -int NoValidKernelEntryTest() {
|
| - GptData *gpt;
|
| - GptEntry *entries, *entries2;
|
| + BuildTestGptData(gpt);
|
| + gpt->secondary_header[0]++;
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_PRIMARY == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + GptRepair(gpt);
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
|
| +
|
| + /* Modify header1 and update its CRC. Since header2 is now different than
|
| + * header1, it'll be the one considered invalid. */
|
| + BuildTestGptData(gpt);
|
| + h1->size++;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_PRIMARY == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + GptRepair(gpt);
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
|
| +
|
| + /* Modify entries */
|
| + BuildTestGptData(gpt);
|
| + gpt->primary_entries[0]++;
|
| + gpt->secondary_entries[0]++;
|
| + EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_NONE == gpt->valid_entries);
|
| + /* 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->modified);
|
|
|
| - gpt = GetEmptyGptData();
|
| - entries = (GptEntry*)gpt->primary_entries;
|
| - entries2 = (GptEntry*)gpt->secondary_entries;
|
| + BuildTestGptData(gpt);
|
| + gpt->primary_entries[0]++;
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_SECONDARY == gpt->valid_entries);
|
| + GptRepair(gpt);
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
|
|
|
| BuildTestGptData(gpt);
|
| - entries[KERNEL_A].attributes |= CGPT_ATTRIBUTE_BAD_MASK;
|
| - Memset(&entries[KERNEL_B].type, 0, sizeof(Guid));
|
| - RefreshCrc32(gpt);
|
| + gpt->secondary_entries[0]++;
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_PRIMARY == gpt->valid_entries);
|
| + GptRepair(gpt);
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
|
|
|
| - EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, NULL, NULL));
|
| + /* 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);
|
| + GptRepair(gpt);
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + 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);
|
| + GptRepair(gpt);
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + 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. */
|
| + BuildTestGptData(gpt);
|
| + gpt->secondary_entries[0]++;
|
| + RefreshCrc32(gpt);
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_PRIMARY == gpt->valid_headers);
|
| + EXPECT(MASK_PRIMARY == gpt->valid_entries);
|
| + GptRepair(gpt);
|
| + EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
|
| + EXPECT(MASK_BOTH == gpt->valid_headers);
|
| + EXPECT(MASK_BOTH == gpt->valid_entries);
|
| + EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
|
|
|
| return TEST_OK;
|
| }
|
|
|
| -/* This is the combination test. Both kernel A and B could be either inactive
|
| - * or invalid. We expect GptNextKetnelEntry() returns good kernel or
|
| - * GPT_ERROR_NO_VALID_KERNEL if no kernel is available. */
|
| -enum FAILURE_MASK {
|
| - MASK_INACTIVE = 1,
|
| - MASK_BAD_ENTRY = 2,
|
| - MASK_FAILURE_BOTH = 3,
|
| -};
|
| -void BreakAnEntry(GptEntry *entry, enum FAILURE_MASK failure) {
|
| - if (failure & MASK_INACTIVE)
|
| - Memset(&entry->type, 0, sizeof(Guid));
|
| - if (failure & MASK_BAD_ENTRY)
|
| - entry->attributes |= CGPT_ATTRIBUTE_BAD_MASK;
|
| +
|
| +static int EntryAttributeGetSetTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptEntry* e = (GptEntry*)(gpt->primary_entries);
|
| +
|
| + e->attributes = 0x0000000000000000;
|
| + SetEntrySuccessful(e, 1);
|
| + EXPECT(0x0100000000000000 == e->attributes);
|
| + EXPECT(1 == GetEntrySuccessful(e));
|
| + e->attributes = 0xFFFFFFFFFFFFFFFF;
|
| + SetEntrySuccessful(e, 0);
|
| + EXPECT(0xFEFFFFFFFFFFFFFF == e->attributes);
|
| + EXPECT(0 == GetEntrySuccessful(e));
|
| +
|
| + e->attributes = 0x0000000000000000;
|
| + SetEntryTries(e, 15);
|
| + EXPECT(15 == GetEntryTries(e));
|
| + EXPECT(0x00F0000000000000 == e->attributes);
|
| + e->attributes = 0xFFFFFFFFFFFFFFFF;
|
| + SetEntryTries(e, 0);
|
| + EXPECT(0xFF0FFFFFFFFFFFFF == e->attributes);
|
| + EXPECT(0 == GetEntryTries(e));
|
| +
|
| + e->attributes = 0x0000000000000000;
|
| + SetEntryPriority(e, 15);
|
| + EXPECT(0x000F000000000000 == e->attributes);
|
| + EXPECT(15 == GetEntryPriority(e));
|
| + e->attributes = 0xFFFFFFFFFFFFFFFF;
|
| + SetEntryPriority(e, 0);
|
| + EXPECT(0xFFF0FFFFFFFFFFFF == e->attributes);
|
| + EXPECT(0 == GetEntryPriority(e));
|
| +
|
| + e->attributes = 0xFFFFFFFFFFFFFFFF;
|
| + EXPECT(1 == GetEntrySuccessful(e));
|
| + EXPECT(15 == GetEntryPriority(e));
|
| + EXPECT(15 == GetEntryTries(e));
|
| +
|
| + e->attributes = 0x0123000000000000;
|
| + EXPECT(1 == GetEntrySuccessful(e));
|
| + EXPECT(2 == GetEntryTries(e));
|
| + EXPECT(3 == GetEntryPriority(e));
|
| +
|
| + return TEST_OK;
|
| }
|
|
|
| -int CombinationalNextKernelEntryTest() {
|
| - GptData *gpt;
|
| - enum {
|
| - MASK_KERNEL_A = 1,
|
| - MASK_KERNEL_B = 2,
|
| - MASK_KERNEL_BOTH = 3,
|
| - } kernel;
|
| - enum FAILURE_MASK failure;
|
| - uint64_t start_sector, size;
|
| - int retval;
|
| -
|
| - for (kernel = MASK_KERNEL_A; kernel <= MASK_KERNEL_BOTH; ++kernel) {
|
| - for (failure = MASK_INACTIVE; failure < MASK_FAILURE_BOTH; ++failure) {
|
| - gpt = GetEmptyGptData();
|
| - BuildTestGptData(gpt);
|
| -
|
| - if (kernel & MASK_KERNEL_A)
|
| - BreakAnEntry(GetEntry(gpt, PRIMARY, KERNEL_A), failure);
|
| - if (kernel & MASK_KERNEL_B)
|
| - BreakAnEntry(GetEntry(gpt, PRIMARY, KERNEL_B), failure);
|
| -
|
| - retval = GptNextKernelEntry(gpt, &start_sector, &size);
|
| -
|
| - if (kernel == MASK_KERNEL_A) {
|
| - EXPECT(retval == GPT_SUCCESS);
|
| - EXPECT(start_sector == 334);
|
| - } else if (kernel == MASK_KERNEL_B) {
|
| - EXPECT(retval == GPT_SUCCESS);
|
| - EXPECT(start_sector == 34);
|
| - } else { /* MASK_KERNEL_BOTH */
|
| - EXPECT(retval == GPT_ERROR_NO_VALID_KERNEL);
|
| - }
|
| - }
|
| - }
|
| +
|
| +static int EntryTypeTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptEntry* e = (GptEntry*)(gpt->primary_entries);
|
| +
|
| + Memcpy(&e->type, &guid_zero, sizeof(Guid));
|
| + EXPECT(1 == IsUnusedEntry(e));
|
| + EXPECT(0 == IsKernelEntry(e));
|
| +
|
| + Memcpy(&e->type, &guid_kernel, sizeof(Guid));
|
| + EXPECT(0 == IsUnusedEntry(e));
|
| + EXPECT(1 == IsKernelEntry(e));
|
| +
|
| + Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
|
| + EXPECT(0 == IsUnusedEntry(e));
|
| + EXPECT(0 == IsKernelEntry(e));
|
| +
|
| return TEST_OK;
|
| }
|
|
|
| -/* Increase tries value from zero, expect it won't explode/overflow after
|
| - * CGPT_ATTRIBUTE_TRIES_MASK.
|
| +
|
| +/* Make an entry unused by clearing its type. */
|
| +static void FreeEntry(GptEntry* e) {
|
| + Memset(&e->type, 0, sizeof(Guid));
|
| +}
|
| +
|
| +
|
| +/* Set up an entry. */
|
| +static void FillEntry(GptEntry* e, int is_kernel,
|
| + int priority, int successful, int tries) {
|
| + Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
|
| + SetEntryPriority(e, priority);
|
| + SetEntrySuccessful(e, successful);
|
| + SetEntryTries(e, tries);
|
| +}
|
| +
|
| +
|
| +/* Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
|
| + * any usable kernel entry.
|
| */
|
| -/* Tries would not count up after CGPT_ATTRIBUTE_MAX_TRIES. */
|
| -#define EXPECTED_TRIES(tries) \
|
| - ((tries >= CGPT_ATTRIBUTE_MAX_TRIES) ? CGPT_ATTRIBUTE_MAX_TRIES \
|
| - : tries)
|
| -int IncreaseTriesTest() {
|
| - GptData *gpt;
|
| - int kernel_index[] = {
|
| - KERNEL_B,
|
| - KERNEL_A,
|
| - };
|
| - int i, tries, j;
|
| +static int NoValidKernelEntryTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
|
|
|
| - gpt = GetEmptyGptData();
|
| - for (i = 0; i < ARRAY_SIZE(kernel_index); ++i) {
|
| - GptEntry *entries[2] = {
|
| - (GptEntry*)gpt->primary_entries,
|
| - (GptEntry*)gpt->secondary_entries,
|
| - };
|
| - int current;
|
| + BuildTestGptData(gpt);
|
| + SetEntryPriority(e1 + KERNEL_A, 0);
|
| + FreeEntry(e1 + KERNEL_B);
|
| + RefreshCrc32(gpt);
|
| + EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, NULL, NULL));
|
|
|
| - BuildTestGptData(gpt);
|
| - current = gpt->current_kernel = kernel_index[i];
|
| -
|
| - for (tries = 0; tries < 2 * CGPT_ATTRIBUTE_MAX_TRIES; ++tries) {
|
| - for (j = 0; j < ARRAY_SIZE(entries); ++j) {
|
| - EXPECT(EXPECTED_TRIES(tries) ==
|
| - ((entries[j][current].attributes & CGPT_ATTRIBUTE_TRIES_MASK) >>
|
| - CGPT_ATTRIBUTE_TRIES_OFFSET));
|
| - }
|
| -
|
| - EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
|
| - /* The expected tries value will be checked in next iteration. */
|
| -
|
| - if (tries < CGPT_ATTRIBUTE_MAX_TRIES)
|
| - EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
|
| - GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
|
| - gpt->modified = 0; /* reset before next test */
|
| - EXPECT(0 ==
|
| - Memcmp(entries[PRIMARY], entries[SECONDARY], TOTAL_ENTRIES_SIZE));
|
| - }
|
| - }
|
| return TEST_OK;
|
| }
|
|
|
| -/* Mark a kernel as bad. Expect:
|
| - * 1. the both bad bits of kernel A in primary and secondary entries are set.
|
| - * 2. headers and entries are marked as modified.
|
| - * 3. primary and secondary entries are identical.
|
| - */
|
| -int MarkBadKernelEntryTest() {
|
| - GptData *gpt;
|
| - GptEntry *entries, *entries2;
|
|
|
| - gpt = GetEmptyGptData();
|
| - entries = (GptEntry*)gpt->primary_entries;
|
| - entries2 = (GptEntry*)gpt->secondary_entries;
|
| +static int GetNextNormalTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
|
| + uint64_t start, size;
|
|
|
| + /* Normal case - both kernels successful */
|
| BuildTestGptData(gpt);
|
| - gpt->current_kernel = KERNEL_A;
|
| - EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
|
| - EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
|
| - GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
|
| - EXPECT(entries[KERNEL_A].attributes & CGPT_ATTRIBUTE_BAD_MASK);
|
| - EXPECT(entries2[KERNEL_A].attributes & CGPT_ATTRIBUTE_BAD_MASK);
|
| - EXPECT(0 == Memcmp(entries, entries2, TOTAL_ENTRIES_SIZE));
|
| + FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
|
| + FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
|
| + RefreshCrc32(gpt);
|
| + GptInit(gpt);
|
| +
|
| + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(KERNEL_A == gpt->current_kernel);
|
| + EXPECT(34 == start);
|
| + EXPECT(100 == size);
|
| +
|
| + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(KERNEL_B == gpt->current_kernel);
|
| + EXPECT(134 == start);
|
| + EXPECT(99 == size);
|
| +
|
| + EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(-1 == gpt->current_kernel);
|
| +
|
| + /* Call as many times as you want; you won't get another kernel... */
|
| + EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(-1 == gpt->current_kernel);
|
|
|
| return TEST_OK;
|
| }
|
|
|
| -/* Given an invalid kernel type, and expect GptUpdateKernelEntry() returns
|
| - * GPT_ERROR_INVALID_UPDATE_TYPE. */
|
| -int UpdateInvalidKernelTypeTest() {
|
| - GptData *gpt;
|
|
|
| - gpt = GetEmptyGptData();
|
| +static int GetNextPrioTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
|
| + uint64_t start, size;
|
| +
|
| + /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
|
| BuildTestGptData(gpt);
|
| - gpt->current_kernel = 0; /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
|
| - EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
|
| - GptUpdateKernelEntry(gpt, 99)); /* any invalid update_type value */
|
| + FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
|
| + FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
|
| + FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
|
| + FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
|
| + RefreshCrc32(gpt);
|
| + GptInit(gpt);
|
| +
|
| + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(KERNEL_B == gpt->current_kernel);
|
| + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(KERNEL_Y == gpt->current_kernel);
|
| + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(KERNEL_A == gpt->current_kernel);
|
| + EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
|
|
|
| return TEST_OK;
|
| }
|
|
|
| -/* A normal boot case:
|
| - * GptInit()
|
| - * GptNextKernelEntry()
|
| - * GptUpdateKernelEntry()
|
| - */
|
| -int NormalBootCase() {
|
| - GptData *gpt;
|
| - GptEntry *entries;
|
| - uint64_t start_sector, size;
|
|
|
| - gpt = GetEmptyGptData();
|
| - entries = (GptEntry*)gpt->primary_entries;
|
| - BuildTestGptData(gpt);
|
| +static int GetNextTriesTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
|
| + uint64_t start, size;
|
|
|
| - EXPECT(GPT_SUCCESS == GptInit(gpt));
|
| - EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start_sector, &size));
|
| - EXPECT(start_sector == 34); /* Kernel A, see top of this file. */
|
| - EXPECT(size == 100);
|
| + /* Tries=nonzero is attempted just like success, but tries=0 isn't */
|
| + BuildTestGptData(gpt);
|
| + FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
|
| + FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
|
| + FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
|
| + FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
|
| + RefreshCrc32(gpt);
|
| + GptInit(gpt);
|
|
|
| - EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
|
| - EXPECT(((entries[KERNEL_A].attributes & CGPT_ATTRIBUTE_TRIES_MASK) >>
|
| - CGPT_ATTRIBUTE_TRIES_OFFSET) == 1);
|
| + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(KERNEL_X == gpt->current_kernel);
|
| + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(KERNEL_A == gpt->current_kernel);
|
| + EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
|
|
|
| return TEST_OK;
|
| }
|
|
|
| -/* Higher priority kernel should boot first.
|
| - * KERNEL_A is low priority
|
| - * KERNEL_B is high priority.
|
| - * We expect KERNEL_B is selected in first run, and then KERNEL_A.
|
| - * We also expect the GptNextKernelEntry() wraps back to KERNEL_B if it's called
|
| - * after twice.
|
| - */
|
| -int HigherPriorityTest() {
|
| - GptData *gpt;
|
| - GptEntry *entries;
|
|
|
| - gpt = GetEmptyGptData();
|
| - entries = (GptEntry*)gpt->primary_entries;
|
| - BuildTestGptData(gpt);
|
| +static int GptUpdateTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| + GptEntry* e = (GptEntry*)(gpt->primary_entries);
|
| + GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
|
| + uint64_t start, size;
|
|
|
| - SetPriority(gpt, PRIMARY, KERNEL_A, 0);
|
| - SetPriority(gpt, PRIMARY, KERNEL_B, 1);
|
| + /* Tries=nonzero is attempted just like success, but tries=0 isn't */
|
| + BuildTestGptData(gpt);
|
| + FillEntry(e + KERNEL_A, 1, 4, 1, 0);
|
| + FillEntry(e + KERNEL_B, 1, 3, 0, 2);
|
| + FillEntry(e + KERNEL_X, 1, 2, 0, 2);
|
| RefreshCrc32(gpt);
|
| + GptInit(gpt);
|
| + gpt->modified = 0; /* Nothing modified yet */
|
|
|
| - EXPECT(GPT_SUCCESS == GptInit(gpt));
|
| - EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, NULL, NULL));
|
| + /* Successful kernel */
|
| + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(KERNEL_A == gpt->current_kernel);
|
| + EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
|
| + EXPECT(4 == GetEntryPriority(e + KERNEL_A));
|
| + EXPECT(0 == GetEntryTries(e + KERNEL_A));
|
| + EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
|
| + EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
|
| + EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
|
| + /* Trying successful kernel changes nothing */
|
| + EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
|
| + EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
|
| + EXPECT(4 == GetEntryPriority(e + KERNEL_A));
|
| + EXPECT(0 == GetEntryTries(e + KERNEL_A));
|
| + EXPECT(0 == gpt->modified);
|
| + /* Marking it bad does, though */
|
| + EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
|
| + EXPECT(0 == GetEntrySuccessful(e + KERNEL_A));
|
| + EXPECT(0 == GetEntryPriority(e + KERNEL_A));
|
| + EXPECT(0 == GetEntryTries(e + KERNEL_A));
|
| + /* Which affects both copies of the partition entries */
|
| + EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_A));
|
| + EXPECT(0 == GetEntryPriority(e2 + KERNEL_A));
|
| + EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
|
| + /* And that's caused the GPT to need updating */
|
| + EXPECT(0x0F == gpt->modified);
|
| +
|
| + /* Kernel with tries */
|
| + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
|
| EXPECT(KERNEL_B == gpt->current_kernel);
|
| + EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
|
| + EXPECT(3 == GetEntryPriority(e + KERNEL_B));
|
| + EXPECT(2 == GetEntryTries(e + KERNEL_B));
|
| + /* Marking it bad clears it */
|
| + EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
|
| + EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
|
| + EXPECT(0 == GetEntryPriority(e + KERNEL_B));
|
| + EXPECT(0 == GetEntryTries(e + KERNEL_B));
|
| +
|
| + /* Another kernel with tries */
|
| + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
|
| + EXPECT(KERNEL_X == gpt->current_kernel);
|
| + EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
|
| + EXPECT(2 == GetEntryPriority(e + KERNEL_X));
|
| + EXPECT(2 == GetEntryTries(e + KERNEL_X));
|
| + /* Trying it uses up a try */
|
| + EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
|
| + EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
|
| + EXPECT(2 == GetEntryPriority(e + KERNEL_X));
|
| + EXPECT(1 == GetEntryTries(e + KERNEL_X));
|
| + EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
|
| + EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
|
| + EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
|
| + /* Trying it again marks it inactive */
|
| + EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
|
| + EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
|
| + EXPECT(0 == GetEntryPriority(e + KERNEL_X));
|
| + EXPECT(0 == GetEntryTries(e + KERNEL_X));
|
|
|
| - EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, NULL, NULL));
|
| - EXPECT(KERNEL_A == gpt->current_kernel);
|
| + return TEST_OK;
|
| +}
|
|
|
| - EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, NULL, NULL));
|
| - EXPECT(KERNEL_B == gpt->current_kernel);
|
| +
|
| +/* Given an invalid kernel type, and expect GptUpdateKernelEntry() returns
|
| + * GPT_ERROR_INVALID_UPDATE_TYPE. */
|
| +static int UpdateInvalidKernelTypeTest() {
|
| + GptData* gpt = GetEmptyGptData();
|
| +
|
| + BuildTestGptData(gpt);
|
| + gpt->current_kernel = 0; /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
|
| + EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
|
| + GptUpdateKernelEntry(gpt, 99)); /* any invalid update_type value */
|
|
|
| return TEST_OK;
|
| }
|
|
|
| +
|
| int main(int argc, char *argv[]) {
|
| int i;
|
| int error_count = 0;
|
| @@ -1137,31 +1090,28 @@ int main(int argc, char *argv[]) {
|
| } test_cases[] = {
|
| { TEST_CASE(TestBuildTestGptData), },
|
| { TEST_CASE(ParameterTests), },
|
| + { TEST_CASE(HeaderCrcTest), },
|
| { TEST_CASE(SignatureTest), },
|
| { TEST_CASE(RevisionTest), },
|
| { TEST_CASE(SizeTest), },
|
| + { TEST_CASE(CrcFieldTest), },
|
| { TEST_CASE(ReservedFieldsTest), },
|
| - { TEST_CASE(MyLbaTest), },
|
| { TEST_CASE(SizeOfPartitionEntryTest), },
|
| { TEST_CASE(NumberOfPartitionEntriesTest), },
|
| - { TEST_CASE(PartitionEntryLbaTest), },
|
| + { TEST_CASE(MyLbaTest), },
|
| { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
|
| - { TEST_CASE(HeaderCrcTest), },
|
| { TEST_CASE(EntriesCrcTest), },
|
| - { TEST_CASE(IdenticalEntriesTest), },
|
| - { TEST_CASE(SynonymousHeaderTest), },
|
| { TEST_CASE(ValidEntryTest), },
|
| { TEST_CASE(OverlappedPartitionTest), },
|
| - { TEST_CASE(CorruptCombinationTest), },
|
| - { TEST_CASE(TestQuickSortFixed), },
|
| - { TEST_CASE(TestQuickSortRandom), },
|
| + { TEST_CASE(SanityCheckTest), },
|
| { TEST_CASE(NoValidKernelEntryTest), },
|
| - { TEST_CASE(CombinationalNextKernelEntryTest), },
|
| - { TEST_CASE(IncreaseTriesTest), },
|
| - { TEST_CASE(MarkBadKernelEntryTest), },
|
| + { TEST_CASE(EntryAttributeGetSetTest), },
|
| + { TEST_CASE(EntryTypeTest), },
|
| + { TEST_CASE(GetNextNormalTest), },
|
| + { TEST_CASE(GetNextPrioTest), },
|
| + { TEST_CASE(GetNextTriesTest), },
|
| + { TEST_CASE(GptUpdateTest), },
|
| { TEST_CASE(UpdateInvalidKernelTypeTest), },
|
| - { TEST_CASE(NormalBootCase), },
|
| - { TEST_CASE(HigherPriorityTest), },
|
| { TEST_CASE(TestCrc32TestVectors), },
|
| };
|
|
|
|
|