• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
SetGuid(void * dest,uint32_t num)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  */
RefreshCrc32(GptData * gpt)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 
ZeroHeaders(GptData * gpt)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 
ZeroEntries(GptData * gpt)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 
ZeroHeadersEntries(GptData * gpt)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  */
GetEmptyGptData(void)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  */
BuildTestGptData(GptData * gpt)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  */
StructSizeTest(void)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. */
TestBuildTestGptData(void)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  */
ParameterTests(void)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. */
HeaderCrcTest(void)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. */
HeaderSameTest(void)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. */
SignatureTest(void)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  */
RevisionTest(void)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 
SizeTest(void)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. */
CrcFieldTest(void)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. */
ReservedFieldsTest(void)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  */
SizeOfPartitionEntryTest(void)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  */
NumberOfPartitionEntriesTest(void)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). */
MyLbaTest(void)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. */
FirstUsableLbaAndLastUsableLbaTest(void)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  */
EntriesCrcTest(void)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  */
ValidEntryTest(void)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. */
OverlappedPartitionTest(void)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. */
SanityCheckTest(void)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 
EntryAttributeGetSetTest(void)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 
EntryTypeTest(void)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. */
FreeEntry(GptEntry * e)1101 static void FreeEntry(GptEntry *e)
1102 {
1103 	Memset(&e->type, 0, sizeof(Guid));
1104 }
1105 
1106 /* Set up an entry. */
FillEntry(GptEntry * e,int is_kernel,int priority,int successful,int tries)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  */
NoValidKernelEntryTest(void)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 
GetNextNormalTest(void)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 
GetNextPrioTest(void)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 
GetNextTriesTest(void)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 
GptUpdateTest(void)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  */
UpdateInvalidKernelTypeTest(void)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. */
DuplicateUniqueGuidTest(void)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 */
GetKernelGuidTest(void)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 */
ErrorTextTest(void)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 
CheckHeaderOffDevice()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 
main(int argc,char * argv[])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