diff options
Diffstat (limited to 'tests/vboot_api_kernel_tests.c')
-rw-r--r-- | tests/vboot_api_kernel_tests.c | 320 |
1 files changed, 320 insertions, 0 deletions
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; +} |