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