summaryrefslogtreecommitdiff
path: root/tests/vboot_kernel_tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/vboot_kernel_tests.c')
-rw-r--r--tests/vboot_kernel_tests.c165
1 files changed, 153 insertions, 12 deletions
diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c
index 935dd869..3712d0d3 100644
--- a/tests/vboot_kernel_tests.c
+++ b/tests/vboot_kernel_tests.c
@@ -11,6 +11,7 @@
#include <string.h>
#include "cgptlib.h"
+#include "cgptlib_internal.h"
#include "gbb_header.h"
#include "gpt.h"
#include "host_common.h"
@@ -24,6 +25,9 @@
#define LOGCALL(fmt, args...) sprintf(call_log + strlen(call_log), fmt, ##args)
#define TEST_CALLS(expect_log) TEST_STR_EQ(call_log, expect_log, " calls")
+#define MOCK_SECTOR_SIZE 512
+#define MOCK_SECTOR_COUNT 1024
+
/* Mock kernel partition */
struct mock_part {
uint32_t start;
@@ -57,6 +61,43 @@ static LoadKernelParams lkp;
static VbKeyBlockHeader kbh;
static VbKernelPreambleHeader kph;
static VbCommonParams cparams;
+static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT];
+static GptHeader *mock_gpt_primary =
+ (GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1];
+static GptHeader *mock_gpt_secondary =
+ (GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * (MOCK_SECTOR_COUNT - 1)];
+
+
+/**
+ * Prepare a valid GPT header that will pass CheckHeader() tests
+ */
+static void SetupGptHeader(GptHeader *h, int is_secondary)
+{
+ Memset(h, '\0', MOCK_SECTOR_SIZE);
+
+ /* "EFI PART" */
+ memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE);
+ h->revision = GPT_HEADER_REVISION;
+ h->size = MIN_SIZE_OF_HEADER;
+
+ /* 16KB: 128 entries of 128 bytes */
+ h->size_of_entry = sizeof(GptEntry);
+ h->number_of_entries = TOTAL_ENTRIES_SIZE / h->size_of_entry;
+
+ /* Set LBA pointers for primary or secondary header */
+ if (is_secondary) {
+ h->my_lba = MOCK_SECTOR_COUNT - GPT_HEADER_SECTORS;
+ h->entries_lba = h->my_lba - GPT_ENTRIES_SECTORS;
+ } else {
+ h->my_lba = GPT_PMBR_SECTORS;
+ h->entries_lba = h->my_lba + 1;
+ }
+
+ h->first_usable_lba = 2 + GPT_ENTRIES_SECTORS;
+ h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - GPT_ENTRIES_SECTORS;
+
+ h->header_crc32 = HeaderCrc(h);
+}
static void ResetCallLog(void)
{
@@ -70,6 +111,10 @@ static void ResetMocks(void)
{
ResetCallLog();
+ memset(&mock_disk, 0, sizeof(mock_disk));
+ SetupGptHeader(mock_gpt_primary, 0);
+ SetupGptHeader(mock_gpt_secondary, 1);
+
disk_read_to_fail = -1;
disk_write_to_fail = -1;
@@ -137,16 +182,9 @@ VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
if ((int)lba_start == disk_read_to_fail)
return VBERROR_SIMULATED;
- /* Keep valgrind happy */
- Memset(buffer, '\0', lba_count);
- /* Fix up entries_lba in GPT header. */
- if (lba_start == 1 || lba_start == 1024 - 1) {
- GptHeader* h = (GptHeader*)buffer;
- if (lba_start == 1)
- h->entries_lba = 1 + 1;
- else
- h->entries_lba = (1024 - 1 - 32);
- }
+ memcpy(buffer, &mock_disk[lba_start * MOCK_SECTOR_SIZE],
+ lba_count * MOCK_SECTOR_SIZE);
+
return VBERROR_SUCCESS;
}
@@ -158,6 +196,9 @@ VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
if ((int)lba_start == disk_write_to_fail)
return VBERROR_SIMULATED;
+ memcpy(&mock_disk[lba_start * MOCK_SECTOR_SIZE], buffer,
+ lba_count * MOCK_SECTOR_SIZE);
+
return VBERROR_SUCCESS;
}
@@ -246,8 +287,9 @@ static void ReadWriteGptTest(void)
GptData g;
GptHeader *h;
- g.sector_bytes = 512;
- g.drive_sectors = 1024;
+ g.sector_bytes = MOCK_SECTOR_SIZE;
+ g.drive_sectors = MOCK_SECTOR_COUNT;
+ g.valid_headers = g.valid_entries = MASK_BOTH;
ResetMocks();
TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead");
@@ -264,6 +306,105 @@ static void ReadWriteGptTest(void)
TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree");
TEST_CALLS("");
+ /*
+ * Invalidate primary GPT header,
+ * check that AllocAndReadGptData still succeeds
+ */
+ ResetMocks();
+ Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
+ TEST_EQ(AllocAndReadGptData(handle, &g), 0,
+ "AllocAndRead primary invalid");
+ TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 1,
+ "Primary header is invalid");
+ TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 0,
+ "Secondary header is valid");
+ TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+ "VbExDiskRead(h, 1023, 1)\n"
+ "VbExDiskRead(h, 991, 32)\n");
+ WriteAndFreeGptData(handle, &g);
+
+ /*
+ * Invalidate secondary GPT header,
+ * check that AllocAndReadGptData still succeeds
+ */
+ ResetMocks();
+ Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
+ TEST_EQ(AllocAndReadGptData(handle, &g), 0,
+ "AllocAndRead secondary invalid");
+ TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 0,
+ "Primary header is valid");
+ TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 1,
+ "Secondary header is invalid");
+ TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+ "VbExDiskRead(h, 2, 32)\n"
+ "VbExDiskRead(h, 1023, 1)\n");
+ WriteAndFreeGptData(handle, &g);
+
+ /*
+ * Invalidate primary AND secondary GPT header,
+ * check that AllocAndReadGptData fails.
+ */
+ ResetMocks();
+ Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
+ Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
+ TEST_EQ(AllocAndReadGptData(handle, &g), 1,
+ "AllocAndRead primary and secondary invalid");
+ TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 1,
+ "Primary header is invalid");
+ TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 1,
+ "Secondary header is invalid");
+ TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+ "VbExDiskRead(h, 1023, 1)\n");
+ WriteAndFreeGptData(handle, &g);
+
+ /*
+ * Invalidate primary GPT header and check that it is
+ * repaired by GptRepair().
+ *
+ * This would normally be called by LoadKernel()->GptInit()
+ * but this callback is mocked in these tests.
+ */
+ ResetMocks();
+ Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
+ TEST_EQ(AllocAndReadGptData(handle, &g), 0,
+ "Fix Primary GPT: AllocAndRead");
+ /* Call GptRepair() with input indicating secondary GPT is valid */
+ g.valid_headers = g.valid_entries = MASK_SECONDARY;
+ GptRepair(&g);
+ TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
+ "Fix Primary GPT: WriteAndFreeGptData");
+ TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+ "VbExDiskRead(h, 1023, 1)\n"
+ "VbExDiskRead(h, 991, 32)\n"
+ "VbExDiskWrite(h, 1, 1)\n"
+ "VbExDiskWrite(h, 2, 32)\n");
+ TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 0,
+ "Fix Primary GPT: Primary header is valid");
+
+ /*
+ * Invalidate secondary GPT header and check that it can be
+ * repaired by GptRepair().
+ *
+ * This would normally be called by LoadKernel()->GptInit()
+ * but this callback is mocked in these tests.
+ */
+ ResetMocks();
+ Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
+ TEST_EQ(AllocAndReadGptData(handle, &g), 0,
+ "Fix Secondary GPT: AllocAndRead");
+ /* Call GptRepair() with input indicating primary GPT is valid */
+ g.valid_headers = g.valid_entries = MASK_PRIMARY;
+ GptRepair(&g);
+ TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
+ "Fix Secondary GPT: WriteAndFreeGptData");
+ TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+ "VbExDiskRead(h, 2, 32)\n"
+ "VbExDiskRead(h, 1023, 1)\n"
+ "VbExDiskWrite(h, 1023, 1)\n"
+ "VbExDiskWrite(h, 991, 32)\n");
+ TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 0,
+ "Fix Secondary GPT: Secondary header is valid");
+
/* Data which is changed is written */
ResetMocks();
AllocAndReadGptData(handle, &g);