diff options
author | Joel Kitching <kitching@google.com> | 2021-07-20 07:18:42 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-07-21 06:49:54 +0000 |
commit | e355c9ea7e30775dc9698646339a4d9fe5fe3ee1 (patch) | |
tree | a0ddc6809fc90f14a9971fd587bb76c4eda7079b | |
parent | 2d3af1227d6c74733f4e16da424ffaabdfcd23d4 (diff) | |
download | vboot-e355c9ea7e30775dc9698646339a4d9fe5fe3ee1.tar.gz |
vboot/vboot_kernel: split gpt tests out of vboot_kernel_tests
These don't really belong together. We can get two cleaner test
files by splitting them apart.
This CL is part of a series to merge vboot1 and vboot2.0
kernel verification code; see b/181739551.
BUG=b:181739551, b:172337800, b:124141368
TEST=make clean && make runtests
BRANCH=none
Signed-off-by: Joel Kitching <kitching@google.com>
Change-Id: Idaa4c36214cc98bffdc50bdb5c071673829250ee
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3039164
Tested-by: Joel Kitching <kitching@chromium.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Commit-Queue: Joel Kitching <kitching@chromium.org>
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | tests/gpt_misc_tests.c | 378 | ||||
-rw-r--r-- | tests/vboot_kernel_tests.c | 344 |
3 files changed, 392 insertions, 332 deletions
@@ -710,6 +710,7 @@ TEST_OBJS += ${TESTLIB_OBJS} TEST_NAMES = \ tests/cgptlib_test \ tests/chromeos_config_tests \ + tests/gpt_misc_tests \ tests/sha_benchmark \ tests/subprocess_tests \ tests/vboot_api_kernel4_tests \ @@ -1266,6 +1267,7 @@ runtestscripts: install_for_test genfuzztestcases .PHONY: runmisctests runmisctests: install_for_test + ${RUNTEST} ${BUILD_RUN}/tests/gpt_misc_tests ${RUNTEST} ${BUILD_RUN}/tests/subprocess_tests ifeq (${MOCK_TPM}${TPM2_MODE},) # tlcl_tests only works when MOCK_TPM is disabled diff --git a/tests/gpt_misc_tests.c b/tests/gpt_misc_tests.c new file mode 100644 index 00000000..e0a8d56e --- /dev/null +++ b/tests/gpt_misc_tests.c @@ -0,0 +1,378 @@ +/* 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. + * + * Tests for vboot_kernel.c + */ + +#include "2api.h" +#include "cgptlib.h" +#include "cgptlib_internal.h" +#include "gpt.h" +#include "test_common.h" + +#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") + +/* Assumes 512-byte disk sectors */ +#define MOCK_SECTOR_SIZE 512 +#define MOCK_SECTOR_COUNT 1024 + +/* Mock kernel partition */ +struct mock_part { + uint32_t start; + uint32_t size; +}; + +/* Mock data */ +static char call_log[4096]; +static int disk_read_to_fail; +static int disk_write_to_fail; + +static VbExDiskHandle_t handle; +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 = MAX_NUMBER_OF_ENTRIES; + + /* 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 - CalculateEntriesSectors(h, + MOCK_SECTOR_SIZE); + } else { + h->my_lba = GPT_PMBR_SECTORS; + h->entries_lba = h->my_lba + 1; + } + + h->first_usable_lba = 2 + CalculateEntriesSectors(h, MOCK_SECTOR_SIZE); + h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - CalculateEntriesSectors(h, + MOCK_SECTOR_SIZE); + + h->header_crc32 = HeaderCrc(h); +} + +static void ResetCallLog(void) +{ + *call_log = 0; +} + +/** + * Reset mock data (for use before each test) + */ +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; +} + +/* Mocks */ + +vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start, + uint64_t lba_count, void *buffer) +{ + LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count); + + if ((int)lba_start == disk_read_to_fail) + return VB2_ERROR_MOCK; + + memcpy(buffer, &mock_disk[lba_start * MOCK_SECTOR_SIZE], + lba_count * MOCK_SECTOR_SIZE); + + return VB2_SUCCESS; +} + +vb2_error_t VbExDiskWrite(VbExDiskHandle_t h, uint64_t lba_start, + uint64_t lba_count, const void *buffer) +{ + LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count); + + if ((int)lba_start == disk_write_to_fail) + return VB2_ERROR_MOCK; + + memcpy(&mock_disk[lba_start * MOCK_SECTOR_SIZE], buffer, + lba_count * MOCK_SECTOR_SIZE); + + return VB2_SUCCESS; +} + +/** + * Test reading/writing GPT + */ +static void ReadWriteGptTest(void) +{ + GptData g; + GptHeader *h; + + g.sector_bytes = MOCK_SECTOR_SIZE; + g.streaming_drive_sectors = g.gpt_drive_sectors = MOCK_SECTOR_COUNT; + g.valid_headers = g.valid_entries = MASK_BOTH; + + ResetMocks(); + TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead"); + TEST_CALLS("VbExDiskRead(h, 1, 1)\n" + "VbExDiskRead(h, 2, 32)\n" + "VbExDiskRead(h, 1023, 1)\n" + "VbExDiskRead(h, 991, 32)\n"); + ResetCallLog(); + /* + * Valgrind complains about access to uninitialized memory here, so + * zero the primary header before each test. + */ + memset(g.primary_header, '\0', g.sector_bytes); + 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.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 1, "Primary header is invalid"); + TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 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.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 0, "Primary header is valid"); + TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 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.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 1, "Primary header is invalid"); + TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 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.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 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.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 0, "Fix Secondary GPT: Secondary header is valid"); + + /* Data which is changed is written */ + ResetMocks(); + AllocAndReadGptData(handle, &g); + g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1; + ResetCallLog(); + memset(g.primary_header, '\0', g.sector_bytes); + h = (GptHeader*)g.primary_header; + h->entries_lba = 2; + h->number_of_entries = MAX_NUMBER_OF_ENTRIES; + h->size_of_entry = sizeof(GptEntry); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); + TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" + "VbExDiskWrite(h, 2, 32)\n"); + + /* Data which is changed is written */ + ResetMocks(); + AllocAndReadGptData(handle, &g); + g.modified = -1; + ResetCallLog(); + memset(g.primary_header, '\0', g.sector_bytes); + h = (GptHeader*)g.primary_header; + h->entries_lba = 2; + h->number_of_entries = MAX_NUMBER_OF_ENTRIES; + h->size_of_entry = sizeof(GptEntry); + h = (GptHeader*)g.secondary_header; + h->entries_lba = 991; + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all"); + TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" + "VbExDiskWrite(h, 2, 32)\n" + "VbExDiskWrite(h, 1023, 1)\n" + "VbExDiskWrite(h, 991, 32)\n"); + + /* If legacy signature, don't modify GPT header/entries 1 */ + ResetMocks(); + AllocAndReadGptData(handle, &g); + h = (GptHeader *)g.primary_header; + memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE); + g.modified = -1; + ResetCallLog(); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all"); + TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n" + "VbExDiskWrite(h, 991, 32)\n"); + + /* Error reading */ + ResetMocks(); + disk_read_to_fail = 1; + TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + g.valid_headers = g.valid_entries = MASK_SECONDARY; + GptRepair(&g); + ResetCallLog(); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); + TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" + "VbExDiskWrite(h, 2, 32)\n"); + + ResetMocks(); + disk_read_to_fail = 2; + TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + g.valid_headers = MASK_BOTH; + g.valid_entries = MASK_SECONDARY; + GptRepair(&g); + ResetCallLog(); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); + TEST_CALLS("VbExDiskWrite(h, 2, 32)\n"); + + ResetMocks(); + disk_read_to_fail = 991; + TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + g.valid_headers = MASK_BOTH; + g.valid_entries = MASK_PRIMARY; + GptRepair(&g); + ResetCallLog(); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2"); + TEST_CALLS("VbExDiskWrite(h, 991, 32)\n"); + + ResetMocks(); + disk_read_to_fail = 1023; + TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + g.valid_headers = g.valid_entries = MASK_PRIMARY; + GptRepair(&g); + ResetCallLog(); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2"); + TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n" + "VbExDiskWrite(h, 991, 32)\n"); + + /* Error writing */ + ResetMocks(); + disk_write_to_fail = 1; + AllocAndReadGptData(handle, &g); + g.modified = -1; + memset(g.primary_header, '\0', g.sector_bytes); + TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); + + ResetMocks(); + disk_write_to_fail = 2; + AllocAndReadGptData(handle, &g); + g.modified = -1; + memset(g.primary_header, '\0', g.sector_bytes); + h = (GptHeader*)g.primary_header; + h->entries_lba = 2; + TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); + + ResetMocks(); + disk_write_to_fail = 991; + AllocAndReadGptData(handle, &g); + g.modified = -1; + memset(g.primary_header, '\0', g.sector_bytes); + TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); + + ResetMocks(); + disk_write_to_fail = 1023; + AllocAndReadGptData(handle, &g); + g.modified = -1; + memset(g.primary_header, '\0', g.sector_bytes); + TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); + +} + +int main(void) +{ + ReadWriteGptTest(); + + return gTestSuccess ? 0 : 255; +} diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c index 486602c0..944be0aa 100644 --- a/tests/vboot_kernel_tests.c +++ b/tests/vboot_kernel_tests.c @@ -11,23 +11,12 @@ #include "2nvstorage.h" #include "2secdata.h" #include "2secdata_struct.h" -#include "2sha.h" -#include "2sysincludes.h" #include "cgptlib.h" #include "cgptlib_internal.h" -#include "crc32.h" #include "gpt.h" -#include "host_common.h" #include "load_kernel_fw.h" #include "test_common.h" #include "vboot_api.h" -#include "vboot_kernel.h" - -#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 { @@ -41,10 +30,8 @@ static struct mock_part mock_parts[MOCK_PART_COUNT]; static int mock_part_next; /* Mock data */ -static char call_log[4096]; static uint8_t kernel_buffer[80000]; static int disk_read_to_fail; -static int disk_write_to_fail; static int gpt_init_fail; static int keyblock_verify_fail; /* 0=ok, 1=sig, 2=hash */ static int preamble_verify_fail; @@ -53,17 +40,11 @@ static int unpack_key_fail; static int gpt_flag_external; static struct vb2_gbb_header gbb; -static VbExDiskHandle_t handle; static VbSelectAndLoadKernelParams lkp; static VbDiskInfo disk_info; static struct vb2_keyblock kbh; static struct vb2_kernel_preamble kph; static struct vb2_secdata_fwmp *fwmp; -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)]; static uint8_t mock_digest[VB2_SHA256_DIGEST_SIZE] = {12, 34, 56, 78}; static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] __attribute__((aligned(VB2_WORKBUF_ALIGN))); @@ -72,56 +53,11 @@ static struct vb2_shared_data *sd; static struct vb2_packed_key mock_key; /** - * 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 = MAX_NUMBER_OF_ENTRIES; - - /* 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 - CalculateEntriesSectors(h, - MOCK_SECTOR_SIZE); - } else { - h->my_lba = GPT_PMBR_SECTORS; - h->entries_lba = h->my_lba + 1; - } - - h->first_usable_lba = 2 + CalculateEntriesSectors(h, MOCK_SECTOR_SIZE); - h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - CalculateEntriesSectors(h, - MOCK_SECTOR_SIZE); - - h->header_crc32 = HeaderCrc(h); -} - -static void ResetCallLog(void) -{ - *call_log = 0; -} - -/** * Reset mock data (for use before each test) */ 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; gpt_init_fail = 0; keyblock_verify_fail = 0; @@ -219,29 +155,15 @@ vb2_error_t vb2_gbb_read_recovery_key(struct vb2_context *c, vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start, uint64_t lba_count, void *buffer) { - LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count); - if ((int)lba_start == disk_read_to_fail) return VB2_ERROR_MOCK; - memcpy(buffer, &mock_disk[lba_start * MOCK_SECTOR_SIZE], - lba_count * MOCK_SECTOR_SIZE); - return VB2_SUCCESS; } -vb2_error_t VbExDiskWrite(VbExDiskHandle_t h, uint64_t lba_start, - uint64_t lba_count, const void *buffer) +int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) { - LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count); - - if ((int)lba_start == disk_write_to_fail) - return VB2_ERROR_MOCK; - - memcpy(&mock_disk[lba_start * MOCK_SECTOR_SIZE], buffer, - lba_count * MOCK_SECTOR_SIZE); - - return VB2_SUCCESS; + return GPT_SUCCESS; } int GptInit(GptData *gpt) @@ -266,6 +188,16 @@ int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size) return GPT_SUCCESS; } +int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type) +{ + return GPT_SUCCESS; +} + +int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) +{ + return GPT_SUCCESS; +} + void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest) { static char fake_guid[] = "FakeGuid"; @@ -343,257 +275,6 @@ void vb2api_fail(struct vb2_context *c, uint8_t reason, uint8_t subcode) TEST_TRUE(0, " called vb2api_fail()"); } -/** - * Test reading/writing GPT - */ -static void ReadWriteGptTest(void) -{ - GptData g; - GptHeader *h; - - g.sector_bytes = MOCK_SECTOR_SIZE; - g.streaming_drive_sectors = g.gpt_drive_sectors = MOCK_SECTOR_COUNT; - g.valid_headers = g.valid_entries = MASK_BOTH; - - ResetMocks(); - TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead"); - TEST_CALLS("VbExDiskRead(h, 1, 1)\n" - "VbExDiskRead(h, 2, 32)\n" - "VbExDiskRead(h, 1023, 1)\n" - "VbExDiskRead(h, 991, 32)\n"); - ResetCallLog(); - /* - * Valgrind complains about access to uninitialized memory here, so - * zero the primary header before each test. - */ - memset(g.primary_header, '\0', g.sector_bytes); - 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.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 1, "Primary header is invalid"); - TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 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.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 0, "Primary header is valid"); - TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 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.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 1, "Primary header is invalid"); - TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 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.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 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.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 0, "Fix Secondary GPT: Secondary header is valid"); - - /* Data which is changed is written */ - ResetMocks(); - AllocAndReadGptData(handle, &g); - g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1; - ResetCallLog(); - memset(g.primary_header, '\0', g.sector_bytes); - h = (GptHeader*)g.primary_header; - h->entries_lba = 2; - h->number_of_entries = MAX_NUMBER_OF_ENTRIES; - h->size_of_entry = sizeof(GptEntry); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); - TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" - "VbExDiskWrite(h, 2, 32)\n"); - - /* Data which is changed is written */ - ResetMocks(); - AllocAndReadGptData(handle, &g); - g.modified = -1; - ResetCallLog(); - memset(g.primary_header, '\0', g.sector_bytes); - h = (GptHeader*)g.primary_header; - h->entries_lba = 2; - h->number_of_entries = MAX_NUMBER_OF_ENTRIES; - h->size_of_entry = sizeof(GptEntry); - h = (GptHeader*)g.secondary_header; - h->entries_lba = 991; - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all"); - TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" - "VbExDiskWrite(h, 2, 32)\n" - "VbExDiskWrite(h, 1023, 1)\n" - "VbExDiskWrite(h, 991, 32)\n"); - - /* If legacy signature, don't modify GPT header/entries 1 */ - ResetMocks(); - AllocAndReadGptData(handle, &g); - h = (GptHeader *)g.primary_header; - memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE); - g.modified = -1; - ResetCallLog(); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all"); - TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n" - "VbExDiskWrite(h, 991, 32)\n"); - - /* Error reading */ - ResetMocks(); - disk_read_to_fail = 1; - TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); - g.valid_headers = g.valid_entries = MASK_SECONDARY; - GptRepair(&g); - ResetCallLog(); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); - TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" - "VbExDiskWrite(h, 2, 32)\n"); - - ResetMocks(); - disk_read_to_fail = 2; - TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); - g.valid_headers = MASK_BOTH; - g.valid_entries = MASK_SECONDARY; - GptRepair(&g); - ResetCallLog(); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); - TEST_CALLS("VbExDiskWrite(h, 2, 32)\n"); - - ResetMocks(); - disk_read_to_fail = 991; - TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); - g.valid_headers = MASK_BOTH; - g.valid_entries = MASK_PRIMARY; - GptRepair(&g); - ResetCallLog(); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2"); - TEST_CALLS("VbExDiskWrite(h, 991, 32)\n"); - - ResetMocks(); - disk_read_to_fail = 1023; - TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); - g.valid_headers = g.valid_entries = MASK_PRIMARY; - GptRepair(&g); - ResetCallLog(); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2"); - TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n" - "VbExDiskWrite(h, 991, 32)\n"); - - /* Error writing */ - ResetMocks(); - disk_write_to_fail = 1; - AllocAndReadGptData(handle, &g); - g.modified = -1; - memset(g.primary_header, '\0', g.sector_bytes); - TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); - - ResetMocks(); - disk_write_to_fail = 2; - AllocAndReadGptData(handle, &g); - g.modified = -1; - memset(g.primary_header, '\0', g.sector_bytes); - h = (GptHeader*)g.primary_header; - h->entries_lba = 2; - TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); - - ResetMocks(); - disk_write_to_fail = 991; - AllocAndReadGptData(handle, &g); - g.modified = -1; - memset(g.primary_header, '\0', g.sector_bytes); - TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); - - ResetMocks(); - disk_write_to_fail = 1023; - AllocAndReadGptData(handle, &g); - g.modified = -1; - memset(g.primary_header, '\0', g.sector_bytes); - TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); - -} - static void TestLoadKernel(int expect_retval, const char *test_name) { TEST_EQ(LoadKernel(ctx, &lkp, &disk_info), expect_retval, test_name); @@ -878,7 +559,6 @@ static void LoadKernelTest(void) int main(void) { - ReadWriteGptTest(); InvalidParamsTest(); LoadKernelTest(); |