summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-01-24 12:25:26 -0800
committerChromeBot <chrome-bot@google.com>2013-01-24 16:46:52 -0800
commit0bda13f5154afc8068e7d2d4563ff20b152f1c87 (patch)
tree268db6481da233a3d219862339d21209b90da033
parente9213a7c133681d6f565adbf218bafa7a3115c22 (diff)
downloadvboot-0bda13f5154afc8068e7d2d4563ff20b152f1c87.tar.gz
Improve coverage of cgptlib.c
BUG=chromium-os:38139 BRANCH=none TEST=make runtests Change-Id: I5719c6b8aa1a23fc65bf38d7096320479152f0ca Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/41955 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--firmware/lib/cgptlib/include/cgptlib.h4
-rw-r--r--firmware/lib/cgptlib/include/cgptlib_internal.h11
-rw-r--r--tests/cgptlib_test.c127
3 files changed, 140 insertions, 2 deletions
diff --git a/firmware/lib/cgptlib/include/cgptlib.h b/firmware/lib/cgptlib/include/cgptlib.h
index b6b27c96..6633733e 100644
--- a/firmware/lib/cgptlib/include/cgptlib.h
+++ b/firmware/lib/cgptlib/include/cgptlib.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2013 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.
*/
@@ -21,6 +21,8 @@ enum {
GPT_ERROR_START_LBA_OVERLAP,
GPT_ERROR_END_LBA_OVERLAP,
GPT_ERROR_DUP_GUID,
+ /* Number of errors */
+ GPT_ERROR_COUNT
};
/* Bit masks for GptData.modified field. */
diff --git a/firmware/lib/cgptlib/include/cgptlib_internal.h b/firmware/lib/cgptlib/include/cgptlib_internal.h
index f899eab0..36e598c2 100644
--- a/firmware/lib/cgptlib/include/cgptlib_internal.h
+++ b/firmware/lib/cgptlib/include/cgptlib_internal.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2013 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.
*/
@@ -89,6 +89,15 @@ uint32_t HeaderCrc(GptHeader* h);
* Returns 0 if entries are valid, 1 if invalid. */
int CheckEntries(GptEntry* entries, GptHeader* h);
+/* Return 0 if the GptHeaders are the same for all fields which don't
+ * differ between the primary and secondary headers - that is, all
+ * fields other than:
+ *
+ * my_lba
+ * alternate_lba
+ * entries_lba */
+int HeaderFieldsSame(GptHeader *h1, GptHeader *h2);
+
/* Check GptData, headers, entries.
*
* If successful, sets gpt->valid_headers and gpt->valid_entries and returns
diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c
index 67ce9fe4..b48543f3 100644
--- a/tests/cgptlib_test.c
+++ b/tests/cgptlib_test.c
@@ -216,6 +216,8 @@ static int TestBuildTestGptData(void)
gpt = GetEmptyGptData();
BuildTestGptData(gpt);
EXPECT(GPT_SUCCESS == GptInit(gpt));
+ gpt->sector_bytes = 0;
+ EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptInit(gpt));
return TEST_OK;
}
@@ -281,6 +283,59 @@ static int HeaderCrcTest(void)
return TEST_OK;
}
+/* Test if header-same comparison works. */
+static int HeaderSameTest(void)
+{
+ GptData *gpt = GetEmptyGptData();
+ GptHeader *h1 = (GptHeader *)gpt->primary_header;
+ GptHeader *h2 = (GptHeader *)gpt->secondary_header;
+ GptHeader h3;
+
+ EXPECT(0 == HeaderFieldsSame(h1, h2));
+
+ Memcpy(&h3, h2, sizeof(h3));
+ h3.signature[0] ^= 0xba;
+ EXPECT(1 == HeaderFieldsSame(h1, &h3));
+
+ Memcpy(&h3, h2, sizeof(h3));
+ h3.revision++;
+ EXPECT(1 == HeaderFieldsSame(h1, &h3));
+
+ Memcpy(&h3, h2, sizeof(h3));
+ h3.size++;
+ EXPECT(1 == HeaderFieldsSame(h1, &h3));
+
+ Memcpy(&h3, h2, sizeof(h3));
+ h3.reserved_zero++;
+ EXPECT(1 == HeaderFieldsSame(h1, &h3));
+
+ Memcpy(&h3, h2, sizeof(h3));
+ h3.first_usable_lba++;
+ EXPECT(1 == HeaderFieldsSame(h1, &h3));
+
+ Memcpy(&h3, h2, sizeof(h3));
+ h3.last_usable_lba++;
+ EXPECT(1 == HeaderFieldsSame(h1, &h3));
+
+ Memcpy(&h3, h2, sizeof(h3));
+ h3.disk_uuid.u.raw[0] ^= 0xba;
+ EXPECT(1 == HeaderFieldsSame(h1, &h3));
+
+ Memcpy(&h3, h2, sizeof(h3));
+ h3.number_of_entries++;
+ EXPECT(1 == HeaderFieldsSame(h1, &h3));
+
+ Memcpy(&h3, h2, sizeof(h3));
+ h3.size_of_entry++;
+ EXPECT(1 == HeaderFieldsSame(h1, &h3));
+
+ Memcpy(&h3, h2, sizeof(h3));
+ h3.entries_crc32++;
+ EXPECT(1 == HeaderFieldsSame(h1, &h3));
+
+ return TEST_OK;
+}
+
/* Test if signature ("EFI PART") is checked. */
static int SignatureTest(void)
{
@@ -289,6 +344,8 @@ static int SignatureTest(void)
GptHeader *h2 = (GptHeader *)gpt->secondary_header;
int i;
+ EXPECT(1 == CheckHeader(NULL, 0, gpt->drive_sectors));
+
for (i = 0; i < 8; ++i) {
BuildTestGptData(gpt);
h1->signature[i] ^= 0xff;
@@ -734,6 +791,8 @@ static int SanityCheckTest(void)
{
GptData *gpt = GetEmptyGptData();
GptHeader *h1 = (GptHeader *)gpt->primary_header;
+ GptEntry *e1 = (GptEntry *)gpt->primary_entries;
+ uint8_t *tempptr;
/* Unmodified test data is completely sane */
BuildTestGptData(gpt);
@@ -747,6 +806,11 @@ static int SanityCheckTest(void)
EXPECT(MASK_BOTH == gpt->valid_entries);
EXPECT(0 == gpt->modified);
+ /* Invalid sector size should fail */
+ BuildTestGptData(gpt);
+ gpt->sector_bytes = 1024;
+ EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptSanityCheck(gpt));
+
/* Modify headers */
BuildTestGptData(gpt);
gpt->primary_header[0]++;
@@ -835,6 +899,22 @@ static int SanityCheckTest(void)
EXPECT(MASK_BOTH == gpt->valid_entries);
EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
+ /*
+ * Modify entries and recompute CRCs, then make both primary and
+ * secondary entry pointers use the secondary data. The primary
+ * header will have the wrong entries CRC, so we should fall back
+ * to the secondary header.
+ */
+ BuildTestGptData(gpt);
+ e1->starting_lba++;
+ RefreshCrc32(gpt);
+ tempptr = gpt->primary_entries;
+ gpt->primary_entries = gpt->secondary_entries;
+ EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
+ EXPECT(MASK_SECONDARY == gpt->valid_headers);
+ EXPECT(MASK_BOTH == gpt->valid_entries);
+ gpt->primary_entries = tempptr;
+
/* Modify both header and entries */
BuildTestGptData(gpt);
gpt->primary_header[0]++;
@@ -1167,6 +1247,15 @@ static int GptUpdateTest(void)
EXPECT(0 == GetEntryPriority(e + KERNEL_X));
EXPECT(0 == GetEntryTries(e + KERNEL_X));
+ /* Can't update if entry isn't a kernel, or there isn't an entry */
+ Memcpy(&e[KERNEL_X].type, &guid_rootfs, sizeof(guid_rootfs));
+ EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
+ GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
+ gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
+ EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
+ GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
+
+
return TEST_OK;
}
@@ -1247,6 +1336,41 @@ static int DuplicateUniqueGuidTest(void)
return TEST_OK;
}
+/* Test getting the current kernel GUID */
+static int GetKernelGuidTest(void)
+{
+ GptData *gpt = GetEmptyGptData();
+ GptEntry *e = (GptEntry *)gpt->primary_entries;
+ Guid g;
+
+ BuildTestGptData(gpt);
+ gpt->current_kernel = 0;
+ GetCurrentKernelUniqueGuid(gpt, &g);
+ EXPECT(!Memcmp(&g, &e[0].unique, sizeof(Guid)));
+ gpt->current_kernel = 1;
+ GetCurrentKernelUniqueGuid(gpt, &g);
+ EXPECT(!Memcmp(&g, &e[1].unique, sizeof(Guid)));
+
+ return TEST_OK;
+}
+
+/* Test getting GPT error text strings */
+static int ErrorTextTest(void)
+{
+ int i;
+
+ /* Known errors are not unknown */
+ for (i = 0; i < GPT_ERROR_COUNT; i++) {
+ EXPECT(GptErrorText(i));
+ EXPECT(strcmp(GptErrorText(i), "Unknown"));
+ }
+
+ /* But other error values are */
+ EXPECT(!strcmp(GptErrorText(GPT_ERROR_COUNT), "Unknown"));
+
+ return TEST_OK;
+}
+
/* disable MSVC warnings on unused arguments */
__pragma(warning (disable: 4100))
@@ -1263,6 +1387,7 @@ int main(int argc, char *argv[])
{ TEST_CASE(TestBuildTestGptData), },
{ TEST_CASE(ParameterTests), },
{ TEST_CASE(HeaderCrcTest), },
+ { TEST_CASE(HeaderSameTest), },
{ TEST_CASE(SignatureTest), },
{ TEST_CASE(RevisionTest), },
{ TEST_CASE(SizeTest), },
@@ -1286,6 +1411,8 @@ int main(int argc, char *argv[])
{ TEST_CASE(UpdateInvalidKernelTypeTest), },
{ TEST_CASE(DuplicateUniqueGuidTest), },
{ TEST_CASE(TestCrc32TestVectors), },
+ { TEST_CASE(GetKernelGuidTest), },
+ { TEST_CASE(ErrorTextTest), },
};
for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {