mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 18:25:10 +00:00
This patch reinstates the external GPT support which was previously committed and reverted. Improvements since last time include: - Cleaned-up internal interface based on code review - Function correctly on legacy bootloaders (e.g., depthcharge before NAND-related patches are added) - Better comments - Treat new field values = 0 -> not use new feature - Tests are added to ensure external GPT flag is passed down properly The original commit had change-id I5a77e417aea8ee9442d18c200d1b073aa5375ecf Its commit message is reproduced below, and then an additional test. ---- To support an external GPT, disks have two new attributes: - A binary flag indicating whether the GPT is in the same address space as the payloads or a separate one. - The number of sectors of the streaming portion of storage, as opposed to the portion containing the GPT. These have been added elsewhere to GptData (in cgptlib) and BlockDev (in depthcharge). This patch adds the plumbing between those, including in the DiskInfo interface between the firmware and vboot. BUG=chromium:425677 BRANCH=none TEST=Interactively wrote the GPT with cgpt and observed the following boot with depthcharge to read the GPT from SPI and then read from the proper locations in NAND flash. TEST=make runalltests passes. TEST=boots from USB with depthcharge from HEAD. Change-Id: Ia7956517a7b9da0301f01fac5a10204f6d78cf4f Signed-off-by: Dan Ehrenberg <dehrenberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/234640 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
331 lines
8.9 KiB
C
331 lines
8.9 KiB
C
/* 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;
|
|
}
|