Home | History | Annotate | Download | only in tests
      1 /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  */
      5 
      6 #include <errno.h>
      7 #include <string.h>
      8 
      9 #include "../cgpt/cgpt.h"
     10 #include "cgptlib_internal.h"
     11 #include "cgptlib_test.h"
     12 #include "crc32.h"
     13 #include "crc32_test.h"
     14 #include "gpt.h"
     15 #include "test_common.h"
     16 #define _STUB_IMPLEMENTATION_
     17 #include "utility.h"
     18 
     19 /*
     20  * Testing partition layout (sector_bytes=512)
     21  *
     22  *     LBA   Size  Usage
     23  * ---------------------------------------------------------
     24  *       0      1  PMBR
     25  *       1      1  primary partition header
     26  *       2     32  primary partition entries (128B * 128)
     27  *      34    100  kernel A (index: 0)
     28  *     134    100  root A (index: 1)
     29  *     234    100  root B (index: 2)
     30  *     334    100  kernel B (index: 3)
     31  *     434     32  secondary partition entries
     32  *     466      1  secondary partition header
     33  *     467
     34  */
     35 #define KERNEL_A 0
     36 #define KERNEL_B 1
     37 #define ROOTFS_A 2
     38 #define ROOTFS_B 3
     39 #define KERNEL_X 2 /* Overload ROOTFS_A, for some GetNext tests */
     40 #define KERNEL_Y 3 /* Overload ROOTFS_B, for some GetNext tests */
     41 
     42 #define DEFAULT_SECTOR_SIZE 512
     43 #define MAX_SECTOR_SIZE 4096
     44 #define DEFAULT_DRIVE_SECTORS 467
     45 #define TOTAL_ENTRIES_SIZE (MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry)) /* 16384 */
     46 #define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
     47 
     48 static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
     49 static const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
     50 static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
     51 
     52 // cgpt_common.c requires these be defined if linked in.
     53 const char *progname = "CGPT-TEST";
     54 const char *command = "TEST";
     55 
     56 /*
     57  * Copy a random-for-this-program-only Guid into the dest. The num parameter
     58  * completely determines the Guid.
     59  */
     60 static void SetGuid(void *dest, uint32_t num)
     61 {
     62 	Guid g = {{{num,0xd450,0x44bc,0xa6,0x93,
     63 		    {0xb8,0xac,0x75,0x5f,0xcd,0x48}}}};
     64 	Memcpy(dest, &g, sizeof(Guid));
     65 }
     66 
     67 /*
     68  * Given a GptData pointer, first re-calculate entries CRC32 value, then reset
     69  * header CRC32 value to 0, and calculate header CRC32 value.  Both primary and
     70  * secondary are updated.
     71  */
     72 static void RefreshCrc32(GptData *gpt)
     73 {
     74 	GptHeader *header, *header2;
     75 	GptEntry *entries, *entries2;
     76 
     77 	header = (GptHeader *)gpt->primary_header;
     78 	entries = (GptEntry *)gpt->primary_entries;
     79 	header2 = (GptHeader *)gpt->secondary_header;
     80 	entries2 = (GptEntry *)gpt->secondary_entries;
     81 
     82 	header->entries_crc32 =
     83 		Crc32((uint8_t *)entries,
     84 		      header->number_of_entries * header->size_of_entry);
     85 	header->header_crc32 = 0;
     86 	header->header_crc32 = Crc32((uint8_t *)header, header->size);
     87 	header2->entries_crc32 =
     88 		Crc32((uint8_t *)entries2,
     89 		      header2->number_of_entries * header2->size_of_entry);
     90 	header2->header_crc32 = 0;
     91 	header2->header_crc32 = Crc32((uint8_t *)header2, header2->size);
     92 }
     93 
     94 static void ZeroHeaders(GptData *gpt)
     95 {
     96 	Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
     97 	Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
     98 }
     99 
    100 static void ZeroEntries(GptData *gpt)
    101 {
    102 	Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
    103 	Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
    104 }
    105 
    106 static void ZeroHeadersEntries(GptData *gpt)
    107 {
    108 	ZeroHeaders(gpt);
    109 	ZeroEntries(gpt);
    110 }
    111 
    112 /*
    113  * Return a pointer to a static GptData instance (no free is required).
    114  * All fields are zero except 4 pointers linking to header and entries.
    115  * All content of headers and entries are zero.
    116  */
    117 static GptData *GetEmptyGptData(void)
    118 {
    119 	static GptData gpt;
    120 	static uint8_t primary_header[MAX_SECTOR_SIZE];
    121 	static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
    122 	static uint8_t secondary_header[MAX_SECTOR_SIZE];
    123 	static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
    124 
    125 	Memset(&gpt, 0, sizeof(gpt));
    126 	gpt.primary_header = primary_header;
    127 	gpt.primary_entries = primary_entries;
    128 	gpt.secondary_header = secondary_header;
    129 	gpt.secondary_entries = secondary_entries;
    130 	ZeroHeadersEntries(&gpt);
    131 
    132 	/* Initialize GptData internal states. */
    133 	gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
    134 
    135 	return &gpt;
    136 }
    137 
    138 /*
    139  * Fill in most of fields and creates the layout described in the top of this
    140  * file. Before calling this function, primary/secondary header/entries must
    141  * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
    142  * This function returns a good (valid) copy of GPT layout described in top of
    143  * this file.
    144  */
    145 static void BuildTestGptData(GptData *gpt)
    146 {
    147 	GptHeader *header, *header2;
    148 	GptEntry *entries, *entries2;
    149 	Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
    150 	Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
    151 
    152 	gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
    153 	gpt->streaming_drive_sectors =
    154 		gpt->gpt_drive_sectors = DEFAULT_DRIVE_SECTORS;
    155 	gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
    156 	gpt->valid_headers = MASK_BOTH;
    157 	gpt->valid_entries = MASK_BOTH;
    158 	gpt->modified = 0;
    159 
    160 	/* Build primary */
    161 	header = (GptHeader *)gpt->primary_header;
    162 	entries = (GptEntry *)gpt->primary_entries;
    163 	Memcpy(header->signature, GPT_HEADER_SIGNATURE,
    164 	       sizeof(GPT_HEADER_SIGNATURE));
    165 	header->revision = GPT_HEADER_REVISION;
    166 	header->size = sizeof(GptHeader);
    167 	header->reserved_zero = 0;
    168 	header->my_lba = 1;
    169 	header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
    170 	header->first_usable_lba = 34;
    171 	header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1;  /* 433 */
    172 	header->entries_lba = 2;
    173 	  /* 512B / 128B * 32sectors = 128 entries */
    174 	header->number_of_entries = 128;
    175 	header->size_of_entry = 128;  /* bytes */
    176 	Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
    177 	SetGuid(&entries[0].unique, 0);
    178 	entries[0].starting_lba = 34;
    179 	entries[0].ending_lba = 133;
    180 	Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
    181 	SetGuid(&entries[1].unique, 1);
    182 	entries[1].starting_lba = 134;
    183 	entries[1].ending_lba = 232;
    184 	Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
    185 	SetGuid(&entries[2].unique, 2);
    186 	entries[2].starting_lba = 234;
    187 	entries[2].ending_lba = 331;
    188 	Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
    189 	SetGuid(&entries[3].unique, 3);
    190 	entries[3].starting_lba = 334;
    191 	entries[3].ending_lba = 430;
    192 
    193 	/* Build secondary */
    194 	header2 = (GptHeader *)gpt->secondary_header;
    195 	entries2 = (GptEntry *)gpt->secondary_entries;
    196 	Memcpy(header2, header, sizeof(GptHeader));
    197 	Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
    198 	header2->my_lba = DEFAULT_DRIVE_SECTORS - 1;  /* 466 */
    199 	header2->alternate_lba = 1;
    200 	header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32;  /* 434 */
    201 
    202 	RefreshCrc32(gpt);
    203 }
    204 
    205 /*
    206  * Test if the structures are the expected size; if this fails, struct packing
    207  * is not working properly.
    208  */
    209 static int StructSizeTest(void)
    210 {
    211 
    212 	EXPECT(GUID_EXPECTED_SIZE == sizeof(Guid));
    213 	EXPECT(GPTHEADER_EXPECTED_SIZE == sizeof(GptHeader));
    214 	EXPECT(GPTENTRY_EXPECTED_SIZE == sizeof(GptEntry));
    215 	return TEST_OK;
    216 }
    217 
    218 
    219 /* Test if the default structure returned by BuildTestGptData() is good. */
    220 static int TestBuildTestGptData(void)
    221 {
    222 	GptData *gpt;
    223 
    224 	gpt = GetEmptyGptData();
    225 	BuildTestGptData(gpt);
    226 	EXPECT(GPT_SUCCESS == GptInit(gpt));
    227 	gpt->sector_bytes = 0;
    228 	EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptInit(gpt));
    229 	return TEST_OK;
    230 }
    231 
    232 /*
    233  * Test if wrong sector_bytes or drive_sectors is detected by GptInit().
    234  * Currently we only support 512 bytes per sector.  In the future, we may
    235  * support other sizes.  A too small drive_sectors should be rejected by
    236  * GptInit().
    237  */
    238 static int ParameterTests(void)
    239 {
    240 	GptData *gpt;
    241 	struct {
    242 		uint32_t sector_bytes;
    243 		uint64_t drive_sectors;
    244 		int expected_retval;
    245 	} cases[] = {
    246 		{512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
    247 		{520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
    248 		{512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
    249 		{512, 10, GPT_ERROR_INVALID_SECTOR_NUMBER},
    250 		{512, GPT_PMBR_SECTORS + GPT_HEADER_SECTORS * 2 +
    251 		 TOTAL_ENTRIES_SIZE / DEFAULT_SECTOR_SIZE * 2, GPT_SUCCESS},
    252 		{4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
    253 	};
    254 	int i;
    255 
    256 	gpt = GetEmptyGptData();
    257 	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
    258 		BuildTestGptData(gpt);
    259 		gpt->sector_bytes = cases[i].sector_bytes;
    260 		gpt->streaming_drive_sectors =
    261 			gpt->gpt_drive_sectors = cases[i].drive_sectors;
    262 		EXPECT(cases[i].expected_retval == CheckParameters(gpt));
    263 	}
    264 
    265 	return TEST_OK;
    266 }
    267 
    268 /* Test if header CRC in two copies are calculated. */
    269 static int HeaderCrcTest(void)
    270 {
    271 	GptData *gpt = GetEmptyGptData();
    272 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    273 
    274 	BuildTestGptData(gpt);
    275 	EXPECT(HeaderCrc(h1) == h1->header_crc32);
    276 
    277 	/* CRC covers first byte of header */
    278 	BuildTestGptData(gpt);
    279 	gpt->primary_header[0] ^= 0xa5;
    280 	EXPECT(HeaderCrc(h1) != h1->header_crc32);
    281 
    282 	/* CRC covers last byte of header */
    283 	BuildTestGptData(gpt);
    284 	gpt->primary_header[h1->size - 1] ^= 0x5a;
    285 	EXPECT(HeaderCrc(h1) != h1->header_crc32);
    286 
    287 	/* CRC only covers header */
    288 	BuildTestGptData(gpt);
    289 	gpt->primary_header[h1->size] ^= 0x5a;
    290 	EXPECT(HeaderCrc(h1) == h1->header_crc32);
    291 
    292 	return TEST_OK;
    293 }
    294 
    295 /* Test if header-same comparison works. */
    296 static int HeaderSameTest(void)
    297 {
    298 	GptData *gpt = GetEmptyGptData();
    299 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    300 	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
    301 	GptHeader h3;
    302 
    303 	EXPECT(0 == HeaderFieldsSame(h1, h2));
    304 
    305 	Memcpy(&h3, h2, sizeof(h3));
    306 	h3.signature[0] ^= 0xba;
    307 	EXPECT(1 == HeaderFieldsSame(h1, &h3));
    308 
    309 	Memcpy(&h3, h2, sizeof(h3));
    310 	h3.revision++;
    311 	EXPECT(1 == HeaderFieldsSame(h1, &h3));
    312 
    313 	Memcpy(&h3, h2, sizeof(h3));
    314 	h3.size++;
    315 	EXPECT(1 == HeaderFieldsSame(h1, &h3));
    316 
    317 	Memcpy(&h3, h2, sizeof(h3));
    318 	h3.reserved_zero++;
    319 	EXPECT(1 == HeaderFieldsSame(h1, &h3));
    320 
    321 	Memcpy(&h3, h2, sizeof(h3));
    322 	h3.first_usable_lba++;
    323 	EXPECT(1 == HeaderFieldsSame(h1, &h3));
    324 
    325 	Memcpy(&h3, h2, sizeof(h3));
    326 	h3.last_usable_lba++;
    327 	EXPECT(1 == HeaderFieldsSame(h1, &h3));
    328 
    329 	Memcpy(&h3, h2, sizeof(h3));
    330 	h3.disk_uuid.u.raw[0] ^= 0xba;
    331 	EXPECT(1 == HeaderFieldsSame(h1, &h3));
    332 
    333 	Memcpy(&h3, h2, sizeof(h3));
    334 	h3.number_of_entries++;
    335 	EXPECT(1 == HeaderFieldsSame(h1, &h3));
    336 
    337 	Memcpy(&h3, h2, sizeof(h3));
    338 	h3.size_of_entry++;
    339 	EXPECT(1 == HeaderFieldsSame(h1, &h3));
    340 
    341 	Memcpy(&h3, h2, sizeof(h3));
    342 	h3.entries_crc32++;
    343 	EXPECT(1 == HeaderFieldsSame(h1, &h3));
    344 
    345 	return TEST_OK;
    346 }
    347 
    348 /* Test if signature ("EFI PART") is checked. */
    349 static int SignatureTest(void)
    350 {
    351 	GptData *gpt = GetEmptyGptData();
    352 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    353 	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
    354 	int i;
    355 
    356 	EXPECT(1 == CheckHeader(NULL, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    357 
    358 	for (i = 0; i < 8; ++i) {
    359 		BuildTestGptData(gpt);
    360 		h1->signature[i] ^= 0xff;
    361 		h2->signature[i] ^= 0xff;
    362 		RefreshCrc32(gpt);
    363 		EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    364 		EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    365 	}
    366 
    367 	return TEST_OK;
    368 }
    369 
    370 /*
    371  * The revision we currently support is GPT_HEADER_REVISION.  If the revision
    372  * in header is not that, we expect the header is invalid.
    373  */
    374 static int RevisionTest(void)
    375 {
    376 	GptData *gpt = GetEmptyGptData();
    377 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    378 	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
    379 	int i;
    380 
    381 	struct {
    382 		uint32_t value_to_test;
    383 		int expect_rv;
    384 	} cases[] = {
    385 		{0x01000000, 1},
    386 		{0x00010000, 0},  /* GPT_HEADER_REVISION */
    387 		{0x00000100, 1},
    388 		{0x00000001, 1},
    389 		{0x23010456, 1},
    390 	};
    391 
    392 	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
    393 		BuildTestGptData(gpt);
    394 		h1->revision = cases[i].value_to_test;
    395 		h2->revision = cases[i].value_to_test;
    396 		RefreshCrc32(gpt);
    397 
    398 		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
    399 		       cases[i].expect_rv);
    400 		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
    401 		       cases[i].expect_rv);
    402 	}
    403 	return TEST_OK;
    404 }
    405 
    406 static int SizeTest(void)
    407 {
    408 	GptData *gpt = GetEmptyGptData();
    409 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    410 	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
    411 	int i;
    412 
    413 	struct {
    414 		uint32_t value_to_test;
    415 		int expect_rv;
    416 	} cases[] = {
    417 		{91, 1},
    418 		{92, 0},
    419 		{93, 0},
    420 		{511, 0},
    421 		{512, 0},
    422 		{513, 1},
    423 	};
    424 
    425 	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
    426 		BuildTestGptData(gpt);
    427 		h1->size = cases[i].value_to_test;
    428 		h2->size = cases[i].value_to_test;
    429 		RefreshCrc32(gpt);
    430 
    431 		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
    432 		       cases[i].expect_rv);
    433 		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
    434 		       cases[i].expect_rv);
    435 	}
    436 	return TEST_OK;
    437 }
    438 
    439 /* Test if CRC is checked. */
    440 static int CrcFieldTest(void)
    441 {
    442 	GptData *gpt = GetEmptyGptData();
    443 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    444 	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
    445 
    446 	BuildTestGptData(gpt);
    447 	/* Modify a field that the header verification doesn't care about */
    448 	h1->entries_crc32++;
    449 	h2->entries_crc32++;
    450 	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    451 	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    452 	/* Refresh the CRC; should pass now */
    453 	RefreshCrc32(gpt);
    454 	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    455 	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    456 
    457 	return TEST_OK;
    458 }
    459 
    460 /* Test if reserved fields are checked.  We'll try non-zero values to test. */
    461 static int ReservedFieldsTest(void)
    462 {
    463 	GptData *gpt = GetEmptyGptData();
    464 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    465 	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
    466 
    467 	BuildTestGptData(gpt);
    468 	h1->reserved_zero ^= 0x12345678;  /* whatever random */
    469 	h2->reserved_zero ^= 0x12345678;  /* whatever random */
    470 	RefreshCrc32(gpt);
    471 	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    472 	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    473 
    474 #ifdef PADDING_CHECKED
    475 	/* TODO: padding check is currently disabled */
    476 	BuildTestGptData(gpt);
    477 	h1->padding[12] ^= 0x34;  /* whatever random */
    478 	h2->padding[56] ^= 0x78;  /* whatever random */
    479 	RefreshCrc32(gpt);
    480 	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    481 	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    482 #endif
    483 
    484 	return TEST_OK;
    485 }
    486 
    487 /*
    488  * Technically, any size which is 2^N where N > 6 should work, but our
    489  * library only supports one size.
    490  */
    491 static int SizeOfPartitionEntryTest(void) {
    492 	GptData *gpt = GetEmptyGptData();
    493 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    494 	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
    495 	int i;
    496 
    497 	struct {
    498 		uint32_t value_to_test;
    499 		int expect_rv;
    500 	} cases[] = {
    501 		{127, 1},
    502 		{128, 0},
    503 		{129, 1},
    504 		{256, 1},
    505 		{512, 1},
    506 	};
    507 
    508 	/* Check size of entryes */
    509 	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
    510 		BuildTestGptData(gpt);
    511 		h1->size_of_entry = cases[i].value_to_test;
    512 		h2->size_of_entry = cases[i].value_to_test;
    513 		h1->number_of_entries = TOTAL_ENTRIES_SIZE /
    514 			cases[i].value_to_test;
    515 		h2->number_of_entries = TOTAL_ENTRIES_SIZE /
    516 			cases[i].value_to_test;
    517 		RefreshCrc32(gpt);
    518 
    519 		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
    520 		       cases[i].expect_rv);
    521 		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
    522 		       cases[i].expect_rv);
    523 	}
    524 
    525 	return TEST_OK;
    526 }
    527 
    528 /*
    529  * Technically, any size which is 2^N where N > 6 should work, but our library
    530  * only supports one size.
    531  */
    532 static int NumberOfPartitionEntriesTest(void)
    533 {
    534 	GptData *gpt = GetEmptyGptData();
    535 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    536 	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
    537 
    538 	BuildTestGptData(gpt);
    539 	h1->number_of_entries--;
    540 	h2->number_of_entries /= 2;
    541 	/* Because we halved h2 entries, its entries_lba is going to change. */
    542 	h2->entries_lba = h2->my_lba - CalculateEntriesSectors(h2);
    543 	RefreshCrc32(gpt);
    544 	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    545 	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    546 	/* But it's okay to have less if the GPT structs are stored elsewhere. */
    547 	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
    548 	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
    549 
    550 	return TEST_OK;
    551 }
    552 
    553 
    554 /* Test if myLBA field is checked (1 for primary, last for secondary). */
    555 static int MyLbaTest(void)
    556 {
    557 	GptData *gpt = GetEmptyGptData();
    558 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    559 	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
    560 
    561 	/* myLBA depends on primary vs secondary flag */
    562 	BuildTestGptData(gpt);
    563 	EXPECT(1 == CheckHeader(h1, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    564 	EXPECT(1 == CheckHeader(h2, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    565 
    566 	BuildTestGptData(gpt);
    567 	h1->my_lba--;
    568 	h2->my_lba--;
    569 	RefreshCrc32(gpt);
    570 	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    571 	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    572 
    573 	BuildTestGptData(gpt);
    574 	h1->my_lba = 2;
    575 	h2->my_lba--;
    576 	RefreshCrc32(gpt);
    577 	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    578 	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    579 
    580 	/* We should ignore the alternate_lba field entirely */
    581 	BuildTestGptData(gpt);
    582 	h1->alternate_lba++;
    583 	h2->alternate_lba++;
    584 	RefreshCrc32(gpt);
    585 	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    586 	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    587 
    588 	BuildTestGptData(gpt);
    589 	h1->alternate_lba--;
    590 	h2->alternate_lba--;
    591 	RefreshCrc32(gpt);
    592 	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    593 	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    594 
    595 	BuildTestGptData(gpt);
    596 	h1->entries_lba++;
    597 	h2->entries_lba++;
    598 	RefreshCrc32(gpt);
    599 	/*
    600 	 * We support a padding between primary GPT header and its entries. So
    601 	 * this still passes.
    602 	 */
    603 	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    604 	/*
    605 	 * But the secondary table should fail because it would overlap the
    606 	 * header, which is now lying after its entry array.
    607 	 */
    608 	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    609 
    610 	BuildTestGptData(gpt);
    611 	h1->entries_lba--;
    612 	h2->entries_lba--;
    613 	RefreshCrc32(gpt);
    614 	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    615 	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
    616 
    617 	return TEST_OK;
    618 }
    619 
    620 /* Test if FirstUsableLBA and LastUsableLBA are checked.
    621  * FirstUsableLBA must be after the end of the primary GPT table array.
    622  * LastUsableLBA must be before the start of the secondary GPT table array.
    623  * FirstUsableLBA <= LastUsableLBA.
    624  * Also see CheckHeaderOffDevice() test. */
    625 static int FirstUsableLbaAndLastUsableLbaTest(void)
    626 {
    627 	GptData *gpt = GetEmptyGptData();
    628 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    629 	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
    630 	int i;
    631 
    632 	struct {
    633 		uint64_t primary_entries_lba;
    634 		uint64_t primary_first_usable_lba;
    635 		uint64_t primary_last_usable_lba;
    636 		uint64_t secondary_first_usable_lba;
    637 		uint64_t secondary_last_usable_lba;
    638 		uint64_t secondary_entries_lba;
    639 		int primary_rv;
    640 		int secondary_rv;
    641 	} cases[] = {
    642 		{2,  34, 433,   34, 433, 434,  0, 0},
    643 		{2,  34, 432,   34, 430, 434,  0, 0},
    644 		{2,  33, 433,   33, 433, 434,  1, 1},
    645 		{2,  34, 434,   34, 433, 434,  1, 0},
    646 		{2,  34, 433,   34, 434, 434,  0, 1},
    647 		{2,  35, 433,   35, 433, 434,  0, 0},
    648 		{2, 433, 433,  433, 433, 434,  0, 0},
    649 		{2, 434, 433,  434, 434, 434,  1, 1},
    650 		{2, 433,  34,   34, 433, 434,  1, 0},
    651 		{2,  34, 433,  433,  34, 434,  0, 1},
    652 	};
    653 
    654 	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
    655 		BuildTestGptData(gpt);
    656 		h1->entries_lba = cases[i].primary_entries_lba;
    657 		h1->first_usable_lba = cases[i].primary_first_usable_lba;
    658 		h1->last_usable_lba = cases[i].primary_last_usable_lba;
    659 		h2->entries_lba = cases[i].secondary_entries_lba;
    660 		h2->first_usable_lba = cases[i].secondary_first_usable_lba;
    661 		h2->last_usable_lba = cases[i].secondary_last_usable_lba;
    662 		RefreshCrc32(gpt);
    663 
    664 		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
    665 		       cases[i].primary_rv);
    666 		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
    667 		       cases[i].secondary_rv);
    668 	}
    669 
    670 	return TEST_OK;
    671 }
    672 
    673 /*
    674  * Test if PartitionEntryArrayCRC32 is checked.  PartitionEntryArrayCRC32 must
    675  * be calculated over SizeOfPartitionEntry * NumberOfPartitionEntries bytes.
    676  */
    677 static int EntriesCrcTest(void)
    678 {
    679 	GptData *gpt = GetEmptyGptData();
    680 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    681 	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
    682 	GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
    683 
    684 	/* Modify first byte of primary entries, and expect the CRC is wrong. */
    685 	BuildTestGptData(gpt);
    686 	EXPECT(0 == CheckEntries(e1, h1));
    687 	EXPECT(0 == CheckEntries(e2, h1));
    688 	gpt->primary_entries[0] ^= 0xa5;  /* just XOR a non-zero value */
    689 	gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
    690 	EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e1, h1));
    691 	EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e2, h1));
    692 
    693 	return TEST_OK;
    694 }
    695 
    696 /*
    697  * Test if partition geometry is checked.
    698  * All active (non-zero PartitionTypeGUID) partition entries should have:
    699  *   entry.StartingLBA >= header.FirstUsableLBA
    700  *   entry.EndingLBA <= header.LastUsableLBA
    701  *   entry.StartingLBA <= entry.EndingLBA
    702  */
    703 static int ValidEntryTest(void)
    704 {
    705 	GptData *gpt = GetEmptyGptData();
    706 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    707 	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
    708 
    709 	/* error case: entry.StartingLBA < header.FirstUsableLBA */
    710 	BuildTestGptData(gpt);
    711 	e1[0].starting_lba = h1->first_usable_lba - 1;
    712 	RefreshCrc32(gpt);
    713 	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
    714 
    715 	/* error case: entry.EndingLBA > header.LastUsableLBA */
    716 	BuildTestGptData(gpt);
    717 	e1[2].ending_lba = h1->last_usable_lba + 1;
    718 	RefreshCrc32(gpt);
    719 	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
    720 
    721 	/* error case: entry.StartingLBA > entry.EndingLBA */
    722 	BuildTestGptData(gpt);
    723 	e1[3].starting_lba = e1[3].ending_lba + 1;
    724 	RefreshCrc32(gpt);
    725 	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
    726 
    727 	/* case: non active entry should be ignored. */
    728 	BuildTestGptData(gpt);
    729 	Memset(&e1[1].type, 0, sizeof(e1[1].type));
    730 	e1[1].starting_lba = e1[1].ending_lba + 1;
    731 	RefreshCrc32(gpt);
    732 	EXPECT(0 == CheckEntries(e1, h1));
    733 
    734 	return TEST_OK;
    735 }
    736 
    737 /* Test if overlapped partition tables can be detected. */
    738 static int OverlappedPartitionTest(void) {
    739 	GptData *gpt = GetEmptyGptData();
    740 	GptHeader *h = (GptHeader *)gpt->primary_header;
    741 	GptEntry *e = (GptEntry *)gpt->primary_entries;
    742 	int i, j;
    743 
    744 	struct {
    745 		int overlapped;
    746 		struct {
    747 			int active;
    748 			uint64_t starting_lba;
    749 			uint64_t ending_lba;
    750 		} entries[16];  /* enough for testing. */
    751 	} cases[] = {
    752 		{GPT_SUCCESS, {{0, 100, 199}}},
    753 		{GPT_SUCCESS, {{1, 100, 199}}},
    754 		{GPT_SUCCESS, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
    755 		{GPT_ERROR_START_LBA_OVERLAP,
    756 		 {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
    757 		{GPT_ERROR_END_LBA_OVERLAP,
    758 		 {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
    759 		{GPT_SUCCESS, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
    760 		{GPT_ERROR_END_LBA_OVERLAP,
    761 		 {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
    762 		{GPT_ERROR_START_LBA_OVERLAP,
    763 		 {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
    764 		{GPT_ERROR_START_LBA_OVERLAP,
    765 		 {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
    766 		{GPT_ERROR_END_LBA_OVERLAP,
    767 		 {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
    768 		{GPT_ERROR_START_LBA_OVERLAP,
    769 		 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
    770 		{GPT_SUCCESS,
    771 		 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
    772 		{GPT_ERROR_START_LBA_OVERLAP,
    773 		 {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
    774 		{GPT_ERROR_START_LBA_OVERLAP,
    775 		 {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
    776 		{GPT_SUCCESS,
    777 		 {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
    778 		{GPT_ERROR_END_LBA_OVERLAP,
    779 		 {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
    780 		{GPT_SUCCESS, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
    781 		{GPT_SUCCESS, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
    782 		{GPT_ERROR_START_LBA_OVERLAP,
    783 		 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
    784 		  {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
    785 		  {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
    786 		{GPT_SUCCESS,
    787 		 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
    788 		  {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
    789 		  {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
    790 	};
    791 
    792 	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
    793 		BuildTestGptData(gpt);
    794 		ZeroEntries(gpt);
    795 		for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
    796 			if (!cases[i].entries[j].starting_lba)
    797 				break;
    798 
    799 			if (cases[i].entries[j].active) {
    800 				Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
    801 			}
    802 			SetGuid(&e[j].unique, j);
    803 			e[j].starting_lba = cases[i].entries[j].starting_lba;
    804 			e[j].ending_lba = cases[i].entries[j].ending_lba;
    805 		}
    806 		RefreshCrc32(gpt);
    807 
    808 		EXPECT(cases[i].overlapped == CheckEntries(e, h));
    809 	}
    810 	return TEST_OK;
    811 }
    812 
    813 /* Test both sanity checking and repair. */
    814 static int SanityCheckTest(void)
    815 {
    816 	GptData *gpt = GetEmptyGptData();
    817 	GptHeader *h1 = (GptHeader *)gpt->primary_header;
    818 	GptEntry *e1 = (GptEntry *)gpt->primary_entries;
    819 	uint8_t *tempptr;
    820 
    821 	/* Unmodified test data is completely sane */
    822 	BuildTestGptData(gpt);
    823 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    824 	EXPECT(MASK_BOTH == gpt->valid_headers);
    825 	EXPECT(MASK_BOTH == gpt->valid_entries);
    826 	/* Repair doesn't damage it */
    827 	GptRepair(gpt);
    828 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    829 	EXPECT(MASK_BOTH == gpt->valid_headers);
    830 	EXPECT(MASK_BOTH == gpt->valid_entries);
    831 	EXPECT(0 == gpt->modified);
    832 
    833 	/* Invalid sector size should fail */
    834 	BuildTestGptData(gpt);
    835 	gpt->sector_bytes = 1024;
    836 	EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptSanityCheck(gpt));
    837 
    838 	/* Modify headers */
    839 	BuildTestGptData(gpt);
    840 	gpt->primary_header[0]++;
    841 	gpt->secondary_header[0]++;
    842 	EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
    843 	EXPECT(0 == gpt->valid_headers);
    844 	EXPECT(0 == gpt->valid_entries);
    845 	/* Repair can't fix completely busted headers */
    846 	GptRepair(gpt);
    847 	EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
    848 	EXPECT(0 == gpt->valid_headers);
    849 	EXPECT(0 == gpt->valid_entries);
    850 	EXPECT(0 == gpt->modified);
    851 
    852 	BuildTestGptData(gpt);
    853 	gpt->primary_header[0]++;
    854 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    855 	EXPECT(MASK_SECONDARY == gpt->valid_headers);
    856 	EXPECT(MASK_BOTH == gpt->valid_entries);
    857 	GptRepair(gpt);
    858 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    859 	EXPECT(MASK_BOTH == gpt->valid_headers);
    860 	EXPECT(MASK_BOTH == gpt->valid_entries);
    861 	EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
    862 
    863 	BuildTestGptData(gpt);
    864 	gpt->secondary_header[0]++;
    865 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    866 	EXPECT(MASK_PRIMARY == gpt->valid_headers);
    867 	EXPECT(MASK_BOTH == gpt->valid_entries);
    868 	GptRepair(gpt);
    869 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    870 	EXPECT(MASK_BOTH == gpt->valid_headers);
    871 	EXPECT(MASK_BOTH == gpt->valid_entries);
    872 	EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
    873 
    874 	/*
    875 	 * Modify header1 and update its CRC.  Since header2 is now different
    876 	 * than header1, it'll be the one considered invalid.
    877 	 */
    878 	BuildTestGptData(gpt);
    879 	h1->size++;
    880 	RefreshCrc32(gpt);
    881 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    882 	EXPECT(MASK_PRIMARY == gpt->valid_headers);
    883 	EXPECT(MASK_BOTH == gpt->valid_entries);
    884 	GptRepair(gpt);
    885 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    886 	EXPECT(MASK_BOTH == gpt->valid_headers);
    887 	EXPECT(MASK_BOTH == gpt->valid_entries);
    888 	EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
    889 
    890 	/* Modify entries */
    891 	BuildTestGptData(gpt);
    892 	gpt->primary_entries[0]++;
    893 	gpt->secondary_entries[0]++;
    894 	EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
    895 	EXPECT(MASK_BOTH == gpt->valid_headers);
    896 	EXPECT(MASK_NONE == gpt->valid_entries);
    897 	/* Repair can't fix both copies of entries being bad, either. */
    898 	GptRepair(gpt);
    899 	EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
    900 	EXPECT(MASK_BOTH == gpt->valid_headers);
    901 	EXPECT(MASK_NONE == gpt->valid_entries);
    902 	EXPECT(0 == gpt->modified);
    903 
    904 	BuildTestGptData(gpt);
    905 	gpt->primary_entries[0]++;
    906 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    907 	EXPECT(MASK_BOTH == gpt->valid_headers);
    908 	EXPECT(MASK_SECONDARY == gpt->valid_entries);
    909 	GptRepair(gpt);
    910 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    911 	EXPECT(MASK_BOTH == gpt->valid_headers);
    912 	EXPECT(MASK_BOTH == gpt->valid_entries);
    913 	EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
    914 
    915 	BuildTestGptData(gpt);
    916 	gpt->secondary_entries[0]++;
    917 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    918 	EXPECT(MASK_BOTH == gpt->valid_headers);
    919 	EXPECT(MASK_PRIMARY == gpt->valid_entries);
    920 	GptRepair(gpt);
    921 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    922 	EXPECT(MASK_BOTH == gpt->valid_headers);
    923 	EXPECT(MASK_BOTH == gpt->valid_entries);
    924 	EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
    925 
    926 	/*
    927 	 * Modify entries and recompute CRCs, then make both primary and
    928 	 * secondary entry pointers use the secondary data.  The primary
    929 	 * header will have the wrong entries CRC, so we should fall back
    930 	 * to the secondary header.
    931 	 */
    932 	BuildTestGptData(gpt);
    933 	e1->starting_lba++;
    934 	RefreshCrc32(gpt);
    935 	tempptr = gpt->primary_entries;
    936 	gpt->primary_entries = gpt->secondary_entries;
    937 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    938 	EXPECT(MASK_SECONDARY == gpt->valid_headers);
    939 	EXPECT(MASK_BOTH == gpt->valid_entries);
    940 	gpt->primary_entries = tempptr;
    941 
    942 	/* Modify both header and entries */
    943 	BuildTestGptData(gpt);
    944 	gpt->primary_header[0]++;
    945 	gpt->primary_entries[0]++;
    946 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    947 	EXPECT(MASK_SECONDARY == gpt->valid_headers);
    948 	EXPECT(MASK_SECONDARY == gpt->valid_entries);
    949 	GptRepair(gpt);
    950 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    951 	EXPECT(MASK_BOTH == gpt->valid_headers);
    952 	EXPECT(MASK_BOTH == gpt->valid_entries);
    953 	EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
    954 
    955 	BuildTestGptData(gpt);
    956 	gpt->secondary_header[0]++;
    957 	gpt->secondary_entries[0]++;
    958 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    959 	EXPECT(MASK_PRIMARY == gpt->valid_headers);
    960 	EXPECT(MASK_PRIMARY == gpt->valid_entries);
    961 	GptRepair(gpt);
    962 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    963 	EXPECT(MASK_BOTH == gpt->valid_headers);
    964 	EXPECT(MASK_BOTH == gpt->valid_entries);
    965 	EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
    966 
    967 	/* Test cross-correction (h1+e2, h2+e1) */
    968 	BuildTestGptData(gpt);
    969 	gpt->primary_header[0]++;
    970 	gpt->secondary_entries[0]++;
    971 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    972 	EXPECT(MASK_SECONDARY == gpt->valid_headers);
    973 	EXPECT(MASK_PRIMARY == gpt->valid_entries);
    974 	GptRepair(gpt);
    975 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    976 	EXPECT(MASK_BOTH == gpt->valid_headers);
    977 	EXPECT(MASK_BOTH == gpt->valid_entries);
    978 	EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
    979 
    980 	BuildTestGptData(gpt);
    981 	gpt->secondary_header[0]++;
    982 	gpt->primary_entries[0]++;
    983 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    984 	EXPECT(MASK_PRIMARY == gpt->valid_headers);
    985 	EXPECT(MASK_SECONDARY == gpt->valid_entries);
    986 	GptRepair(gpt);
    987 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
    988 	EXPECT(MASK_BOTH == gpt->valid_headers);
    989 	EXPECT(MASK_BOTH == gpt->valid_entries);
    990 	EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
    991 
    992 	/*
    993 	 * Test mismatched pairs (h1+e1 valid, h2+e2 valid but different.  This
    994 	 * simulates a partial update of the drive.
    995 	 */
    996 	BuildTestGptData(gpt);
    997 	gpt->secondary_entries[0]++;
    998 	RefreshCrc32(gpt);
    999 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
   1000 	EXPECT(MASK_PRIMARY == gpt->valid_headers);
   1001 	EXPECT(MASK_PRIMARY == gpt->valid_entries);
   1002 	GptRepair(gpt);
   1003 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
   1004 	EXPECT(MASK_BOTH == gpt->valid_headers);
   1005 	EXPECT(MASK_BOTH == gpt->valid_entries);
   1006 	EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
   1007 
   1008 	/* Test unloaded entry array. */
   1009 	gpt = GetEmptyGptData();
   1010 	BuildTestGptData(gpt);
   1011 	gpt->primary_entries = NULL;
   1012 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
   1013 	EXPECT(MASK_SECONDARY == gpt->valid_entries);
   1014 	gpt = GetEmptyGptData();
   1015 	BuildTestGptData(gpt);
   1016 	gpt->secondary_entries = NULL;
   1017 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
   1018 	EXPECT(MASK_PRIMARY == gpt->valid_entries);
   1019 
   1020 	/* Test unloaded header. */
   1021 	gpt = GetEmptyGptData();
   1022 	BuildTestGptData(gpt);
   1023 	gpt->primary_header = NULL;
   1024 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
   1025 	EXPECT(MASK_SECONDARY == gpt->valid_headers);
   1026 	gpt = GetEmptyGptData();
   1027 	BuildTestGptData(gpt);
   1028 	gpt->secondary_header = NULL;
   1029 	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
   1030 	EXPECT(MASK_PRIMARY == gpt->valid_headers);
   1031 
   1032 	return TEST_OK;
   1033 }
   1034 
   1035 static int EntryAttributeGetSetTest(void)
   1036 {
   1037 	GptData *gpt = GetEmptyGptData();
   1038 	GptEntry *e = (GptEntry *)(gpt->primary_entries);
   1039 
   1040 	e->attrs.whole = 0x0000000000000000ULL;
   1041 	SetEntrySuccessful(e, 1);
   1042 	EXPECT(0x0100000000000000ULL == e->attrs.whole);
   1043 	EXPECT(1 == GetEntrySuccessful(e));
   1044 	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
   1045 	SetEntrySuccessful(e, 0);
   1046 	EXPECT(0xFEFFFFFFFFFFFFFFULL == e->attrs.whole);
   1047 	EXPECT(0 == GetEntrySuccessful(e));
   1048 
   1049 	e->attrs.whole = 0x0000000000000000ULL;
   1050 	SetEntryTries(e, 15);
   1051 	EXPECT(15 == GetEntryTries(e));
   1052 	EXPECT(0x00F0000000000000ULL == e->attrs.whole);
   1053 	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
   1054 	SetEntryTries(e, 0);
   1055 	EXPECT(0xFF0FFFFFFFFFFFFFULL == e->attrs.whole);
   1056 	EXPECT(0 == GetEntryTries(e));
   1057 
   1058 	e->attrs.whole = 0x0000000000000000ULL;
   1059 	SetEntryPriority(e, 15);
   1060 	EXPECT(0x000F000000000000ULL == e->attrs.whole);
   1061 	EXPECT(15 == GetEntryPriority(e));
   1062 	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
   1063 	SetEntryPriority(e, 0);
   1064 	EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole);
   1065 	EXPECT(0 == GetEntryPriority(e));
   1066 
   1067 	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
   1068 	EXPECT(1 == GetEntrySuccessful(e));
   1069 	EXPECT(15 == GetEntryPriority(e));
   1070 	EXPECT(15 == GetEntryTries(e));
   1071 
   1072 	e->attrs.whole = 0x0123000000000000ULL;
   1073 	EXPECT(1 == GetEntrySuccessful(e));
   1074 	EXPECT(2 == GetEntryTries(e));
   1075 	EXPECT(3 == GetEntryPriority(e));
   1076 
   1077 	return TEST_OK;
   1078 }
   1079 
   1080 static int EntryTypeTest(void)
   1081 {
   1082 	GptData *gpt = GetEmptyGptData();
   1083 	GptEntry *e = (GptEntry *)(gpt->primary_entries);
   1084 
   1085 	Memcpy(&e->type, &guid_zero, sizeof(Guid));
   1086 	EXPECT(1 == IsUnusedEntry(e));
   1087 	EXPECT(0 == IsKernelEntry(e));
   1088 
   1089 	Memcpy(&e->type, &guid_kernel, sizeof(Guid));
   1090 	EXPECT(0 == IsUnusedEntry(e));
   1091 	EXPECT(1 == IsKernelEntry(e));
   1092 
   1093 	Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
   1094 	EXPECT(0 == IsUnusedEntry(e));
   1095 	EXPECT(0 == IsKernelEntry(e));
   1096 
   1097 	return TEST_OK;
   1098 }
   1099 
   1100 /* Make an entry unused by clearing its type. */
   1101 static void FreeEntry(GptEntry *e)
   1102 {
   1103 	Memset(&e->type, 0, sizeof(Guid));
   1104 }
   1105 
   1106 /* Set up an entry. */
   1107 static void FillEntry(GptEntry *e, int is_kernel,
   1108                       int priority, int successful, int tries)
   1109 {
   1110 	Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
   1111 	SetEntryPriority(e, priority);
   1112 	SetEntrySuccessful(e, successful);
   1113 	SetEntryTries(e, tries);
   1114 }
   1115 
   1116 /*
   1117  * Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
   1118  * any usable kernel entry.
   1119  */
   1120 static int NoValidKernelEntryTest(void)
   1121 {
   1122 	GptData *gpt = GetEmptyGptData();
   1123 	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
   1124 
   1125 	BuildTestGptData(gpt);
   1126 	SetEntryPriority(e1 + KERNEL_A, 0);
   1127 	FreeEntry(e1 + KERNEL_B);
   1128 	RefreshCrc32(gpt);
   1129 	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
   1130 	       GptNextKernelEntry(gpt, NULL, NULL));
   1131 
   1132 	return TEST_OK;
   1133 }
   1134 
   1135 static int GetNextNormalTest(void)
   1136 {
   1137 	GptData *gpt = GetEmptyGptData();
   1138 	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
   1139 	uint64_t start, size;
   1140 
   1141 	/* Normal case - both kernels successful */
   1142 	BuildTestGptData(gpt);
   1143 	FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
   1144 	FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
   1145 	RefreshCrc32(gpt);
   1146 	GptInit(gpt);
   1147 
   1148 	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
   1149 	EXPECT(KERNEL_A == gpt->current_kernel);
   1150 	EXPECT(34 == start);
   1151 	EXPECT(100 == size);
   1152 
   1153 	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
   1154 	EXPECT(KERNEL_B == gpt->current_kernel);
   1155 	EXPECT(134 == start);
   1156 	EXPECT(99 == size);
   1157 
   1158 	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
   1159 	       GptNextKernelEntry(gpt, &start, &size));
   1160 	EXPECT(-1 == gpt->current_kernel);
   1161 
   1162 	/* Call as many times as you want; you won't get another kernel... */
   1163 	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
   1164 	       GptNextKernelEntry(gpt, &start, &size));
   1165 	EXPECT(-1 == gpt->current_kernel);
   1166 
   1167 	return TEST_OK;
   1168 }
   1169 
   1170 static int GetNextPrioTest(void)
   1171 {
   1172 	GptData *gpt = GetEmptyGptData();
   1173 	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
   1174 	uint64_t start, size;
   1175 
   1176 	/* Priority 3, 4, 0, 4 - should boot order B, Y, A */
   1177 	BuildTestGptData(gpt);
   1178 	FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
   1179 	FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
   1180 	FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
   1181 	FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
   1182 	RefreshCrc32(gpt);
   1183 	GptInit(gpt);
   1184 
   1185 	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
   1186 	EXPECT(KERNEL_B == gpt->current_kernel);
   1187 	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
   1188 	EXPECT(KERNEL_Y == gpt->current_kernel);
   1189 	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
   1190 	EXPECT(KERNEL_A == gpt->current_kernel);
   1191 	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
   1192 	       GptNextKernelEntry(gpt, &start, &size));
   1193 
   1194 	return TEST_OK;
   1195 }
   1196 
   1197 static int GetNextTriesTest(void)
   1198 {
   1199 	GptData *gpt = GetEmptyGptData();
   1200 	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
   1201 	uint64_t start, size;
   1202 
   1203 	/* Tries=nonzero is attempted just like success, but tries=0 isn't */
   1204 	BuildTestGptData(gpt);
   1205 	FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
   1206 	FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
   1207 	FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
   1208 	FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
   1209 	RefreshCrc32(gpt);
   1210 	GptInit(gpt);
   1211 
   1212 	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
   1213 	EXPECT(KERNEL_X == gpt->current_kernel);
   1214 	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
   1215 	EXPECT(KERNEL_A == gpt->current_kernel);
   1216 	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
   1217 	       GptNextKernelEntry(gpt, &start, &size));
   1218 
   1219 	return TEST_OK;
   1220 }
   1221 
   1222 static int GptUpdateTest(void)
   1223 {
   1224 	GptData *gpt = GetEmptyGptData();
   1225 	GptEntry *e = (GptEntry *)(gpt->primary_entries);
   1226 	GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
   1227 	uint64_t start, size;
   1228 
   1229 	/* Tries=nonzero is attempted just like success, but tries=0 isn't */
   1230 	BuildTestGptData(gpt);
   1231 	FillEntry(e + KERNEL_A, 1, 4, 1, 0);
   1232 	FillEntry(e + KERNEL_B, 1, 3, 0, 2);
   1233 	FillEntry(e + KERNEL_X, 1, 2, 0, 2);
   1234 	RefreshCrc32(gpt);
   1235 	GptInit(gpt);
   1236 	gpt->modified = 0;  /* Nothing modified yet */
   1237 
   1238 	/* Successful kernel */
   1239 	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
   1240 	EXPECT(KERNEL_A == gpt->current_kernel);
   1241 	EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
   1242 	EXPECT(4 == GetEntryPriority(e + KERNEL_A));
   1243 	EXPECT(0 == GetEntryTries(e + KERNEL_A));
   1244 	EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
   1245 	EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
   1246 	EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
   1247 	/* Trying successful kernel changes nothing */
   1248 	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
   1249 	EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
   1250 	EXPECT(4 == GetEntryPriority(e + KERNEL_A));
   1251 	EXPECT(0 == GetEntryTries(e + KERNEL_A));
   1252 	EXPECT(0 == gpt->modified);
   1253 	/* Marking it bad also does not update it. */
   1254 	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
   1255 	EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
   1256 	EXPECT(4 == GetEntryPriority(e + KERNEL_A));
   1257 	EXPECT(0 == GetEntryTries(e + KERNEL_A));
   1258 	EXPECT(0 == gpt->modified);
   1259 
   1260 	/* Kernel with tries */
   1261 	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
   1262 	EXPECT(KERNEL_B == gpt->current_kernel);
   1263 	EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
   1264 	EXPECT(3 == GetEntryPriority(e + KERNEL_B));
   1265 	EXPECT(2 == GetEntryTries(e + KERNEL_B));
   1266 	/* Marking it bad clears it */
   1267 	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
   1268 	EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
   1269 	EXPECT(0 == GetEntryPriority(e + KERNEL_B));
   1270 	EXPECT(0 == GetEntryTries(e + KERNEL_B));
   1271 	/* Which affects both copies of the partition entries */
   1272 	EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_B));
   1273 	EXPECT(0 == GetEntryPriority(e2 + KERNEL_B));
   1274 	EXPECT(0 == GetEntryTries(e2 + KERNEL_B));
   1275 	/* And that's caused the GPT to need updating */
   1276 	EXPECT(0x0F == gpt->modified);
   1277 
   1278 	/* Another kernel with tries */
   1279 	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
   1280 	EXPECT(KERNEL_X == gpt->current_kernel);
   1281 	EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
   1282 	EXPECT(2 == GetEntryPriority(e + KERNEL_X));
   1283 	EXPECT(2 == GetEntryTries(e + KERNEL_X));
   1284 	/* Trying it uses up a try */
   1285 	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
   1286 	EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
   1287 	EXPECT(2 == GetEntryPriority(e + KERNEL_X));
   1288 	EXPECT(1 == GetEntryTries(e + KERNEL_X));
   1289 	EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
   1290 	EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
   1291 	EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
   1292 	/* Trying it again marks it inactive */
   1293 	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
   1294 	EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
   1295 	EXPECT(0 == GetEntryPriority(e + KERNEL_X));
   1296 	EXPECT(0 == GetEntryTries(e + KERNEL_X));
   1297 
   1298 	/* Can't update if entry isn't a kernel, or there isn't an entry */
   1299 	Memcpy(&e[KERNEL_X].type, &guid_rootfs, sizeof(guid_rootfs));
   1300 	EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
   1301 	       GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
   1302 	gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
   1303 	EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
   1304 	       GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
   1305 
   1306 
   1307 	return TEST_OK;
   1308 }
   1309 
   1310 /*
   1311  * Give an invalid kernel type, and expect GptUpdateKernelEntry() returns
   1312  * GPT_ERROR_INVALID_UPDATE_TYPE.
   1313  */
   1314 static int UpdateInvalidKernelTypeTest(void)
   1315 {
   1316 	GptData *gpt = GetEmptyGptData();
   1317 
   1318 	BuildTestGptData(gpt);
   1319 	/* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
   1320 	gpt->current_kernel = 0;
   1321 	/* any invalid update_type value */
   1322 	EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
   1323 	       GptUpdateKernelEntry(gpt, 99));
   1324 
   1325 	return TEST_OK;
   1326 }
   1327 
   1328 /* Test duplicate UniqueGuids can be detected. */
   1329 static int DuplicateUniqueGuidTest(void)
   1330 {
   1331 	GptData *gpt = GetEmptyGptData();
   1332 	GptHeader *h = (GptHeader *)gpt->primary_header;
   1333 	GptEntry *e = (GptEntry *)gpt->primary_entries;
   1334 	int i, j;
   1335 
   1336 	struct {
   1337 		int duplicate;
   1338 		struct {
   1339 			uint64_t starting_lba;
   1340 			uint64_t ending_lba;
   1341 			uint32_t type_guid;
   1342 			uint32_t unique_guid;
   1343 		} entries[16];   /* enough for testing. */
   1344 	} cases[] = {
   1345 		{GPT_SUCCESS, {{100, 109, 1, 1},
   1346 			       {110, 119, 2, 2},
   1347 			       {120, 129, 3, 3},
   1348 			       {130, 139, 4, 4},
   1349 			}},
   1350 		{GPT_SUCCESS, {{100, 109, 1, 1},
   1351 			       {110, 119, 1, 2},
   1352 			       {120, 129, 2, 3},
   1353 			       {130, 139, 2, 4},
   1354 			}},
   1355 		{GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
   1356 				      {110, 119, 2, 2},
   1357 				      {120, 129, 3, 1},
   1358 				      {130, 139, 4, 4},
   1359 			}},
   1360 		{GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
   1361 				      {110, 119, 1, 2},
   1362 				      {120, 129, 2, 3},
   1363 				      {130, 139, 2, 2},
   1364 			}},
   1365 	};
   1366 
   1367 	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
   1368 		BuildTestGptData(gpt);
   1369 		ZeroEntries(gpt);
   1370 		for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
   1371 			if (!cases[i].entries[j].starting_lba)
   1372 				break;
   1373 
   1374 			e[j].starting_lba = cases[i].entries[j].starting_lba;
   1375 			e[j].ending_lba = cases[i].entries[j].ending_lba;
   1376 			SetGuid(&e[j].type, cases[i].entries[j].type_guid);
   1377 			SetGuid(&e[j].unique, cases[i].entries[j].unique_guid);
   1378 		}
   1379 		RefreshCrc32(gpt);
   1380 
   1381 		EXPECT(cases[i].duplicate == CheckEntries(e, h));
   1382 	}
   1383 
   1384 	return TEST_OK;
   1385 }
   1386 
   1387 /* Test getting the current kernel GUID */
   1388 static int GetKernelGuidTest(void)
   1389 {
   1390 	GptData *gpt = GetEmptyGptData();
   1391 	GptEntry *e = (GptEntry *)gpt->primary_entries;
   1392 	Guid g;
   1393 
   1394 	BuildTestGptData(gpt);
   1395 	gpt->current_kernel = 0;
   1396 	GetCurrentKernelUniqueGuid(gpt, &g);
   1397 	EXPECT(!Memcmp(&g, &e[0].unique, sizeof(Guid)));
   1398 	gpt->current_kernel = 1;
   1399 	GetCurrentKernelUniqueGuid(gpt, &g);
   1400 	EXPECT(!Memcmp(&g, &e[1].unique, sizeof(Guid)));
   1401 
   1402 	return TEST_OK;
   1403 }
   1404 
   1405 /* Test getting GPT error text strings */
   1406 static int ErrorTextTest(void)
   1407 {
   1408 	int i;
   1409 
   1410 	/* Known errors are not unknown */
   1411 	for (i = 0; i < GPT_ERROR_COUNT; i++) {
   1412 		EXPECT(GptErrorText(i));
   1413 		EXPECT(strcmp(GptErrorText(i), "Unknown"));
   1414 	}
   1415 
   1416 	/* But other error values are */
   1417 	EXPECT(!strcmp(GptErrorText(GPT_ERROR_COUNT), "Unknown"));
   1418 
   1419 	return TEST_OK;
   1420 }
   1421 
   1422 static int CheckHeaderOffDevice()
   1423 {
   1424 	GptData* gpt = GetEmptyGptData();
   1425 	BuildTestGptData(gpt);
   1426 
   1427 	GptHeader* primary_header = (GptHeader*)gpt->primary_header;
   1428 	primary_header->first_usable_lba = 0;
   1429 	RefreshCrc32(gpt);
   1430 	// GPT is stored on the same device so first usable lba should not
   1431 	// start at 0.
   1432 	EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
   1433 		gpt->gpt_drive_sectors, 0));
   1434 	// But off device, it is okay to accept this GPT header.
   1435 	EXPECT(0 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
   1436 		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
   1437 
   1438 	BuildTestGptData(gpt);
   1439 	primary_header->number_of_entries = 100;
   1440 	RefreshCrc32(gpt);
   1441 	// Normally, number of entries is 128. So this should fail.
   1442 	EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
   1443 		gpt->gpt_drive_sectors, 0));
   1444 	// But off device, it is okay.
   1445 	EXPECT(0 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
   1446 		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
   1447 
   1448 	primary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
   1449 	RefreshCrc32(gpt);
   1450 	// However, too few entries is not good.
   1451 	EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
   1452 		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
   1453 
   1454 	// Repeat for secondary header.
   1455 	BuildTestGptData(gpt);
   1456 	GptHeader* secondary_header = (GptHeader*)gpt->secondary_header;
   1457 	secondary_header->first_usable_lba = 0;
   1458 	RefreshCrc32(gpt);
   1459 	EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
   1460 		gpt->gpt_drive_sectors, 0));
   1461 	EXPECT(0 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
   1462 		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
   1463 
   1464 	BuildTestGptData(gpt);
   1465 	secondary_header->number_of_entries = 100;
   1466 	/* Because we change number of entries, we need to also update entrie_lba. */
   1467 	secondary_header->entries_lba = secondary_header->my_lba -
   1468 		CalculateEntriesSectors(secondary_header);
   1469 	RefreshCrc32(gpt);
   1470 	EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
   1471 		gpt->gpt_drive_sectors, 0));
   1472 	EXPECT(0 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
   1473 		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
   1474 
   1475 	secondary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
   1476 	RefreshCrc32(gpt);
   1477 	EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
   1478 		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
   1479 
   1480 	return TEST_OK;
   1481 }
   1482 
   1483 int main(int argc, char *argv[])
   1484 {
   1485 	int i;
   1486 	int error_count = 0;
   1487 	struct {
   1488 		char *name;
   1489 		test_func fp;
   1490 		int retval;
   1491 	} test_cases[] = {
   1492 		{ TEST_CASE(StructSizeTest), },
   1493 		{ TEST_CASE(TestBuildTestGptData), },
   1494 		{ TEST_CASE(ParameterTests), },
   1495 		{ TEST_CASE(HeaderCrcTest), },
   1496 		{ TEST_CASE(HeaderSameTest), },
   1497 		{ TEST_CASE(SignatureTest), },
   1498 		{ TEST_CASE(RevisionTest), },
   1499 		{ TEST_CASE(SizeTest), },
   1500 		{ TEST_CASE(CrcFieldTest), },
   1501 		{ TEST_CASE(ReservedFieldsTest), },
   1502 		{ TEST_CASE(SizeOfPartitionEntryTest), },
   1503 		{ TEST_CASE(NumberOfPartitionEntriesTest), },
   1504 		{ TEST_CASE(MyLbaTest), },
   1505 		{ TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
   1506 		{ TEST_CASE(EntriesCrcTest), },
   1507 		{ TEST_CASE(ValidEntryTest), },
   1508 		{ TEST_CASE(OverlappedPartitionTest), },
   1509 		{ TEST_CASE(SanityCheckTest), },
   1510 		{ TEST_CASE(NoValidKernelEntryTest), },
   1511 		{ TEST_CASE(EntryAttributeGetSetTest), },
   1512 		{ TEST_CASE(EntryTypeTest), },
   1513 		{ TEST_CASE(GetNextNormalTest), },
   1514 		{ TEST_CASE(GetNextPrioTest), },
   1515 		{ TEST_CASE(GetNextTriesTest), },
   1516 		{ TEST_CASE(GptUpdateTest), },
   1517 		{ TEST_CASE(UpdateInvalidKernelTypeTest), },
   1518 		{ TEST_CASE(DuplicateUniqueGuidTest), },
   1519 		{ TEST_CASE(TestCrc32TestVectors), },
   1520 		{ TEST_CASE(GetKernelGuidTest), },
   1521 		{ TEST_CASE(ErrorTextTest), },
   1522 		{ TEST_CASE(CheckHeaderOffDevice), },
   1523 	};
   1524 
   1525 	for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
   1526 		printf("Running %s() ...\n", test_cases[i].name);
   1527 		test_cases[i].retval = test_cases[i].fp();
   1528 		if (test_cases[i].retval) {
   1529 			printf(COL_RED "[ERROR]\n\n" COL_STOP);
   1530 			++error_count;
   1531 		} else {
   1532 			printf(COL_GREEN "[PASS]\n\n" COL_STOP);
   1533 		}
   1534 	}
   1535 
   1536 	if (error_count) {
   1537 		printf("\n------------------------------------------------\n");
   1538 		printf(COL_RED "The following %d test cases are failed:\n"
   1539 		       COL_STOP, error_count);
   1540 		for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
   1541 			if (test_cases[i].retval)
   1542 				printf("  %s()\n", test_cases[i].name);
   1543 		}
   1544 	}
   1545 
   1546 	return error_count ? 1 : 0;
   1547 }
   1548