blob: 792f3281e866e5c3d234481f2bbf8a3027f53b3d [file] [log] [blame]
/* 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 = 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; 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;
}