diff --git a/cgptlib/cgpt.c b/cgptlib/cgpt.c index 7f18a1cf8d..4504a618a5 100644 --- a/cgptlib/cgpt.c +++ b/cgptlib/cgpt.c @@ -9,19 +9,19 @@ static int start[] = { 34, 10034 }; int GPTInit(GPTData_t *gpt) { - gpt->current_kernel = 1; - return 0; + gpt->current_kernel = 1; + return 0; } int GPTNextKernelEntry(GPTData_t *gpt, uint64_t *start_sector, uint64_t *size) { - gpt->current_kernel ^= 1; - if (start_sector) *start_sector = start[gpt->current_kernel]; - if (size) *size = 10000; - return 0; + gpt->current_kernel ^= 1; + if (start_sector) *start_sector = start[gpt->current_kernel]; + if (size) *size = 10000; + return 0; } int GPTUpdateKernelEntry(GPTData_t *gpt, uint32_t update_type) { - gpt->modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) << - gpt->current_kernel; - return 0; + gpt->modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) << + gpt->current_kernel; + return 0; } diff --git a/cgptlib/cgpt.h b/cgptlib/cgpt.h index acc1ec9e66..c9cd04ddb9 100644 --- a/cgptlib/cgpt.h +++ b/cgptlib/cgpt.h @@ -9,10 +9,11 @@ #include enum { - GPT_ERROR_INVALID_HEADERS = 1, - GPT_ERROR_INVALID_ENTRIES, - GPT_ERROR_INVALID_SECTOR_SIZE, - GPT_ERROR_INVALID_SECTOR_NUMBER, + GPT_ERROR_NO_VALID_KERNEL = 1, + GPT_ERROR_INVALID_HEADERS, + GPT_ERROR_INVALID_ENTRIES, + GPT_ERROR_INVALID_SECTOR_SIZE, + GPT_ERROR_INVALID_SECTOR_NUMBER, }; #define GPT_MODIFIED_HEADER1 0x01 @@ -28,27 +29,27 @@ enum { * invalid. */ struct GPTData { - /* Fill in the following fields before calling GPTInit() */ - uint8_t *header1; /* GPT primary header, from sector 1 of disk - * (size: 512 bytes) */ - uint8_t *header2; /* GPT secondary header, from last sector of - * disk (size: 512 bytes) */ - uint8_t *entries1; /* primary GPT table, follows primary header - * (size: 16 KB) */ - uint8_t *entries2; /* secondary GPT table, precedes secondary - * header (size: 16 KB) */ - uint32_t sector_bytes; /* Size of a LBA sector, in bytes */ - uint64_t drive_sectors; /* Size of drive in LBA sectors, in sectors */ + /* Fill in the following fields before calling GPTInit() */ + uint8_t *header1; /* GPT primary header, from sector 1 of disk + * (size: 512 bytes) */ + uint8_t *header2; /* GPT secondary header, from last sector of + * disk (size: 512 bytes) */ + uint8_t *entries1; /* primary GPT table, follows primary header + * (size: 16 KB) */ + uint8_t *entries2; /* secondary GPT table, precedes secondary + * header (size: 16 KB) */ + uint32_t sector_bytes; /* Size of a LBA sector, in bytes */ + uint64_t drive_sectors; /* Size of drive in LBA sectors, in sectors */ - /* Outputs */ - uint8_t modified; /* Which inputs have been modified? - * 0x01 = header1 - * 0x02 = header2 - * 0x04 = table1 - * 0x08 = table2 */ + /* Outputs */ + uint8_t modified; /* Which inputs have been modified? + * 0x01 = header1 + * 0x02 = header2 + * 0x04 = table1 + * 0x08 = table2 */ - /* Internal state */ - uint8_t current_kernel; // the current kernel index + /* Internal state */ + uint8_t current_kernel; // the current kernel index }; typedef struct GPTData GPTData_t; @@ -74,7 +75,8 @@ int GPTNextKernelEntry(GPTData_t *gpt, uint64_t *start_sector, uint64_t *size); * for the start of the kernel partition, and the size parameter contains the * size of the kernel partition in LBA sectors. * - * Returns 0 if successful, 1 if error or no more sectors. */ + * Returns 0 if successful, else + * GPT_ERROR_NO_VALID_KERNEL, no avaliable kernel, enters recovery mode */ int GPTUpdateKernelEntry(GPTData_t *gpt, uint32_t update_type); /* Updates the kernel entry with the specified index, using the specified type @@ -85,4 +87,4 @@ int GPTUpdateKernelEntry(GPTData_t *gpt, uint32_t update_type); * * Returns 0 if successful, 1 if error. */ -#endif // VBOOT_REFERENCE_CGPT_H_ +#endif /* VBOOT_REFERENCE_CGPT_H_ */ diff --git a/cgptlib/tests/cgpt_test.c b/cgptlib/tests/cgpt_test.c new file mode 100644 index 0000000000..b5b26e70f9 --- /dev/null +++ b/cgptlib/tests/cgpt_test.c @@ -0,0 +1,136 @@ +/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cgpt.h" +#include "cgpt_test.h" + +#define TEST_CASE(func) #func, func +typedef int (*test_func)(void); + +/* Tests if header CRC in two copies are calculated. */ +int HeaderCrcTest() { + return TEST_FAIL; +} + +/* Tests if myLBA field is checked (1 for primary, last for secondary). */ +int MyLbaTest() { + return TEST_FAIL; +} + +/* Tests if SizeOfPartitionEntry is checked. SizeOfPartitionEntry must be + * between 128 and 512, and a multiple of 8. */ +int SizeOfPartitionEntryTest() { + return TEST_FAIL; +} + +/* Tests if NumberOfPartitionEntries is checes. NumberOfPartitionEntries must + * be between 32 and 512, and SizeOfPartitionEntry * NumberOfPartitionEntries + * must be 16384. */ +int NumberOfPartitionEntriesTest() { + return TEST_FAIL; +} + +/* Tests if PartitionEntryLBA in primary/secondary headers is checked. */ +int PartitionEntryLbaTest() { + return TEST_FAIL; +} + +/* Tests if FirstUsableLBA and LastUsableLBA are checked. + * FirstUsableLBA must be after the end of the primary GPT table array. + * LastUsableLBA must be before the start of the secondary GPT table array. + * FirstUsableLBA <= LastUsableLBA. */ +int FirstUsableLbaAndLastUsableLbaTest() { + return TEST_FAIL; +} + +/* Tests if GPTInit() handles non-identical partition entries well. + * Two copies of partition table entries must be identical. If not, we trust the + * primary table entries, and mark secondary as modified (see Caller's write- + * back order below). */ +int IdenticalEntriesTest() { + return TEST_FAIL; +} + +/* Tests if GPTInit() handles non-identical headers well. + * Two partition headers must be identical. If not, we trust the primary + * partition header, and mark secondary as modified (see Caller's write-back + * order below). */ +int IdenticalHeaderTest() { + return TEST_FAIL; +} + +/* Tests if PartitionEntryArrayCRC32 is checked. + * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry * + * NumberOfPartitionEntries bytes. + */ +int EntriesCrcTest() { + return TEST_FAIL; +} + +/* Tests if partition geometry is checked. + * All active (non-zero PartitionTypeGUID) partition entries should have: + * entry.StartingLBA >= header.FirstUsableLBA + * entry.EndingLBA <= header.LastUsableLBA + * entry.StartingLBA <= entry.EndingLBA + */ +int ValidEntryTest() { + return TEST_FAIL; +} + +/* Tests if overlapped partition tables can be detected. */ +int NoOverlappedPartitionTest() { + return TEST_FAIL; +} + +/* Tests if GPTNextKernelEntry() can survive in different corrupt header/entries + * combinations, like: + * primary GPT header - valid + * primary partition table - invalid + * secondary partition table - valid + * secondary GPT header - invalid + */ +int CorruptCombinationTest() { + return TEST_FAIL; +} + +int main(int argc, char *argv[]) { + int i; + struct { + char *name; + test_func fp; + int retval; + } test_cases[] = { + { TEST_CASE(HeaderCrcTest), }, + { TEST_CASE(MyLbaTest), }, + { TEST_CASE(SizeOfPartitionEntryTest), }, + { TEST_CASE(NumberOfPartitionEntriesTest), }, + { TEST_CASE(PartitionEntryLbaTest), }, + { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), }, + { TEST_CASE(IdenticalEntriesTest), }, + { TEST_CASE(IdenticalHeaderTest), }, + { TEST_CASE(EntriesCrcTest), }, + { TEST_CASE(ValidEntryTest), }, + { TEST_CASE(NoOverlappedPartitionTest), }, + { TEST_CASE(CorruptCombinationTest), }, + }; + + for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { + printf("Running %s() ...\n", test_cases[i].name); + test_cases[i].retval = test_cases[i].fp(); + if (test_cases[i].retval) + printf(COL_RED "[ERROR]" COL_STOP " %s()\n\n", test_cases[i].name); + else + printf(COL_GREEN "[PASS]" COL_STOP " %s()\n\n", test_cases[i].name); + } + + printf("\n--------------------------------------------------\n"); + printf("The following test cases are failed:\n"); + for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { + if (test_cases[i].retval) + printf(" %s()\n", test_cases[i].name); + } + + return 0; +} diff --git a/cgptlib/tests/cgpt_test.h b/cgptlib/tests/cgpt_test.h new file mode 100644 index 0000000000..0dcb637e82 --- /dev/null +++ b/cgptlib/tests/cgpt_test.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef VBOOT_REFERENCE_CGPTLIB_TESTS_CGPT_TEST_H_ +#define VBOOT_REFERENCE_CGPTLIB_TESTS_CGPT_TEST_H_ + +#include + +#define TEST_FAIL -1 + +/* ANSI Color coding sequences. */ +#define COL_GREEN "\e[1;32m" +#define COL_RED "\e[0;31m" +#define COL_STOP "\e[m" + +#define EXPECT(expr) \ + if (!expr) { \ + printf(COL_RED " fail " COL_STOP "in expression %s in %s() line %d\n",\ + #expr, __FUNCTION__, __LINE__); \ + return TEST_FAIL; \ + } + +#endif /* VBOOT_REFERENCE_CGPTLIB_TESTS_CGPT_TEST_H_ */