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