summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/lib/vboot_api_kernel.c9
-rw-r--r--tests/Makefile3
-rw-r--r--tests/vboot_api_kernel_tests.c320
3 files changed, 329 insertions, 3 deletions
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 8ed22cbf..bcb3d232 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -75,7 +75,9 @@ uint32_t VbTryLoadKernel(VbCommonParams* cparams, LoadKernelParams* p,
if (512 != disk_info[i].bytes_per_lba || /* cgptlib restriction */
32 > disk_info[i].lba_count || /* ditto */
get_info_flags != disk_info[i].flags) { /* got only what we asked for */
- VBDEBUG((" skipping - bogus parameters\n"));
+ VBDEBUG((" skipping: bytes_per_lba=%Ld lba_count=%Ld flags=0x%x\n",
+ disk_info[i].bytes_per_lba, disk_info[i].lba_count,
+ disk_info[i].flags));
continue;
}
p->disk_handle = disk_info[i].handle;
@@ -92,8 +94,11 @@ uint32_t VbTryLoadKernel(VbCommonParams* cparams, LoadKernelParams* p,
}
/* If we didn't succeed, don't return a disk handle */
- if (VBERROR_SUCCESS != retval)
+ if (VBERROR_SUCCESS != retval) {
+ VbSetRecoveryRequest(VBNV_RECOVERY_RW_NO_DISK);
+ retval = VBERROR_NO_DISK_FOUND;
p->disk_handle = NULL;
+ }
VbExDiskFreeInfo(disk_info, p->disk_handle);
diff --git a/tests/Makefile b/tests/Makefile
index 20c19dd4..9fcb5c76 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -29,7 +29,8 @@ TEST_NAMES = cgptlib_test \
vboot_firmware_tests \
vboot_nvstorage_test \
vboot_api_devmode_tests \
- vboot_audio_tests
+ vboot_audio_tests \
+ vboot_api_kernel_tests
TEST_BINS = $(addprefix ${BUILD_ROOT}/,$(TEST_NAMES))
diff --git a/tests/vboot_api_kernel_tests.c b/tests/vboot_api_kernel_tests.c
new file mode 100644
index 00000000..9fe2991d
--- /dev/null
+++ b/tests/vboot_api_kernel_tests.c
@@ -0,0 +1,320 @@
+/* Copyright (c) 2012 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 VbTryLoadKernel()
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "gbb_header.h"
+#include "load_kernel_fw.h"
+#include "rollback_index.h"
+#include "test_common.h"
+#include "utility.h"
+#include "vboot_api.h"
+
+
+#define MAX_TEST_DISKS 10
+#define DEFAULT_COUNT -1
+
+typedef struct {
+ uint64_t bytes_per_lba;
+ uint64_t lba_count;
+ uint32_t flags;
+ const char *diskname;
+} disk_desc_t;
+
+typedef struct {
+ char *name;
+
+ /* inputs for test case */
+ uint32_t want_flags;
+ VbError_t diskgetinfo_return_val;
+ disk_desc_t disks_to_provide[MAX_TEST_DISKS];
+ int disk_count_to_return;
+ VbError_t loadkernel_return_val[MAX_TEST_DISKS];
+
+ /* outputs from test */
+ uint32_t expected_recovery_request_val;
+ const char *expected_to_find_disk;
+ const char *expected_to_load_disk;
+ uint32_t expected_return_val;
+
+} test_case_t;
+
+/****************************************************************************/
+/* Test cases */
+
+static const char pickme[] = "correct choice";
+#define DONT_CARE ((const char *)42)
+
+test_case_t test[] = {
+
+ {
+ .name = "first removable drive",
+ .want_flags = VB_DISK_FLAG_REMOVABLE,
+ .disks_to_provide = {
+ {512, 10, VB_DISK_FLAG_REMOVABLE, 0 }, /* too small */
+ {2048, 100, VB_DISK_FLAG_REMOVABLE, 0 }, /* wrong LBA */
+ {512, 100, VB_DISK_FLAG_FIXED, 0 }, /* wrong type */
+ {512, 100, 0, 0 }, /* wrong flags */
+ {512, 100, -1, 0 }, /* still wrong flags */
+ {512, 100, VB_DISK_FLAG_REMOVABLE, pickme},
+ {512, 100, VB_DISK_FLAG_REMOVABLE, "holygrail"}, /* already got one */
+ },
+ .disk_count_to_return = DEFAULT_COUNT,
+ .diskgetinfo_return_val = VBERROR_SUCCESS,
+ .loadkernel_return_val = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
+
+ .expected_recovery_request_val = VBNV_RECOVERY_NOT_REQUESTED,
+ .expected_to_find_disk = pickme,
+ .expected_to_load_disk = pickme,
+ .expected_return_val = VBERROR_SUCCESS
+ },
+
+ {
+ .name = "second removable drive",
+ .want_flags = VB_DISK_FLAG_REMOVABLE,
+ .disks_to_provide = {
+ {512, 100, 0, 0 }, /* wrong flags */
+ {512, 100, VB_DISK_FLAG_REMOVABLE, "not yet"},
+ {512, 100, VB_DISK_FLAG_REMOVABLE, pickme},
+ },
+ .disk_count_to_return = DEFAULT_COUNT,
+ .diskgetinfo_return_val = VBERROR_SUCCESS,
+ .loadkernel_return_val = { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, },
+
+ .expected_recovery_request_val = VBNV_RECOVERY_NOT_REQUESTED,
+ .expected_to_find_disk = pickme,
+ .expected_to_load_disk = pickme,
+ .expected_return_val = VBERROR_SUCCESS
+ },
+
+ {
+ .name = "first fixed drive",
+ .want_flags = VB_DISK_FLAG_FIXED,
+ .disks_to_provide = {
+ {512, 10, VB_DISK_FLAG_FIXED, 0 }, /* too small */
+ {2048, 100, VB_DISK_FLAG_FIXED, 0 }, /* wrong LBA */
+ {512, 100, VB_DISK_FLAG_REMOVABLE, 0 }, /* wrong type */
+ {512, 100, 0, 0 }, /* wrong flags */
+ {512, 100, -1, 0 }, /* still wrong flags */
+ {512, 100, VB_DISK_FLAG_REMOVABLE|VB_DISK_FLAG_FIXED, 0 }, /* flags */
+ {512, 100, VB_DISK_FLAG_FIXED, pickme},
+ {512, 100, VB_DISK_FLAG_FIXED, "holygrail"}, /* already got one */
+ },
+ .disk_count_to_return = DEFAULT_COUNT,
+ .diskgetinfo_return_val = VBERROR_SUCCESS,
+ .loadkernel_return_val = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
+
+ .expected_recovery_request_val = VBNV_RECOVERY_NOT_REQUESTED,
+ .expected_to_find_disk = pickme,
+ .expected_to_load_disk = pickme,
+ .expected_return_val = VBERROR_SUCCESS
+ },
+
+ {
+ .name = "no drives at all",
+ .want_flags = VB_DISK_FLAG_FIXED,
+ .disks_to_provide = {
+ },
+ .disk_count_to_return = DEFAULT_COUNT,
+ .diskgetinfo_return_val = VBERROR_SUCCESS,
+ .loadkernel_return_val = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
+
+ .expected_recovery_request_val = VBNV_RECOVERY_RW_NO_DISK,
+ .expected_to_find_disk = 0,
+ .expected_to_load_disk = 0,
+ .expected_return_val = VBERROR_NO_DISK_FOUND
+ },
+
+ {
+ .name = "no valid drives",
+ .want_flags = VB_DISK_FLAG_FIXED,
+ .disks_to_provide = {
+ {512, 10, VB_DISK_FLAG_FIXED, 0 }, /* too small */
+ {2048, 100, VB_DISK_FLAG_FIXED, 0 }, /* wrong LBA */
+ {512, 100, VB_DISK_FLAG_REMOVABLE, 0 }, /* wrong type */
+ {512, 100, 0, 0 }, /* wrong flags */
+ {512, 100, -1, 0 }, /* still wrong flags */
+ {512, 100, VB_DISK_FLAG_FIXED, "bad1"}, /* doesn't load */
+ {512, 100, VB_DISK_FLAG_FIXED, "bad2"}, /* doesn't load */
+ },
+ .disk_count_to_return = DEFAULT_COUNT,
+ .diskgetinfo_return_val = VBERROR_SUCCESS,
+ .loadkernel_return_val = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
+
+ .expected_recovery_request_val = VBNV_RECOVERY_RW_NO_DISK,
+ .expected_to_find_disk = DONT_CARE,
+ .expected_to_load_disk = 0,
+ .expected_return_val = VBERROR_NO_DISK_FOUND
+ },
+
+};
+
+
+/****************************************************************************/
+
+/* Mock data */
+static LoadKernelParams lkparams;
+static VbDiskInfo mock_disks[MAX_TEST_DISKS];
+static test_case_t *t;
+static int load_kernel_calls;
+static uint32_t got_recovery_request_val;
+static const char *got_find_disk;
+static const char *got_load_disk;
+static uint32_t got_return_val;
+
+/* Reset mock data (for use before each test) */
+static void ResetMocks(int i) {
+ Memset(&lkparams, 0, sizeof(lkparams));
+ Memset(&mock_disks, 0, sizeof(mock_disks));
+ load_kernel_calls = 0;
+
+ got_recovery_request_val = VBNV_RECOVERY_NOT_REQUESTED;
+ got_find_disk = 0;
+ got_load_disk = 0;
+ got_return_val = 0xdeadbeef;
+
+ t = test+i;
+}
+
+int is_nonzero(const void *vptr, size_t count) {
+ const char *p = (const char *)vptr;
+ while (count--)
+ if (*p++)
+ return 1;
+
+ return 0;
+}
+
+int CheckResults(void) {
+ VBDEBUG(("%s()\n", __FUNCTION__));
+ VBDEBUG((" recovery_request: %x %x\n",
+ t->expected_recovery_request_val, got_recovery_request_val));
+ VBDEBUG((" find_disk: (%s) (%s)\n",
+ (t->expected_to_find_disk == DONT_CARE
+ ? "DONT CARE"
+ : t->expected_to_find_disk),
+ got_find_disk));
+ VBDEBUG((" load_disk: (%s) (%s)\n",
+ (t->expected_to_load_disk == DONT_CARE
+ ? "DONT CARE"
+ : t->expected_to_load_disk),
+ got_load_disk));
+ VBDEBUG((" return_val: %x %x\n",
+ t->expected_return_val, got_return_val));
+ return (t->expected_recovery_request_val == got_recovery_request_val &&
+ (t->expected_to_find_disk == DONT_CARE ||
+ t->expected_to_find_disk == got_find_disk) &&
+ (t->expected_to_load_disk == DONT_CARE ||
+ t->expected_to_load_disk == got_load_disk) &&
+ t->expected_return_val == got_return_val);
+}
+
+/****************************************************************************/
+/* Mocked verification functions */
+
+VbError_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count,
+ uint32_t disk_flags) {
+ int i;
+ int num_disks = 0;
+
+ VBDEBUG(("My %s\n", __FUNCTION__));
+
+ *infos_ptr = mock_disks;
+
+ for(i=0; i<MAX_TEST_DISKS; i++) {
+ if (is_nonzero(&t->disks_to_provide[i], sizeof(t->disks_to_provide[i]))) {
+ mock_disks[num_disks].bytes_per_lba =
+ t->disks_to_provide[i].bytes_per_lba;
+ mock_disks[num_disks].lba_count = t->disks_to_provide[i].lba_count;
+ mock_disks[num_disks].flags = t->disks_to_provide[i].flags;
+ mock_disks[num_disks].handle =
+ (VbExDiskHandle_t)t->disks_to_provide[i].diskname;
+ VBDEBUG((" mock_disk[%d] %Ld %Ld 0x%x %s\n", i,
+ mock_disks[num_disks].bytes_per_lba,
+ mock_disks[num_disks].lba_count,
+ mock_disks[num_disks].flags,
+ (mock_disks[num_disks].handle
+ ? (char *)mock_disks[num_disks].handle
+ : "0")));
+ num_disks++;
+ } else {
+ mock_disks[num_disks].handle = (VbExDiskHandle_t)"INVALID";
+ }
+ }
+
+ if (t->disk_count_to_return >= 0)
+ *count = t->disk_count_to_return;
+ else
+ *count = num_disks;
+
+ VBDEBUG((" *count=%Ld\n", *count));
+ VBDEBUG((" return 0x%x\n", t->diskgetinfo_return_val));
+
+ return t->diskgetinfo_return_val;
+}
+
+VbError_t VbExDiskFreeInfo(VbDiskInfo* infos,
+ VbExDiskHandle_t preserve_handle) {
+ got_load_disk = (const char *)preserve_handle;
+ VBDEBUG(("%s(): got_load_disk = %s\n", __FUNCTION__,
+ got_load_disk ? got_load_disk : "0"));
+ return VBERROR_SUCCESS;
+}
+
+VbError_t LoadKernel(LoadKernelParams* params) {
+ got_find_disk = (const char *)params->disk_handle;
+ VBDEBUG(("%s(%d): got_find_disk = %s\n", __FUNCTION__,
+ load_kernel_calls,
+ got_find_disk ? got_find_disk : "0"));
+ return t->loadkernel_return_val[load_kernel_calls++];
+}
+
+int VbNvSet(VbNvContext* context, VbNvParam param, uint32_t value) {
+ VBDEBUG(("%s(): got_recovery_request_val = %d (0x%x)\n", __FUNCTION__,
+ value, value));
+ got_recovery_request_val = value;
+ return 0;
+}
+
+/****************************************************************************/
+
+
+
+/* This is not declared in any headers, so declare it here. */
+uint32_t VbTryLoadKernel(VbCommonParams* cparams, LoadKernelParams* p,
+ uint32_t get_info_flags);
+
+
+static void VbTryLoadKernelTest(void) {
+ int i;
+ int num_tests = sizeof(test) / sizeof(test[0]);
+
+ for (i=0; i<num_tests; i++) {
+ VBDEBUG(("STARTING %s ...\n", test[i].name));
+ ResetMocks(i);
+ got_return_val = VbTryLoadKernel(0, &lkparams, test[i].want_flags);
+ VBDEBUG(("VbTryLoadKernel(): got_return_val = 0x%x\n", got_return_val));
+ TEST_TRUE(CheckResults(), test[i].name);
+ }
+}
+
+
+/* disable MSVC warnings on unused arguments */
+__pragma(warning (disable: 4100))
+
+int main(int argc, char* argv[]) {
+ int error_code = 0;
+
+ VbTryLoadKernelTest();
+
+ if (!gTestSuccess)
+ error_code = 255;
+
+ return error_code;
+}