You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
331 lines
8.9 KiB
331 lines
8.9 KiB
/* 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 VbTryLoadKernel()
|
|
*/
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.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"
|
|
#include "vboot_kernel.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];
|
|
uint8_t external_expected[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 = {
|
|
/* too small */
|
|
{512, 10, VB_DISK_FLAG_REMOVABLE, 0},
|
|
/* wrong LBA */
|
|
{2048, 100, VB_DISK_FLAG_REMOVABLE, 0},
|
|
/* wrong type */
|
|
{512, 100, VB_DISK_FLAG_FIXED, 0},
|
|
/* wrong flags */
|
|
{512, 100, 0, 0},
|
|
/* still wrong flags */
|
|
{512, 100, -1, 0},
|
|
{512, 100,
|
|
VB_DISK_FLAG_REMOVABLE | VB_DISK_FLAG_EXTERNAL_GPT,
|
|
pickme},
|
|
/* already got one */
|
|
{512, 100, VB_DISK_FLAG_REMOVABLE, "holygrail"},
|
|
},
|
|
.disk_count_to_return = DEFAULT_COUNT,
|
|
.diskgetinfo_return_val = VBERROR_SUCCESS,
|
|
.loadkernel_return_val = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
|
|
.external_expected = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
|
|
|
|
.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 = {
|
|
/* wrong flags */
|
|
{512, 100, 0, 0},
|
|
{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 = {
|
|
/* too small */
|
|
{512, 10, VB_DISK_FLAG_FIXED, 0},
|
|
/* wrong LBA */
|
|
{2048, 100, VB_DISK_FLAG_FIXED, 0},
|
|
/* wrong type */
|
|
{512, 100, VB_DISK_FLAG_REMOVABLE, 0},
|
|
/* wrong flags */
|
|
{512, 100, 0, 0},
|
|
/* still wrong flags */
|
|
{512, 100, -1, 0},
|
|
/* flags */
|
|
{512, 100, VB_DISK_FLAG_REMOVABLE|VB_DISK_FLAG_FIXED,
|
|
0},
|
|
{512, 100, VB_DISK_FLAG_FIXED, pickme},
|
|
/* already got one */
|
|
{512, 100, VB_DISK_FLAG_FIXED, "holygrail"},
|
|
},
|
|
.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 = {
|
|
/* too small */
|
|
{512, 10, VB_DISK_FLAG_FIXED, 0},
|
|
/* wrong LBA */
|
|
{2048, 100, VB_DISK_FLAG_FIXED, 0},
|
|
/* wrong type */
|
|
{512, 100, VB_DISK_FLAG_REMOVABLE, 0},
|
|
/* wrong flags */
|
|
{512, 100, 0, 0},
|
|
/* still wrong flags */
|
|
{512, 100, -1, 0},
|
|
/* doesn't load */
|
|
{512, 100, VB_DISK_FLAG_FIXED, "bad1"},
|
|
/* doesn't load */
|
|
{512, 100, VB_DISK_FLAG_FIXED, "bad2"},
|
|
},
|
|
.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_KERNEL,
|
|
.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;
|
|
static uint32_t got_external_mismatch;
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* 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 =
|
|
mock_disks[num_disks].streaming_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] %" PRIu64 " %" PRIu64
|
|
" 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=%" PRIu32 "\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, VbCommonParams *cparams)
|
|
{
|
|
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"));
|
|
if (t->external_expected[load_kernel_calls] !=
|
|
!!(params->boot_flags & BOOT_FLAG_EXTERNAL_GPT))
|
|
got_external_mismatch++;
|
|
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;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static void VbTryLoadKernelTest(void)
|
|
{
|
|
int i;
|
|
int num_tests = sizeof(test) / sizeof(test[0]);
|
|
|
|
for (i = 0; i < num_tests; i++) {
|
|
printf("Test case: %s ...\n", test[i].name);
|
|
ResetMocks(i);
|
|
TEST_EQ(VbTryLoadKernel(0, &lkparams, test[i].want_flags),
|
|
t->expected_return_val, " return value");
|
|
TEST_EQ(got_recovery_request_val,
|
|
t->expected_recovery_request_val, " recovery_request");
|
|
if (t->expected_to_find_disk != DONT_CARE) {
|
|
TEST_PTR_EQ(got_find_disk, t->expected_to_find_disk,
|
|
" find disk");
|
|
TEST_PTR_EQ(got_load_disk, t->expected_to_load_disk,
|
|
" load disk");
|
|
}
|
|
TEST_EQ(got_external_mismatch, 0, " external GPT errors");
|
|
}
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
VbTryLoadKernelTest();
|
|
|
|
if (vboot_api_stub_check_memory())
|
|
return 255;
|
|
|
|
return gTestSuccess ? 0 : 255;
|
|
}
|