/* 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 #include #include #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 = 1 }, }; /****************************************************************************/ /* 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; idisks_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] %lld %lld 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=%lld\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