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