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