blob: 1f77cc5c63b4d53a3247c03f0dca2a4b78c3dfe0 [file] [log] [blame]
/* 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 vboot_kernel.c
*/
#include "2api.h"
#include "2common.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2secdata.h"
#include "2secdata_struct.h"
#include "cgptlib.h"
#include "cgptlib_internal.h"
#include "gpt.h"
#include "load_kernel_fw.h"
#include "test_common.h"
#include "vboot_api.h"
/* Mock kernel partition */
struct mock_part {
uint32_t start;
uint32_t size;
};
/* Partition list; ends with a 0-size partition. */
#define MOCK_PART_COUNT 8
static struct mock_part mock_parts[MOCK_PART_COUNT];
static int mock_part_next;
/* Mock data */
static uint8_t kernel_buffer[80000];
static int disk_read_to_fail;
static int gpt_init_fail;
static int keyblock_verify_fail; /* 0=ok, 1=sig, 2=hash */
static int preamble_verify_fail;
static int verify_data_fail;
static int unpack_key_fail;
static int gpt_flag_external;
static struct vb2_gbb_header gbb;
static VbSelectAndLoadKernelParams lkp;
static VbDiskInfo disk_info;
static struct vb2_keyblock kbh;
static struct vb2_kernel_preamble kph;
static struct vb2_secdata_fwmp *fwmp;
static uint8_t mock_digest[VB2_SHA256_DIGEST_SIZE] = {12, 34, 56, 78};
static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
__attribute__((aligned(VB2_WORKBUF_ALIGN)));
static struct vb2_context *ctx;
static struct vb2_shared_data *sd;
static struct vb2_packed_key mock_key;
static enum vb2_boot_mode *boot_mode;
/**
* Reset mock data (for use before each test)
*/
static void ResetMocks(void)
{
disk_read_to_fail = -1;
gpt_init_fail = 0;
keyblock_verify_fail = 0;
preamble_verify_fail = 0;
verify_data_fail = 0;
unpack_key_fail = 0;
gpt_flag_external = 0;
memset(&gbb, 0, sizeof(gbb));
gbb.major_version = VB2_GBB_MAJOR_VER;
gbb.minor_version = VB2_GBB_MINOR_VER;
gbb.flags = 0;
memset(&lkp, 0, sizeof(lkp));
lkp.kernel_buffer = kernel_buffer;
lkp.kernel_buffer_size = sizeof(kernel_buffer);
lkp.disk_handle = (VbExDiskHandle_t)1;
memset(&disk_info, 0, sizeof(disk_info));
disk_info.bytes_per_lba = 512;
disk_info.streaming_lba_count = 1024;
disk_info.lba_count = 1024;
disk_info.handle = lkp.disk_handle;
memset(&kbh, 0, sizeof(kbh));
kbh.data_key.key_version = 2;
kbh.keyblock_flags = -1;
kbh.keyblock_size = sizeof(kbh);
memset(&kph, 0, sizeof(kph));
kph.kernel_version = 1;
kph.preamble_size = 4096 - kbh.keyblock_size;
kph.body_signature.data_size = 70144;
kph.bootloader_address = 0xbeadd008;
kph.bootloader_size = 0x1234;
memset(mock_parts, 0, sizeof(mock_parts));
mock_parts[0].start = 100;
mock_parts[0].size = 150; /* 75 KB */
mock_part_next = 0;
memset(&mock_key, 0, sizeof(mock_key));
TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
"vb2api_init failed");
vb2_nv_init(ctx);
sd = vb2_get_sd(ctx);
sd->kernel_version_secdata = 0x20001;
/* CRC will be invalid after here, but nobody's checking */
sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT;
fwmp = (struct vb2_secdata_fwmp *)ctx->secdata_fwmp;
memcpy(&fwmp->dev_key_hash, mock_digest, sizeof(fwmp->dev_key_hash));
boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode;
*boot_mode = VB2_BOOT_MODE_NORMAL;
// TODO: more workbuf fields - flags, secdata_firmware
vb2api_secdata_kernel_create(ctx);
vb2_secdata_kernel_init(ctx);
vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS,
VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED);
}
/* Mocks */
struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
{
return &gbb;
}
vb2_error_t vb2ex_read_resource(struct vb2_context *c,
enum vb2_resource_index index, uint32_t offset,
void *buf, uint32_t size)
{
memset(buf, 0, size);
return VB2_SUCCESS;
}
vb2_error_t vb2_gbb_read_root_key(struct vb2_context *c,
struct vb2_packed_key **keyp, uint32_t *size,
struct vb2_workbuf *wb)
{
*keyp = &mock_key;
return VB2_SUCCESS;
}
vb2_error_t vb2_gbb_read_recovery_key(struct vb2_context *c,
struct vb2_packed_key **keyp,
uint32_t *size, struct vb2_workbuf *wb)
{
*keyp = &mock_key;
return VB2_SUCCESS;
}
vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start,
uint64_t lba_count, void *buffer)
{
if ((int)lba_start == disk_read_to_fail)
return VB2_ERROR_MOCK;
return VB2_SUCCESS;
}
int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
{
return GPT_SUCCESS;
}
int GptInit(GptData *gpt)
{
return gpt_init_fail;
}
int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size)
{
struct mock_part *p = mock_parts + mock_part_next;
if (!p->size)
return GPT_ERROR_NO_VALID_KERNEL;
if (gpt->flags & GPT_FLAG_EXTERNAL)
gpt_flag_external++;
gpt->current_kernel = mock_part_next;
*start_sector = p->start;
*size = p->size;
mock_part_next++;
return GPT_SUCCESS;
}
int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type)
{
return GPT_SUCCESS;
}
int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
{
return GPT_SUCCESS;
}
void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest)
{
static char fake_guid[] = "FakeGuid";
memcpy(dest, fake_guid, sizeof(fake_guid));
}
vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key,
const uint8_t *buf, uint32_t size)
{
if (--unpack_key_fail == 0)
return VB2_ERROR_MOCK;
return VB2_SUCCESS;
}
vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size,
const struct vb2_public_key *key,
const struct vb2_workbuf *wb)
{
if (keyblock_verify_fail >= 1)
return VB2_ERROR_MOCK;
/* Use this as an opportunity to override the keyblock */
memcpy((void *)block, &kbh, sizeof(kbh));
return VB2_SUCCESS;
}
vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block,
uint32_t size,
const struct vb2_workbuf *wb)
{
if (keyblock_verify_fail >= 2)
return VB2_ERROR_MOCK;
/* Use this as an opportunity to override the keyblock */
memcpy((void *)block, &kbh, sizeof(kbh));
return VB2_SUCCESS;
}
vb2_error_t vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
uint32_t size, const struct vb2_public_key *key,
const struct vb2_workbuf *wb)
{
if (preamble_verify_fail)
return VB2_ERROR_MOCK;
/* Use this as an opportunity to override the preamble */
memcpy((void *)preamble, &kph, sizeof(kph));
return VB2_SUCCESS;
}
vb2_error_t vb2_verify_data(const uint8_t *data, uint32_t size,
struct vb2_signature *sig,
const struct vb2_public_key *key,
const struct vb2_workbuf *wb)
{
if (verify_data_fail)
return VB2_ERROR_MOCK;
return VB2_SUCCESS;
}
vb2_error_t vb2_digest_buffer(const uint8_t *buf, uint32_t size,
enum vb2_hash_algorithm hash_alg, uint8_t *digest,
uint32_t digest_size)
{
memcpy(digest, mock_digest, sizeof(mock_digest));
return VB2_SUCCESS;
}
/* Make sure nothing tested here ever calls this directly. */
void vb2api_fail(struct vb2_context *c, uint8_t reason, uint8_t subcode)
{
TEST_TRUE(0, " called vb2api_fail()");
}
static void TestLoadKernel(int expect_retval, const char *test_name)
{
TEST_EQ(LoadKernel(ctx, &lkp, &disk_info), expect_retval, test_name);
}
/**
* Trivial invalid calls to LoadKernel()
*/
static void InvalidParamsTest(void)
{
ResetMocks();
gpt_init_fail = 1;
TestLoadKernel(VB2_ERROR_LK_NO_KERNEL_FOUND, "Bad GPT");
/* This causes the stream open call to fail */
ResetMocks();
lkp.disk_handle = NULL;
disk_info.handle = NULL;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad disk handle");
}
static void LoadKernelTest(void)
{
ResetMocks();
TestLoadKernel(0, "First kernel good");
TEST_EQ(lkp.partition_number, 1, " part num");
TEST_EQ(lkp.bootloader_address, 0xbeadd008, " bootloader addr");
TEST_EQ(lkp.bootloader_size, 0x1234, " bootloader size");
TEST_STR_EQ((char *)lkp.partition_guid, "FakeGuid", " guid");
TEST_EQ(gpt_flag_external, 0, "GPT was internal");
TEST_NEQ(sd->flags & VB2_SD_FLAG_KERNEL_SIGNED, 0, " use signature");
ResetMocks();
mock_parts[1].start = 300;
mock_parts[1].size = 150;
TestLoadKernel(0, "Two good kernels");
TEST_EQ(lkp.partition_number, 1, " part num");
TEST_EQ(mock_part_next, 1, " didn't read second one");
/* Fail if no kernels found */
ResetMocks();
mock_parts[0].size = 0;
TestLoadKernel(VB2_ERROR_LK_NO_KERNEL_FOUND, "No kernels");
/* Skip kernels which are too small */
ResetMocks();
mock_parts[0].size = 10;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Too small");
ResetMocks();
disk_read_to_fail = 100;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Fail reading kernel start");
ResetMocks();
keyblock_verify_fail = 1;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Fail key block sig");
/* In dev mode, fail if hash is bad too */
ResetMocks();
ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
keyblock_verify_fail = 2;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Fail key block dev hash");
/* But just bad sig is ok */
ResetMocks();
ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
keyblock_verify_fail = 1;
TestLoadKernel(0, "Succeed keyblock dev sig");
TEST_EQ(sd->flags & VB2_SD_FLAG_KERNEL_SIGNED, 0, " use hash");
/* In dev mode and requiring signed kernel, fail if sig is bad */
ResetMocks();
ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
keyblock_verify_fail = 1;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Fail key block dev sig");
ResetMocks();
ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY;
keyblock_verify_fail = 1;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Fail key block dev sig fwmp");
/* Check keyblock flags */
ResetMocks();
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
| VB2_KEYBLOCK_FLAG_DEVELOPER_1
| VB2_KEYBLOCK_FLAG_MINIOS_0;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock dev flag mismatch");
ResetMocks();
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_0;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock rec flag mismatch");
ResetMocks();
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_1;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock minios flag mismatch");
ResetMocks();
ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
*boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_1
| VB2_KEYBLOCK_FLAG_MINIOS_0;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock recdev flag mismatch");
ResetMocks();
ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
*boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_0;
TestLoadKernel(0, "Keyblock rec flag okay");
ResetMocks();
ctx->flags |= VB2_CONTEXT_RECOVERY_MODE | VB2_CONTEXT_DEVELOPER_MODE;
*boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_0;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock rec!dev flag mismatch");
ResetMocks();
ctx->flags |= VB2_CONTEXT_RECOVERY_MODE | VB2_CONTEXT_DEVELOPER_MODE;
*boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_1
| VB2_KEYBLOCK_FLAG_MINIOS_0;
TestLoadKernel(0, "Keyblock recdev flag okay");
/* Check keyblock flags (dev mode + signed kernel required) */
ResetMocks();
ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_0;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock dev flag mismatch (signed kernel required)");
ResetMocks();
ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY;
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_0;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock dev flag mismatch (signed kernel required)");
ResetMocks();
ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY;
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_1;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock dev flag mismatch (signed kernel required)");
ResetMocks();
ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
| VB2_KEYBLOCK_FLAG_DEVELOPER_1
| VB2_KEYBLOCK_FLAG_MINIOS_0;
TestLoadKernel(0, "Keyblock dev flag okay (signed kernel required)");
/* Check kernel key version */
ResetMocks();
kbh.data_key.key_version = 1;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock kernel key rollback");
ResetMocks();
kbh.data_key.key_version = 0x10000;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock kernel key version too big");
ResetMocks();
kbh.data_key.key_version = 3;
TestLoadKernel(0, "Keyblock version roll forward");
TEST_EQ(sd->kernel_version, 0x30001, " SD version");
ResetMocks();
kbh.data_key.key_version = 3;
mock_parts[1].start = 300;
mock_parts[1].size = 150;
TestLoadKernel(0, "Two kernels roll forward");
TEST_EQ(mock_part_next, 2, " read both");
TEST_EQ(sd->kernel_version, 0x30001, " SD version");
ResetMocks();
kbh.data_key.key_version = 1;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
TestLoadKernel(0, "Key version ignored in dev mode");
ResetMocks();
kbh.data_key.key_version = 1;
*boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
TestLoadKernel(0, "Key version ignored in rec mode");
ResetMocks();
unpack_key_fail = 2;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad data key");
ResetMocks();
preamble_verify_fail = 1;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad preamble");
ResetMocks();
kph.kernel_version = 0;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Kernel version rollback");
ResetMocks();
kph.kernel_version = 0;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
TestLoadKernel(0, "Kernel version ignored in dev mode");
ResetMocks();
kph.kernel_version = 0;
*boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
TestLoadKernel(0, "Kernel version ignored in rec mode");
/* Check kernel version (dev mode + signed kernel required) */
ResetMocks();
kbh.data_key.key_version = 0;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock key version checked in dev mode "
"(signed kernel required)");
ResetMocks();
kbh.data_key.key_version = 0;
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Keyblock key version checked in dev mode "
"(signed kernel required)");
/* Check developer key hash - bad */
ResetMocks();
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
fwmp->flags |= VB2_SECDATA_FWMP_DEV_USE_KEY_HASH;
fwmp->dev_key_hash[0]++;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Fail keyblock dev fwmp hash");
/* Check developer key hash - bad (recovery mode) */
ResetMocks();
*boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
fwmp->flags |= VB2_SECDATA_FWMP_DEV_USE_KEY_HASH;
fwmp->dev_key_hash[0]++;
TestLoadKernel(0, "Bad keyblock dev fwmp hash ignored in rec mode");
/* Check developer key hash - good */
ResetMocks();
*boot_mode = VB2_BOOT_MODE_DEVELOPER;
fwmp->flags |= VB2_SECDATA_FWMP_DEV_USE_KEY_HASH;
TestLoadKernel(0, "Good keyblock dev fwmp hash");
ResetMocks();
kph.preamble_size |= 0x07;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Kernel body offset");
ResetMocks();
kph.preamble_size += 65536;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Kernel body offset huge");
/* Check getting kernel load address from header */
ResetMocks();
kph.body_load_address = (size_t)kernel_buffer;
lkp.kernel_buffer = NULL;
TestLoadKernel(0, "Get load address from preamble");
TEST_PTR_EQ(lkp.kernel_buffer, kernel_buffer, " address");
/* Size is rounded up to nearest sector */
TEST_EQ(lkp.kernel_buffer_size, 70144, " size");
ResetMocks();
lkp.kernel_buffer_size = 8192;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Kernel too big for buffer");
ResetMocks();
mock_parts[0].size = 130;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Kernel too big for partition");
ResetMocks();
kph.body_signature.data_size = 8192;
TestLoadKernel(0, "Kernel tiny");
ResetMocks();
disk_read_to_fail = 228;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
"Fail reading kernel data");
ResetMocks();
verify_data_fail = 1;
TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad data");
/* Check that EXTERNAL_GPT flag makes it down */
ResetMocks();
disk_info.flags |= VB_DISK_FLAG_EXTERNAL_GPT;
TestLoadKernel(0, "Succeed external GPT");
TEST_EQ(gpt_flag_external, 1, "GPT was external");
/* Check recovery from unreadble primary GPT */
ResetMocks();
disk_read_to_fail = 1;
TestLoadKernel(0, "Can't read disk");
}
int main(void)
{
InvalidParamsTest();
LoadKernelTest();
return gTestSuccess ? 0 : 255;
}