From 7f43669630cb42e40ca6ddc1128eefea8fd339d9 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Tue, 5 Feb 2013 12:42:36 -0800 Subject: Add more vboot_api_kernel tests BUG=chromium-os:38139 BRANCH=none TEST=make runtests && FEATURES=test emerge-daisy vboot_reference Change-Id: Ib280b80ba707f8a2141d728f78ae296774b1301a Signed-off-by: Randall Spangler Reviewed-on: https://gerrit.chromium.org/gerrit/42669 --- Makefile | 6 + firmware/lib/include/vboot_kernel.h | 45 +++ firmware/lib/vboot_api_kernel.c | 33 +-- tests/vboot_api_kernel2_tests.c | 554 ++++++++++++++++++++++++++++++++++++ tests/vboot_api_kernel3_tests.c | 335 ++++++++++++++++++++++ tests/vboot_api_kernel4_tests.c | 241 ++++++++++++++++ tests/vboot_api_kernel_tests.c | 6 +- 7 files changed, 1189 insertions(+), 31 deletions(-) create mode 100644 tests/vboot_api_kernel2_tests.c create mode 100644 tests/vboot_api_kernel3_tests.c create mode 100644 tests/vboot_api_kernel4_tests.c diff --git a/Makefile b/Makefile index cc310dea..9cb27ea7 100644 --- a/Makefile +++ b/Makefile @@ -419,6 +419,9 @@ TEST_NAMES = \ vboot_api_devmode_tests \ vboot_api_firmware_tests \ vboot_api_kernel_tests \ + vboot_api_kernel2_tests \ + vboot_api_kernel3_tests \ + vboot_api_kernel4_tests \ vboot_audio_tests \ vboot_common_tests \ vboot_common2_tests \ @@ -948,6 +951,9 @@ runmisctests: test_setup ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_firmware_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_init_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel_tests + ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel2_tests + ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel3_tests + ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel4_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_audio_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_common_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_common2_tests ${TEST_KEYS} diff --git a/firmware/lib/include/vboot_kernel.h b/firmware/lib/include/vboot_kernel.h index 6e6c5dc3..e3a44190 100644 --- a/firmware/lib/include/vboot_kernel.h +++ b/firmware/lib/include/vboot_kernel.h @@ -10,7 +10,9 @@ #define VBOOT_REFERENCE_VBOOT_KERNEL_H_ #include "cgptlib.h" +#include "load_firmware_fw.h" #include "vboot_api.h" +#include "vboot_kernel.h" /** * Allocate and read GPT data from the drive. The sector_bytes and @@ -26,4 +28,47 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata); */ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata); +/** + * Accessors for unit tests only. + */ +VbNvContext *VbApiKernelGetVnc(void); + +/** + * Try to load a kernel. + */ +uint32_t VbTryLoadKernel(VbCommonParams *cparams, LoadKernelParams *p, + uint32_t get_info_flags); + +/** + * Ask the user to confirm something. + * + * We should display whatever the question is first, then call this. ESC is + * always "no", ENTER is always "yes", and we'll specify what SPACE means. We + * don't return until one of those keys is pressed, or until asked to shut + * down. + * + * Returns: 1=yes, 0=no, -1 = shutdown. + */ +int VbUserConfirms(VbCommonParams *cparams, int space_means_no); + +/** + * Handle a normal boot. + */ +VbError_t VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p); + +/** + * Handle a developer-mode boot. + */ +VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p); + +/** + * Handle a recovery-mode boot. + */ +VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p); + +/** + * Sync EC firmware to expected version. + */ +VbError_t VbEcSoftwareSync(VbCommonParams *cparams); + #endif /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */ diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index c7213ede..9b596fc2 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -28,7 +28,7 @@ VbNvContext *VbApiKernelGetVnc(void) #endif /** - * Set recovery request + * Set recovery request (called from vboot_api_kernel.c functions only) */ static void VbSetRecoveryRequest(uint32_t recovery_request) { @@ -125,17 +125,7 @@ uint32_t VbTryLoadKernel(VbCommonParams *cparams, LoadKernelParams *p, #define CONFIRM_KEY_DELAY 20 /* Check confirm screen keys every 20ms */ -/** - * Ask the user to confirm something. - * - * We should display whatever the question is first, then call this. ESC is - * always "no", ENTER is always "yes", and we'll specify what SPACE means. We - * don't return until one of those keys is pressed, or until asked to shut - * down. - * - * Returns: 1=yes, 0=no, -1 = shutdown. - */ -static int VbUserConfirms(VbCommonParams *cparams, int space_means_no) +int VbUserConfirms(VbCommonParams *cparams, int space_means_no) { uint32_t key; @@ -171,9 +161,6 @@ static int VbUserConfirms(VbCommonParams *cparams, int space_means_no) return -1; } -/** - * Handle a normal boot. - */ VbError_t VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p) { /* Boot from fixed disk only */ @@ -181,9 +168,6 @@ VbError_t VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p) return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED); } -/** - * Handle a developer-mode boot. - */ VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p) { GoogleBinaryBlockHeader *gbb = @@ -320,11 +304,11 @@ VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p) VbExBeep(120, 400); break; - case VB_KEY_CTRL_ENTER: - /* - * The Ctrl-Enter is special for Lumpy test purpose; fall through - * to Ctrl+U handler. - */ + case VB_KEY_CTRL_ENTER: + /* + * The Ctrl-Enter is special for Lumpy test purpose; + * fall through to Ctrl+U handler. + */ case 0x15: /* Ctrl+U = try USB boot, or beep if failure */ VBDEBUG(("VbBootDeveloper() - " @@ -393,9 +377,6 @@ VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p) #define REC_DISK_DELAY 1000 /* Check disks every 1s */ #define REC_KEY_DELAY 20 /* Check keys every 20ms */ -/** - * Handle a recovery-mode boot. - */ VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p) { VbSharedDataHeader *shared = diff --git a/tests/vboot_api_kernel2_tests.c b/tests/vboot_api_kernel2_tests.c new file mode 100644 index 00000000..9b921cd2 --- /dev/null +++ b/tests/vboot_api_kernel2_tests.c @@ -0,0 +1,554 @@ +/* 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_api_kernel, part 2 + */ + +#include +#include + +#include "gbb_header.h" +#include "host_common.h" +#include "load_kernel_fw.h" +#include "rollback_index.h" +#include "test_common.h" +#include "vboot_audio.h" +#include "vboot_common.h" +#include "vboot_kernel.h" +#include "vboot_nvstorage.h" +#include "vboot_struct.h" + +/* Mock data */ +static VbCommonParams cparams; +static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; +static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; +static GoogleBinaryBlockHeader gbb; +static LoadKernelParams lkp; + +static int shutdown_request_calls_left; +static int audio_looping_calls_left; +static uint32_t vbtlk_retval; +static int vbexlegacy_called; +static int trust_ec; +static int virtdev_set; +static uint32_t virtdev_retval; + +static uint32_t mock_keypress[8]; +static uint32_t mock_keypress_count; +static uint32_t screens_displayed[8]; +static uint32_t screens_count = 0; +static uint32_t mock_num_disks[8]; +static uint32_t mock_num_disks_count; + +/* Reset mock data (for use before each test) */ +static void ResetMocks(void) +{ + Memset(&cparams, 0, sizeof(cparams)); + cparams.shared_data_size = sizeof(shared_data); + cparams.shared_data_blob = shared_data; + cparams.gbb_data = &gbb; + + Memset(&gbb, 0, sizeof(gbb)); + gbb.major_version = GBB_MAJOR_VER; + gbb.minor_version = GBB_MINOR_VER; + gbb.flags = 0; + + /* + * Only the outermost vboot_api_kernel call sets vboot_api_kernel's + * vnc. So clear it here too. + */ + Memset(VbApiKernelGetVnc(), 0, sizeof(VbNvContext)); + VbNvSetup(VbApiKernelGetVnc()); + VbNvTeardown(VbApiKernelGetVnc()); /* So CRC gets generated */ + + Memset(&shared_data, 0, sizeof(shared_data)); + VbSharedDataInit(shared, sizeof(shared_data)); + + Memset(&lkp, 0, sizeof(lkp)); + + shutdown_request_calls_left = -1; + audio_looping_calls_left = 30; + vbtlk_retval = 1000; + vbexlegacy_called = 0; + trust_ec = 0; + virtdev_set = 0; + virtdev_retval = 0; + + Memset(screens_displayed, 0, sizeof(screens_displayed)); + screens_count = 0; + + Memset(mock_keypress, 0, sizeof(mock_keypress)); + mock_keypress_count = 0; + + Memset(mock_num_disks, 0, sizeof(mock_num_disks)); + mock_num_disks_count = 0; +} + +/* Mock functions */ + +uint32_t VbExIsShutdownRequested(void) +{ + if (shutdown_request_calls_left == 0) + return 1; + else if (shutdown_request_calls_left > 0) + shutdown_request_calls_left--; + + return 0; +} + +uint32_t VbExKeyboardRead(void) +{ + if (mock_keypress_count < ARRAY_SIZE(mock_keypress)) + return mock_keypress[mock_keypress_count++]; + else + return 0; +} + +int VbExLegacy(void) +{ + vbexlegacy_called++; + return 0; +} + +VbError_t VbExDiskGetInfo(VbDiskInfo **infos_ptr, uint32_t *count, + uint32_t disk_flags) +{ + if (mock_num_disks_count < ARRAY_SIZE(mock_num_disks)) { + if (mock_num_disks[mock_num_disks_count] == -1) + return VBERROR_SIMULATED; + else + *count = mock_num_disks[mock_num_disks_count++]; + } else { + *count = 0; + } + return VBERROR_SUCCESS; +} + +VbError_t VbExDiskFreeInfo(VbDiskInfo *infos, + VbExDiskHandle_t preserve_handle) +{ + return VBERROR_SUCCESS; +} + +int VbExTrustEC(void) +{ + return trust_ec; +} + +int VbAudioLooping(VbAudioContext *audio) +{ + if (audio_looping_calls_left == 0) + return 0; + else if (audio_looping_calls_left > 0) + audio_looping_calls_left--; + + return 1; +} + +uint32_t VbTryLoadKernel(VbCommonParams *cparams, LoadKernelParams *p, + uint32_t get_info_flags) +{ + return vbtlk_retval + get_info_flags; +} + +VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, int force, + VbNvContext *vncptr) +{ + if (screens_count < ARRAY_SIZE(screens_displayed)) + screens_displayed[screens_count++] = screen; + + return VBERROR_SUCCESS; +} + +uint32_t SetVirtualDevMode(int val) +{ + virtdev_set = val; + return virtdev_retval; +} + +/* Tests */ + +static void VbUserConfirmsTest(void) +{ + printf("Testing VbUserConfirms()...\n"); + + ResetMocks(); + shutdown_request_calls_left = 1; + TEST_EQ(VbUserConfirms(&cparams, 0), -1, "Shutdown requested"); + + ResetMocks(); + mock_keypress[0] = '\r'; + TEST_EQ(VbUserConfirms(&cparams, 0), 1, "Enter"); + + ResetMocks(); + mock_keypress[0] = 0x1b; + TEST_EQ(VbUserConfirms(&cparams, 0), 0, "Esc"); + + ResetMocks(); + mock_keypress[0] = ' '; + shutdown_request_calls_left = 1; + TEST_EQ(VbUserConfirms(&cparams, 1), 0, "Space means no"); + + ResetMocks(); + mock_keypress[0] = ' '; + shutdown_request_calls_left = 1; + TEST_EQ(VbUserConfirms(&cparams, 0), -1, "Space ignored"); + + printf("...done.\n"); +} + +static void VbBootTest(void) +{ + ResetMocks(); + TEST_EQ(VbBootNormal(&cparams, &lkp), 1002, "VbBootNormal()"); +} + +static void VbBootDevTest(void) +{ + uint32_t u; + + printf("Testing VbBootDeveloper()...\n"); + + /* Proceed after timeout */ + ResetMocks(); + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Timeout"); + TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, + " warning screen"); + VbNvGet(VbApiKernelGetVnc(), VBNV_RECOVERY_REQUEST, &u); + TEST_EQ(u, 0, " recovery reason"); + TEST_EQ(audio_looping_calls_left, 0, " used up audio"); + + /* Up arrow is uninteresting / passed to VbCheckDisplayKey() */ + ResetMocks(); + mock_keypress[0] = VB_KEY_UP; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Up arrow"); + + /* Shutdown requested in loop */ + ResetMocks(); + shutdown_request_calls_left = 2; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Shutdown requested"); + TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); + + /* Space goes straight to recovery if no virtual dev switch */ + ResetMocks(); + mock_keypress[0] = ' '; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), VBERROR_LOAD_KERNEL_RECOVERY, + "Space = recovery"); + VbNvGet(VbApiKernelGetVnc(), VBNV_RECOVERY_REQUEST, &u); + TEST_EQ(u, VBNV_RECOVERY_RW_DEV_SCREEN, " recovery reason"); + + /* Space asks to disable virtual dev switch */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; + mock_keypress[0] = ' '; + mock_keypress[1] = '\r'; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), VBERROR_TPM_REBOOT_REQUIRED, + "Space = tonorm"); + TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, + " warning screen"); + TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM, + " tonorm screen"); + TEST_EQ(screens_displayed[2], VB_SCREEN_TO_NORM_CONFIRMED, + " confirm screen"); + VbNvGet(VbApiKernelGetVnc(), VBNV_DISABLE_DEV_REQUEST, &u); + TEST_EQ(u, 1, " disable dev request"); + + /* Space-space doesn't disable it */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; + mock_keypress[0] = ' '; + mock_keypress[1] = ' '; + mock_keypress[2] = 0x1b; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Space-space"); + TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, + " warning screen"); + TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM, + " tonorm screen"); + TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING, + " warning screen"); + + /* Enter doesn't by default */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; + mock_keypress[0] = '\r'; + mock_keypress[1] = '\r'; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Enter ignored"); + + /* Enter does if GBB flag set */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; + gbb.flags |= GBB_FLAG_ENTER_TRIGGERS_TONORM; + mock_keypress[0] = '\r'; + mock_keypress[1] = '\r'; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), VBERROR_TPM_REBOOT_REQUIRED, + "Enter = tonorm"); + + /* Tonorm ignored if GBB forces dev switch on */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; + gbb.flags |= GBB_FLAG_FORCE_DEV_SWITCH_ON; + mock_keypress[0] = ' '; + mock_keypress[1] = '\r'; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Can't tonorm gbb-dev"); + + /* Shutdown requested at tonorm screen */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; + mock_keypress[0] = ' '; + shutdown_request_calls_left = 2; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Shutdown requested at tonorm"); + TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, + " warning screen"); + TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM, + " tonorm screen"); + + /* Ctrl+D dismisses warning */ + ResetMocks(); + mock_keypress[0] = 0x04; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Ctrl+D"); + VbNvGet(VbApiKernelGetVnc(), VBNV_RECOVERY_REQUEST, &u); + TEST_EQ(u, 0, " recovery reason"); + TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); + + /* Ctrl+L tries legacy boot mode only if enabled */ + ResetMocks(); + mock_keypress[0] = 0x0c; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Ctrl+L normal"); + TEST_EQ(vbexlegacy_called, 0, " not legacy"); + + ResetMocks(); + + gbb.flags |= GBB_FLAG_FORCE_DEV_BOOT_LEGACY; + mock_keypress[0] = 0x0c; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Ctrl+L force legacy"); + TEST_EQ(vbexlegacy_called, 1, " try legacy"); + + ResetMocks(); + VbNvSet(VbApiKernelGetVnc(), VBNV_DEV_BOOT_LEGACY, 1); + mock_keypress[0] = 0x0c; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Ctrl+L nv legacy"); + TEST_EQ(vbexlegacy_called, 1, " try legacy"); + + /* Ctrl+U boots USB only if enabled */ + ResetMocks(); + mock_keypress[0] = 0x15; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Ctrl+U normal"); + + /* Ctrl+U enabled, with good USB boot */ + ResetMocks(); + VbNvSet(VbApiKernelGetVnc(), VBNV_DEV_BOOT_USB, 1); + mock_keypress[0] = 0x15; + vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 0, "Ctrl+U USB"); + + /* Ctrl+U enabled via GBB */ + ResetMocks(); + gbb.flags |= GBB_FLAG_FORCE_DEV_BOOT_USB; + mock_keypress[0] = 0x15; + vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 0, "Ctrl+U force USB"); + + /* If no USB, eventually times out and tries fixed disk */ + ResetMocks(); + VbNvSet(VbApiKernelGetVnc(), VBNV_DEV_BOOT_USB, 1); + mock_keypress[0] = 0x15; + TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Ctrl+U enabled"); + TEST_EQ(vbexlegacy_called, 0, " not legacy"); + VbNvGet(VbApiKernelGetVnc(), VBNV_RECOVERY_REQUEST, &u); + TEST_EQ(u, 0, " recovery reason"); + TEST_EQ(audio_looping_calls_left, 0, " used up audio"); + + printf("...done.\n"); +} + +static void VbBootRecTest(void) +{ + uint32_t u; + + printf("Testing VbBootRecovery()...\n"); + + /* Shutdown requested in loop */ + ResetMocks(); + shutdown_request_calls_left = 10; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Shutdown requested"); + VbNvGet(VbApiKernelGetVnc(), VBNV_RECOVERY_REQUEST, &u); + TEST_EQ(u, 0, " recovery reason"); + TEST_EQ(screens_displayed[0], VB_SCREEN_BLANK, + " blank screen"); + TEST_EQ(screens_displayed[1], VB_SCREEN_RECOVERY_NO_GOOD, + " no good screen"); + + /* Disk inserted after start */ + ResetMocks(); + vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE; + TEST_EQ(VbBootRecovery(&cparams, &lkp), 0, "Good"); + + /* No disk inserted */ + ResetMocks(); + vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; + shutdown_request_calls_left = 10; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Bad disk"); + TEST_EQ(screens_displayed[0], VB_SCREEN_BLANK, + " blank screen"); + TEST_EQ(screens_displayed[1], VB_SCREEN_RECOVERY_INSERT, + " insert screen"); + + /* Remove disks */ + ResetMocks(); + shutdown_request_calls_left = 100; + mock_num_disks[0] = 1; + mock_num_disks[1] = 1; + vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Remove"); + TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_REMOVE, + " remove screen"); + TEST_EQ(screens_displayed[1], VB_SCREEN_RECOVERY_REMOVE, + " remove screen"); + TEST_EQ(screens_displayed[2], VB_SCREEN_BLANK, + " blank screen"); + TEST_EQ(screens_displayed[3], VB_SCREEN_RECOVERY_INSERT, + " insert screen"); + + /* No removal if dev switch is on */ + ResetMocks(); + shutdown_request_calls_left = 100; + mock_num_disks[0] = 1; + mock_num_disks[1] = 1; + shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; + vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "No remove in dev"); + TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, + " insert screen"); + + /* No removal if recovery button physically pressed */ + ResetMocks(); + shutdown_request_calls_left = 100; + mock_num_disks[0] = 1; + mock_num_disks[1] = 1; + shared->flags |= VBSD_BOOT_REC_SWITCH_ON; + vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "No remove in rec"); + TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, + " insert screen"); + + /* Bad disk count doesn't require removal */ + ResetMocks(); + mock_num_disks[0] = -1; + vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; + shutdown_request_calls_left = 10; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Bad disk count"); + TEST_EQ(screens_displayed[0], VB_SCREEN_BLANK, + " blank screen"); + TEST_EQ(screens_displayed[1], VB_SCREEN_RECOVERY_INSERT, + " insert screen"); + + /* Ctrl+D ignored for many reasons... */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_REC_SWITCH_ON; + shutdown_request_calls_left = 100; + mock_keypress[0] = 0x04; + trust_ec = 0; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Ctrl+D ignored if EC not trusted"); + TEST_EQ(virtdev_set, 0, " virtual dev mode off"); + TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, + " todev screen"); + + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_REC_SWITCH_ON | + VBSD_BOOT_DEV_SWITCH_ON; + trust_ec = 1; + shutdown_request_calls_left = 100; + mock_keypress[0] = 0x04; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Ctrl+D ignored if already in dev mode"); + TEST_EQ(virtdev_set, 0, " virtual dev mode off"); + TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, + " todev screen"); + + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH; + trust_ec = 1; + shutdown_request_calls_left = 100; + mock_keypress[0] = 0x04; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Ctrl+D ignored if recovery not manually triggered"); + TEST_EQ(virtdev_set, 0, " virtual dev mode off"); + TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, + " todev screen"); + + ResetMocks(); + shared->flags = VBSD_BOOT_REC_SWITCH_ON; + trust_ec = 1; + shutdown_request_calls_left = 100; + mock_keypress[0] = 0x04; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Ctrl+D ignored if no virtual dev switch"); + TEST_EQ(virtdev_set, 0, " virtual dev mode off"); + TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, + " todev screen"); + + /* Ctrl+D then space means don't enable */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_REC_SWITCH_ON; + shutdown_request_calls_left = 100; + vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; + trust_ec = 1; + mock_keypress[0] = 0x04; + mock_keypress[1] = ' '; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED, + "Ctrl+D todev abort"); + TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, + " insert screen"); + TEST_EQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, + " todev screen"); + TEST_EQ(screens_displayed[2], VB_SCREEN_RECOVERY_INSERT, + " insert screen"); + TEST_EQ(virtdev_set, 0, " virtual dev mode off"); + + /* Ctrl+D then enter means enable */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_REC_SWITCH_ON; + shutdown_request_calls_left = 100; + vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; + trust_ec = 1; + mock_keypress[0] = 0x04; + mock_keypress[1] = '\r'; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_TPM_REBOOT_REQUIRED, + "Ctrl+D todev confirm"); + TEST_EQ(virtdev_set, 1, " virtual dev mode on"); + + /* Handle TPM error in enabling dev mode */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_REC_SWITCH_ON; + shutdown_request_calls_left = 100; + vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; + trust_ec = 1; + mock_keypress[0] = 0x04; + mock_keypress[1] = '\r'; + virtdev_retval = VBERROR_SIMULATED; + TEST_EQ(VbBootRecovery(&cparams, &lkp), VBERROR_TPM_SET_BOOT_MODE_STATE, + "Ctrl+D todev failure"); + + printf("...done.\n"); +} + + +int main(void) +{ + VbUserConfirmsTest(); + VbBootTest(); + VbBootDevTest(); + VbBootRecTest(); + + return gTestSuccess ? 0 : 255; +} diff --git a/tests/vboot_api_kernel3_tests.c b/tests/vboot_api_kernel3_tests.c new file mode 100644 index 00000000..836a48de --- /dev/null +++ b/tests/vboot_api_kernel3_tests.c @@ -0,0 +1,335 @@ +/* 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_api_kernel, part 3 - software sync + */ + +#include +#include + +#include "gbb_header.h" +#include "host_common.h" +#include "load_kernel_fw.h" +#include "rollback_index.h" +#include "test_common.h" +#include "vboot_audio.h" +#include "vboot_common.h" +#include "vboot_kernel.h" +#include "vboot_nvstorage.h" +#include "vboot_struct.h" + +/* Mock data */ +static VbCommonParams cparams; +static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; +static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; +static GoogleBinaryBlockHeader gbb; + +static int trust_ec; +static int mock_in_rw; +static VbError_t in_rw_retval; +static int protect_retval; +static int ec_protected; +static int run_retval; +static int ec_run_image; +static int update_retval; +static int ec_updated; +static int get_expected_retval; + +static uint8_t mock_ec_hash[32]; +static int mock_ec_hash_size; +static uint8_t want_ec_hash[32]; +static int want_ec_hash_size; +static uint8_t mock_sha[32]; + +static uint32_t screens_displayed[8]; +static uint32_t screens_count = 0; + +/* Reset mock data (for use before each test) */ +static void ResetMocks(void) +{ + Memset(&cparams, 0, sizeof(cparams)); + cparams.shared_data_size = sizeof(shared_data); + cparams.shared_data_blob = shared_data; + cparams.gbb_data = &gbb; + + Memset(&gbb, 0, sizeof(gbb)); + gbb.major_version = GBB_MAJOR_VER; + gbb.minor_version = GBB_MINOR_VER; + gbb.flags = 0; + + /* + * Only the outermost vboot_api_kernel call sets vboot_api_kernel's + * vnc. So clear it here too. + */ + Memset(VbApiKernelGetVnc(), 0, sizeof(VbNvContext)); + VbNvSetup(VbApiKernelGetVnc()); + VbNvTeardown(VbApiKernelGetVnc()); /* So CRC gets generated */ + + Memset(&shared_data, 0, sizeof(shared_data)); + VbSharedDataInit(shared, sizeof(shared_data)); + + trust_ec = 0; + mock_in_rw = 0; + ec_protected = 0; + ec_run_image = -1; /* 0 = RO, 1 = RW */ + ec_updated = 0; + in_rw_retval = VBERROR_SUCCESS; + protect_retval = VBERROR_SUCCESS; + update_retval = VBERROR_SUCCESS; + run_retval = VBERROR_SUCCESS; + get_expected_retval = VBERROR_SUCCESS; + + Memset(mock_ec_hash, 0, sizeof(mock_ec_hash)); + mock_ec_hash[0] = 42; + mock_ec_hash_size = sizeof(mock_ec_hash); + + Memset(want_ec_hash, 0, sizeof(want_ec_hash)); + want_ec_hash[0] = 42; + want_ec_hash_size = sizeof(want_ec_hash); + + Memset(mock_sha, 0, sizeof(want_ec_hash)); + mock_sha[0] = 42; + + // TODO: ensure these are actually needed + + Memset(screens_displayed, 0, sizeof(screens_displayed)); + screens_count = 0; +} + +/* Mock functions */ + +int VbExTrustEC(void) +{ + return trust_ec; +} + +VbError_t VbExEcRunningRW(int *in_rw) +{ + *in_rw = mock_in_rw; + return in_rw_retval; +} + +VbError_t VbExEcProtectRW(void) +{ + ec_protected = 1; + return protect_retval; +} + +VbError_t VbExEcStayInRO(void) +{ + ec_run_image = 0; + return run_retval; +} + +VbError_t VbExEcJumpToRW(void) +{ + ec_run_image = 1; + return run_retval; +} + +VbError_t VbExEcHashRW(const uint8_t **hash, int *hash_size) +{ + *hash = mock_ec_hash; + *hash_size = mock_ec_hash_size; + return mock_ec_hash_size ? VBERROR_SUCCESS : VBERROR_SIMULATED; +} + +VbError_t VbExEcGetExpectedRW(enum VbSelectFirmware_t select, + const uint8_t **image, int *image_size) +{ + static uint8_t fake_image[64] = {5, 6, 7, 8}; + *image = fake_image; + *image_size = sizeof(fake_image); + return get_expected_retval; +} + +VbError_t VbExEcGetExpectedRWHash(enum VbSelectFirmware_t select, + const uint8_t **hash, int *hash_size) +{ + *hash = want_ec_hash; + *hash_size = want_ec_hash_size; + + if (want_ec_hash_size == -1) + return VBERROR_EC_GET_EXPECTED_HASH_FROM_IMAGE; + else + return want_ec_hash_size ? VBERROR_SUCCESS : VBERROR_SIMULATED; +} + +uint8_t *internal_SHA256(const uint8_t *data, uint64_t len, uint8_t *digest) +{ + Memcpy(digest, mock_sha, sizeof(mock_sha)); + return digest; +} + +VbError_t VbExEcUpdateRW(const uint8_t *image, int image_size) +{ + ec_updated = 1; + return update_retval; +} + +VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, int force, + VbNvContext *vncptr) +{ + if (screens_count < ARRAY_SIZE(screens_displayed)) + screens_displayed[screens_count++] = screen; + + return VBERROR_SUCCESS; +} + +static void test_ssync(VbError_t retval, int recovery_reason, const char *desc) +{ + uint32_t u; + + TEST_EQ(VbEcSoftwareSync(&cparams), retval, desc); + VbNvGet(VbApiKernelGetVnc(), VBNV_RECOVERY_REQUEST, &u); + TEST_EQ(u, recovery_reason, " recovery reason"); +} + +/* Tests */ + +static void VbSoftwareSyncTest(void) +{ + /* Recovery cases */ + ResetMocks(); + shared->recovery_reason = 123; + test_ssync(0, 0, "In recovery, EC-RO"); + TEST_EQ(ec_protected, 0, " ec protected"); + + ResetMocks(); + shared->recovery_reason = 123; + mock_in_rw = 1; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + 123, "Recovery needs EC-RO"); + + /* AP-RO cases */ + ResetMocks(); + in_rw_retval = VBERROR_SIMULATED; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + VBNV_RECOVERY_EC_UNKNOWN_IMAGE, "Unknown EC image"); + + ResetMocks(); + shared->flags |= VBSD_LF_USE_RO_NORMAL; + mock_in_rw = 1; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + 0, "AP-RO needs EC-RO"); + + ResetMocks(); + shared->flags |= VBSD_LF_USE_RO_NORMAL; + test_ssync(0, 0, "AP-RO, EC-RO"); + TEST_EQ(ec_protected, 1, " ec protected"); + TEST_EQ(ec_run_image, 0, " ec run image"); + + ResetMocks(); + shared->flags |= VBSD_LF_USE_RO_NORMAL; + run_retval = VBERROR_SIMULATED; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + VBNV_RECOVERY_EC_SOFTWARE_SYNC, "Stay in RO fail"); + + ResetMocks(); + shared->flags |= VBSD_LF_USE_RO_NORMAL; + protect_retval = VBERROR_SIMULATED; + test_ssync(VBERROR_SIMULATED, + VBNV_RECOVERY_EC_PROTECT, "Protect error"); + + /* Calculate hashes */ + ResetMocks(); + mock_ec_hash_size = 0; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + VBNV_RECOVERY_EC_HASH_FAILED, "Bad EC hash"); + + ResetMocks(); + mock_ec_hash_size = 16; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + VBNV_RECOVERY_EC_HASH_SIZE, "Bad EC hash size"); + + ResetMocks(); + want_ec_hash_size = 0; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + VBNV_RECOVERY_EC_EXPECTED_HASH, "Bad precalculated hash"); + + ResetMocks(); + want_ec_hash_size = 16; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + VBNV_RECOVERY_EC_EXPECTED_HASH, + "Bad precalculated hash size"); + + ResetMocks(); + mock_in_rw = 1; + want_ec_hash_size = -1; + test_ssync(0, 0, "No precomputed hash"); + + ResetMocks(); + want_ec_hash_size = -1; + get_expected_retval = VBERROR_SIMULATED; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + VBNV_RECOVERY_EC_EXPECTED_IMAGE, "Can't fetch image"); + + /* Updates required */ + ResetMocks(); + mock_in_rw = 1; + want_ec_hash[0]++; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + VBNV_RECOVERY_EC_HASH_MISMATCH, + "Precalculated hash mismatch"); + + ResetMocks(); + mock_in_rw = 1; + mock_ec_hash[0]++; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + 0, "Pending update needs reboot"); + + ResetMocks(); + mock_ec_hash[0]++; + test_ssync(0, 0, "Update without reboot"); + TEST_EQ(ec_protected, 1, " ec protected"); + TEST_EQ(ec_run_image, 1, " ec run image"); + TEST_EQ(ec_updated, 1, " ec updated"); + + ResetMocks(); + mock_ec_hash[0]++; + update_retval = VBERROR_EC_REBOOT_TO_RO_REQUIRED; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + 0, "Reboot after update"); + TEST_EQ(ec_updated, 1, " ec updated"); + + ResetMocks(); + mock_ec_hash[0]++; + update_retval = VBERROR_SIMULATED; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + VBNV_RECOVERY_EC_UPDATE, "Update failed"); + + ResetMocks(); + mock_ec_hash[0]++; + shared->flags |= VBSD_EC_SLOW_UPDATE; + test_ssync(0, 0, "Slow update"); + TEST_EQ(screens_displayed[0], VB_SCREEN_WAIT, " wait screen"); + + /* RW cases, no update */ + ResetMocks(); + mock_in_rw = 1; + test_ssync(0, 0, "AP-RW, EC-RW"); + + ResetMocks(); + test_ssync(0, 0, "AP-RW, EC-RO -> EC-RW"); + TEST_EQ(ec_protected, 1, " ec protected"); + TEST_EQ(ec_run_image, 1, " ec run image"); + TEST_EQ(ec_updated, 0, " ec updated"); + + ResetMocks(); + run_retval = VBERROR_SIMULATED; + test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, + VBNV_RECOVERY_EC_JUMP_RW, "Jump to RW fail"); + + ResetMocks(); + protect_retval = VBERROR_SIMULATED; + test_ssync(VBERROR_SIMULATED, + VBNV_RECOVERY_EC_PROTECT, "Protect error"); +} + +int main(void) +{ + VbSoftwareSyncTest(); + + return gTestSuccess ? 0 : 255; +} diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c new file mode 100644 index 00000000..414279e5 --- /dev/null +++ b/tests/vboot_api_kernel4_tests.c @@ -0,0 +1,241 @@ +/* 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_api_kernel, part 4 - select and load kernel + */ + +#include +#include + +#include "gbb_header.h" +#include "host_common.h" +#include "load_kernel_fw.h" +#include "rollback_index.h" +#include "test_common.h" +#include "vboot_audio.h" +#include "vboot_common.h" +#include "vboot_kernel.h" +#include "vboot_nvstorage.h" +#include "vboot_struct.h" + +/* Mock data */ +static VbCommonParams cparams; +static VbSelectAndLoadKernelParams kparams; +static VbNvContext vnc; +static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; +static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; +static GoogleBinaryBlockHeader gbb; + +static int ecsync_retval; +static uint32_t rkr_version; +static uint32_t new_version; +static int rkr_retval, rkw_retval, rkl_retval; +static VbError_t vbboot_retval; + +/* Reset mock data (for use before each test) */ +static void ResetMocks(void) +{ + Memset(&cparams, 0, sizeof(cparams)); + cparams.shared_data_size = sizeof(shared_data); + cparams.shared_data_blob = shared_data; + cparams.gbb_data = &gbb; + + Memset(&kparams, 0, sizeof(kparams)); + + Memset(&gbb, 0, sizeof(gbb)); + gbb.major_version = GBB_MAJOR_VER; + gbb.minor_version = GBB_MINOR_VER; + gbb.flags = 0; + + Memset(&vnc, 0, sizeof(vnc)); + VbNvSetup(&vnc); + VbNvTeardown(&vnc); /* So CRC gets generated */ + + Memset(&shared_data, 0, sizeof(shared_data)); + VbSharedDataInit(shared, sizeof(shared_data)); + + ecsync_retval = VBERROR_SUCCESS; + rkr_version = new_version = 0x10002; + rkr_retval = rkw_retval = rkl_retval = VBERROR_SUCCESS; + vbboot_retval = VBERROR_SUCCESS; +} + +/* Mock functions */ + +VbError_t VbExNvStorageRead(uint8_t *buf) +{ + Memcpy(buf, vnc.raw, sizeof(vnc.raw)); + return VBERROR_SUCCESS; +} + +VbError_t VbExNvStorageWrite(const uint8_t *buf) +{ + Memcpy(vnc.raw, buf, sizeof(vnc.raw)); + return VBERROR_SUCCESS; +} + +VbError_t VbEcSoftwareSync(VbCommonParams *cparams) +{ + return ecsync_retval; +} + +uint32_t RollbackKernelRead(uint32_t *version) +{ + *version = rkr_version; + return rkr_retval; +} + +uint32_t RollbackKernelWrite(uint32_t version) +{ + TEST_EQ(version, new_version, "RollbackKernelWrite new version"); + rkr_version = version; + return rkw_retval; +} + +uint32_t RollbackKernelLock(void) +{ + return rkl_retval; +} + +VbError_t VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p) +{ + shared->kernel_version_tpm = new_version; + + if (vbboot_retval == -1) + return VBERROR_SIMULATED; + + return vbboot_retval; +} + +VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p) +{ + shared->kernel_version_tpm = new_version; + + if (vbboot_retval == -2) + return VBERROR_SIMULATED; + + return vbboot_retval; +} + +VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p) +{ + shared->kernel_version_tpm = new_version; + + if (vbboot_retval == -3) + return VBERROR_SIMULATED; + + return vbboot_retval; +} + +static void test_slk(VbError_t retval, int recovery_reason, const char *desc) +{ + uint32_t u; + + TEST_EQ(VbSelectAndLoadKernel(&cparams, &kparams), retval, desc); + VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u); + TEST_EQ(u, recovery_reason, " recovery reason"); +} + +/* Tests */ + +static void VbSlkTest(void) +{ + ResetMocks(); + test_slk(0, 0, "Normal"); + + /* Software sync */ + ResetMocks(); + shared->flags |= VBSD_EC_SOFTWARE_SYNC; + ecsync_retval = VBERROR_SIMULATED; + test_slk(VBERROR_SIMULATED, 0, "EC sync bad"); + + ResetMocks(); + ecsync_retval = VBERROR_SIMULATED; + test_slk(0, 0, "EC sync not done"); + + /* Rollback kernel version */ + ResetMocks(); + rkr_retval = 123; + test_slk(VBERROR_TPM_READ_KERNEL, + VBNV_RECOVERY_RW_TPM_R_ERROR, "Read kernel rollback"); + + ResetMocks(); + new_version = 0x20003; + test_slk(0, 0, "Roll forward"); + TEST_EQ(rkr_version, 0x20003, " version"); + + ResetMocks(); + new_version = 0x20003; + shared->flags |= VBSD_FWB_TRIED; + shared->firmware_index = 1; + test_slk(0, 0, "Don't roll forward during try B"); + TEST_EQ(rkr_version, 0x10002, " version"); + + ResetMocks(); + vbboot_retval = VBERROR_INVALID_KERNEL_FOUND; + VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123); + VbNvTeardown(&vnc); + shared->flags |= VBSD_FWB_TRIED; + shared->firmware_index = 1; + test_slk(VBERROR_INVALID_KERNEL_FOUND, + 0, "Don't go to recovery if try b fails to find a kernel"); + + ResetMocks(); + new_version = 0x20003; + rkw_retval = 123; + test_slk(VBERROR_TPM_WRITE_KERNEL, + VBNV_RECOVERY_RW_TPM_W_ERROR, "Write kernel rollback"); + + ResetMocks(); + rkl_retval = 123; + test_slk(VBERROR_TPM_LOCK_KERNEL, + VBNV_RECOVERY_RW_TPM_L_ERROR, "Lock kernel rollback"); + + /* Boot normal */ + ResetMocks(); + vbboot_retval = -1; + test_slk(VBERROR_SIMULATED, 0, "Normal boot bad"); + + /* Boot dev */ + ResetMocks(); + shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; + vbboot_retval = -2; + test_slk(VBERROR_SIMULATED, 0, "Dev boot bad"); + + ResetMocks(); + shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; + new_version = 0x20003; + test_slk(0, 0, "Dev doesn't roll forward"); + TEST_EQ(rkr_version, 0x10002, " version"); + + /* Boot recovery */ + ResetMocks(); + shared->recovery_reason = 123; + vbboot_retval = -3; + test_slk(VBERROR_SIMULATED, 0, "Recovery boot bad"); + + ResetMocks(); + shared->recovery_reason = 123; + new_version = 0x20003; + test_slk(0, 0, "Recovery doesn't roll forward"); + TEST_EQ(rkr_version, 0x10002, " version"); + + ResetMocks(); + shared->recovery_reason = 123; + rkr_retval = rkw_retval = rkl_retval = VBERROR_SIMULATED; + test_slk(0, 0, "Recovery ignore TPM errors"); + + + + // todo: rkr/w/l fail ignored if recovery + + +} + +int main(void) +{ + VbSlkTest(); + + return gTestSuccess ? 0 : 255; +} diff --git a/tests/vboot_api_kernel_tests.c b/tests/vboot_api_kernel_tests.c index 9435fa10..8c04814e 100644 --- a/tests/vboot_api_kernel_tests.c +++ b/tests/vboot_api_kernel_tests.c @@ -15,7 +15,7 @@ #include "test_common.h" #include "utility.h" #include "vboot_api.h" - +#include "vboot_kernel.h" #define MAX_TEST_DISKS 10 #define DEFAULT_COUNT -1 @@ -286,10 +286,6 @@ int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value) /****************************************************************************/ -/* 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; -- cgit v1.2.1