summaryrefslogtreecommitdiff
path: root/tests/vboot_ui_legacy_clamshell_tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/vboot_ui_legacy_clamshell_tests.c')
-rw-r--r--tests/vboot_ui_legacy_clamshell_tests.c1641
1 files changed, 1641 insertions, 0 deletions
diff --git a/tests/vboot_ui_legacy_clamshell_tests.c b/tests/vboot_ui_legacy_clamshell_tests.c
new file mode 100644
index 00000000..5d973e66
--- /dev/null
+++ b/tests/vboot_ui_legacy_clamshell_tests.c
@@ -0,0 +1,1641 @@
+/* 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 "2common.h"
+#include "2misc.h"
+#include "2nvstorage.h"
+#include "2secdata.h"
+#include "2secdata_struct.h"
+#include "host_common.h"
+#include "load_kernel_fw.h"
+#include "test_common.h"
+#include "tss_constants.h"
+#include "vboot_audio.h"
+#include "vboot_kernel.h"
+#include "vboot_struct.h"
+#include "vboot_test.h"
+#include "vboot_ui_legacy.h"
+
+/* Mock data */
+static LoadKernelParams lkp;
+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_gbb_header gbb;
+static struct vb2_secdata_fwmp *fwmp;
+
+static int audio_looping_calls_left;
+static uint32_t vbtlk_retval;
+static int vbtlk_expect_fixed;
+static int vbtlk_expect_removable;
+static int vbexlegacy_called;
+static enum VbAltFwIndex_t altfw_num;
+static uint64_t current_ticks;
+static int trust_ec;
+static int virtdev_set;
+static uint32_t virtdev_fail;
+static uint32_t mock_keypress[16];
+static uint32_t mock_keyflags[8];
+static uint32_t mock_keypress_count;
+
+#define GPIO_SHUTDOWN 1
+#define GPIO_PRESENCE 2
+#define GPIO_LID_CLOSED 4
+typedef struct GpioState {
+ uint32_t gpio_flags;
+ uint32_t count;
+} GpioState;
+struct GpioState mock_gpio[8];
+static uint32_t mock_gpio_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;
+static int tpm_set_mode_called;
+static enum vb2_tpm_mode tpm_mode;
+
+/* Extra character to guarantee null termination. */
+static char set_vendor_data[VENDOR_DATA_LENGTH + 2];
+static int set_vendor_data_called;
+
+/*
+ * Mocks the assertion of 1 or more gpios in |gpio_flags| for 100 ticks after
+ * an optional |ticks| delay.
+ */
+static void MockGpioAfter(uint32_t ticks, uint32_t gpio_flags)
+{
+ uint32_t index = 0;
+ if (ticks > 0)
+ mock_gpio[index++].count = ticks - 1;
+
+ mock_gpio[index].gpio_flags = gpio_flags;
+ mock_gpio[index].count = 100;
+}
+
+/* Reset mock data (for use before each test) */
+static void ResetMocks(void)
+{
+ vb2_reset_power_button();
+
+ memset(&lkp, 0, sizeof(lkp));
+
+ TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
+ "vb2api_init failed");
+ vb2_nv_init(ctx);
+
+ sd = vb2_get_sd(ctx);
+ sd->flags |= VB2_SD_FLAG_DISPLAY_AVAILABLE;
+
+ /* 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;
+
+ memset(&gbb, 0, sizeof(gbb));
+
+ audio_looping_calls_left = 30;
+ vbtlk_retval = VB2_ERROR_MOCK;
+ vbtlk_expect_fixed = 0;
+ vbtlk_expect_removable = 0;
+ vbexlegacy_called = 0;
+ altfw_num = -100;
+ current_ticks = 0;
+ trust_ec = 0;
+ virtdev_set = 0;
+ virtdev_fail = 0;
+ set_vendor_data_called = 0;
+
+ memset(screens_displayed, 0, sizeof(screens_displayed));
+ screens_count = 0;
+
+ memset(mock_keypress, 0, sizeof(mock_keypress));
+ memset(mock_keyflags, 0, sizeof(mock_keyflags));
+ mock_keypress_count = 0;
+ memset(mock_gpio, 0, sizeof(mock_gpio));
+ mock_gpio_count = 0;
+ memset(mock_num_disks, 0, sizeof(mock_num_disks));
+ mock_num_disks_count = 0;
+
+ tpm_set_mode_called = 0;
+ tpm_mode = VB2_TPM_MODE_ENABLED_TENTATIVE;
+}
+
+/* Mock functions */
+
+struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
+{
+ return &gbb;
+}
+
+uint32_t VbExIsShutdownRequested(void)
+{
+ uint32_t result = 0;
+ if (mock_gpio_count >= ARRAY_SIZE(mock_gpio))
+ return 0;
+ if (mock_gpio[mock_gpio_count].gpio_flags & GPIO_SHUTDOWN)
+ result |= VB_SHUTDOWN_REQUEST_POWER_BUTTON;
+ if (mock_gpio[mock_gpio_count].gpio_flags & GPIO_LID_CLOSED)
+ result |= VB_SHUTDOWN_REQUEST_LID_CLOSED;
+ if (mock_gpio[mock_gpio_count].count > 0) {
+ --mock_gpio[mock_gpio_count].count;
+ } else {
+ ++mock_gpio_count;
+ }
+ return result;
+}
+
+uint32_t VbExKeyboardRead(void)
+{
+ return VbExKeyboardReadWithFlags(NULL);
+}
+
+uint32_t VbExKeyboardReadWithFlags(uint32_t *key_flags)
+{
+ if (mock_keypress_count < ARRAY_SIZE(mock_keypress)) {
+ if (key_flags != NULL &&
+ mock_keypress_count < ARRAY_SIZE(mock_keyflags))
+ *key_flags = mock_keyflags[mock_keypress_count];
+ return mock_keypress[mock_keypress_count++];
+ } else
+ return 0;
+}
+
+int vb2ex_physical_presence_pressed(void)
+{
+ uint32_t result = 0;
+
+ if (mock_gpio_count >= ARRAY_SIZE(mock_gpio))
+ return 0;
+
+ if ((mock_gpio[mock_gpio_count].gpio_flags & GPIO_PRESENCE))
+ result = 1;
+
+ if (mock_gpio[mock_gpio_count].count > 0)
+ --mock_gpio[mock_gpio_count].count;
+ else
+ ++mock_gpio_count;
+
+ return result;
+}
+
+vb2_error_t VbExLegacy(enum VbAltFwIndex_t _altfw_num)
+{
+ vbexlegacy_called++;
+ altfw_num = _altfw_num;
+
+ /* VbExLegacy() can only return failure, or not return at all. */
+ return VB2_ERROR_UNKNOWN;
+}
+
+void VbExSleepMs(uint32_t msec)
+{
+ current_ticks += (uint64_t)msec * VB_USEC_PER_MSEC;
+}
+
+uint64_t VbExGetTimer(void)
+{
+ return current_ticks;
+}
+
+vb2_error_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 VB2_ERROR_MOCK;
+ else
+ *count = mock_num_disks[mock_num_disks_count++];
+ } else {
+ *count = 0;
+ }
+ return VB2_SUCCESS;
+}
+
+vb2_error_t VbExDiskFreeInfo(VbDiskInfo *infos,
+ VbExDiskHandle_t preserve_handle)
+{
+ return VB2_SUCCESS;
+}
+
+int vb2ex_ec_trusted(void)
+{
+ return trust_ec;
+}
+
+int vb2_audio_looping(void)
+{
+ if (audio_looping_calls_left == 0)
+ return 0;
+ else if (audio_looping_calls_left > 0)
+ audio_looping_calls_left--;
+
+ return 1;
+}
+
+vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t get_info_flags)
+{
+ /*
+ * TODO: Currently we don't have a good way of testing for an ordered
+ * sequence of VB_DISK_FLAG_FIXED and then VB_DISK_FLAG_REMOVABLE. If
+ * both are set, then just assume success.
+ */
+ if (vbtlk_expect_fixed && vbtlk_expect_removable)
+ return vbtlk_retval;
+
+ TEST_EQ(!!vbtlk_expect_fixed,
+ !!(get_info_flags & VB_DISK_FLAG_FIXED),
+ " VbTryLoadKernel unexpected fixed disk call");
+ TEST_EQ(!!vbtlk_expect_removable,
+ !!(get_info_flags & VB_DISK_FLAG_REMOVABLE),
+ " VbTryLoadKernel unexpected removable disk call");
+
+ return vbtlk_retval;
+}
+
+vb2_error_t VbDisplayScreen(struct vb2_context *c, uint32_t screen, int force,
+ const VbScreenData *data)
+{
+ if (screens_count < ARRAY_SIZE(screens_displayed))
+ screens_displayed[screens_count++] = screen;
+
+ return VB2_SUCCESS;
+}
+
+void vb2_enable_developer_mode(struct vb2_context *c)
+{
+ VB2_ASSERT(!virtdev_fail);
+ virtdev_set = 1;
+}
+
+vb2_error_t VbExSetVendorData(const char *vendor_data_value)
+{
+ set_vendor_data_called = 1;
+ /*
+ * set_vendor_data is a global variable, so it is automatically
+ * initialized to zero, and so the -1 will ensure the string is null
+ * terminated.
+ */
+ strncpy(set_vendor_data, vendor_data_value, sizeof(set_vendor_data) - 1);
+
+ return VB2_SUCCESS;
+}
+
+vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val)
+{
+ tpm_set_mode_called = 1;
+
+ /* Fail if the TPM is already disabled. */
+ if (tpm_mode == VB2_TPM_MODE_DISABLED)
+ return VB2_ERROR_UNKNOWN;
+
+ tpm_mode = mode_val;
+ return VB2_SUCCESS;
+}
+
+/* Tests */
+
+/*
+ * Helper function to test VbUserConfirms against a sequence of gpio events.
+ * caller specifies a sequence of gpio events and the expected confirm vs.
+ * reboot result.
+ *
+ * Non-asserted gpios are used for 5 events, then 'first' for 5 events,
+ * 'second' for 5 events, and 'third' for 5 events.
+ * Typically most tests want 5 events of each type (so they'll specify 0 for
+ * 'first' and use 'second' through 'fourth'), but a few tests want the
+ * shutdown event to be seen once.
+ */
+static void VbUserConfirmsTestGpio(uint32_t first, uint32_t second,
+ uint32_t third, uint32_t confirm,
+ const char *msg)
+{
+ ResetMocks();
+ mock_gpio[0].gpio_flags = 0;
+ mock_gpio[0].count = 4;
+ mock_gpio[1].gpio_flags = first;
+ mock_gpio[1].count = 4;
+ mock_gpio[2].gpio_flags = second;
+ mock_gpio[2].count = 4;
+ mock_gpio[3].gpio_flags = third;
+ mock_gpio[3].count = 4;
+ if (confirm) {
+ TEST_EQ(VbUserConfirms(ctx,
+ VB_CONFIRM_SPACE_MEANS_NO |
+ VB_CONFIRM_MUST_TRUST_KEYBOARD),
+ 1, msg);
+ } else {
+ TEST_EQ(VbUserConfirms(ctx,
+ VB_CONFIRM_SPACE_MEANS_NO |
+ VB_CONFIRM_MUST_TRUST_KEYBOARD),
+ -1, msg);
+ }
+}
+
+static void VbUserConfirmsTest(void)
+{
+ VB2_DEBUG("Testing VbUserConfirms()...\n");
+
+ ResetMocks();
+ MockGpioAfter(1, GPIO_SHUTDOWN);
+ TEST_EQ(VbUserConfirms(ctx, 0), -1, "Shutdown requested");
+
+ ResetMocks();
+ mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS;
+ TEST_EQ(VbUserConfirms(ctx, 0), -1, "Shutdown requested");
+
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_ENTER;
+ TEST_EQ(VbUserConfirms(ctx, 0), 1, "Enter");
+
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_ESC;
+ TEST_EQ(VbUserConfirms(ctx, 0), 0, "Esc");
+
+ ResetMocks();
+ mock_keypress[0] = ' ';
+ MockGpioAfter(1, GPIO_SHUTDOWN);
+ TEST_EQ(VbUserConfirms(ctx, VB_CONFIRM_SPACE_MEANS_NO), 0,
+ "Space means no");
+
+ ResetMocks();
+ mock_keypress[0] = ' ';
+ MockGpioAfter(1, GPIO_SHUTDOWN);
+ TEST_EQ(VbUserConfirms(ctx, 0), -1, "Space ignored");
+
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_ENTER;
+ mock_keyflags[0] = VB_KEY_FLAG_TRUSTED_KEYBOARD;
+ TEST_EQ(VbUserConfirms(ctx, VB_CONFIRM_MUST_TRUST_KEYBOARD),
+ 1, "Enter with trusted keyboard");
+
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_ENTER; /* untrusted */
+ mock_keypress[1] = ' ';
+ TEST_EQ(VbUserConfirms(ctx,
+ VB_CONFIRM_SPACE_MEANS_NO |
+ VB_CONFIRM_MUST_TRUST_KEYBOARD),
+ 0, "Untrusted keyboard");
+
+ ResetMocks();
+ MockGpioAfter(0, GPIO_PRESENCE);
+ TEST_EQ(VbUserConfirms(ctx,
+ VB_CONFIRM_SPACE_MEANS_NO |
+ VB_CONFIRM_MUST_TRUST_KEYBOARD),
+ 1, "Presence button");
+
+ /*
+ * List of possiblities for shutdown and physical presence events that
+ * occur over time. Time advanced from left to right (where each
+ * represents the gpio[s] that are seen during a given iteration of
+ * the loop). The meaning of the characters:
+ *
+ * _ means no gpio
+ * s means shutdown gpio
+ * p means presence gpio
+ * B means both shutdown and presence gpio
+ *
+ * 1: ______ppp______ -> confirm
+ * 2: ______sss______ -> shutdown
+ * 3: ___pppsss______ -> confirm
+ * 4: ___sssppp______ -> shutdown
+ * 5: ___pppBBB______ -> confirm
+ * 6: ___pppBBBppp___ -> shutdown
+ * 7: ___pppBBBsss___ -> confirm
+ * 8: ___sssBBB______ -> confirm
+ * 9: ___sssBBBppp___ -> shutdown
+ * 10: ___sssBBBsss___ -> confirm
+ * 11: ______BBB______ -> confirm
+ * 12: ______BBBsss___ -> confirm
+ * 13: ______BBBppp___ -> shutdown
+ */
+
+ /* 1: presence means confirm */
+ VbUserConfirmsTestGpio(GPIO_PRESENCE, 0, 0, 1, "presence");
+
+ /* 2: shutdown means shutdown */
+ VbUserConfirmsTestGpio(GPIO_SHUTDOWN, 0, 0, 0, "shutdown");
+
+ /* 3: presence then shutdown means confirm */
+ VbUserConfirmsTestGpio(GPIO_PRESENCE, GPIO_SHUTDOWN, 0, 1,
+ "presence then shutdown");
+
+ /* 4: shutdown then presence means shutdown */
+ VbUserConfirmsTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE, 0, 0,
+ "shutdown then presence");
+
+ /* 5: presence then shutdown+presence then none mean confirm */
+ VbUserConfirmsTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN,
+ 0, 1, "presence, both, none");
+
+ /* 6: presence then shutdown+presence then presence means shutdown */
+ VbUserConfirmsTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN,
+ GPIO_PRESENCE, 0, "presence, both, presence");
+
+ /* 7: presence then shutdown+presence then shutdown means confirm */
+ VbUserConfirmsTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN,
+ GPIO_SHUTDOWN, 1, "presence, both, shutdown");
+
+ /* 8: shutdown then shutdown+presence then none means confirm */
+ VbUserConfirmsTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN,
+ 0, 1, "shutdown, both, none");
+
+ /* 9: shutdown then shutdown+presence then presence means shutdown */
+ VbUserConfirmsTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN,
+ GPIO_PRESENCE, 0, "shutdown, both, presence");
+
+ /* 10: shutdown then shutdown+presence then shutdown means confirm */
+ VbUserConfirmsTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN,
+ GPIO_SHUTDOWN, 1, "shutdown, both, shutdown");
+
+ /* 11: shutdown+presence then none means confirm */
+ VbUserConfirmsTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN, 0, 0, 1,
+ "both");
+
+ /* 12: shutdown+presence then shutdown means confirm */
+ VbUserConfirmsTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN,
+ GPIO_SHUTDOWN, 0, 1, "both, shutdown");
+
+ /* 13: shutdown+presence then presence means shutdown */
+ VbUserConfirmsTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN,
+ GPIO_PRESENCE, 0, 0, "both, presence");
+
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_ENTER;
+ mock_keypress[1] = 'y';
+ mock_keypress[2] = 'z';
+ mock_keypress[3] = ' ';
+ mock_gpio[0].gpio_flags = GPIO_PRESENCE;
+ mock_gpio[0].count = ~0;
+ TEST_EQ(VbUserConfirms(ctx,
+ VB_CONFIRM_SPACE_MEANS_NO |
+ VB_CONFIRM_MUST_TRUST_KEYBOARD),
+ 0, "Recovery button stuck");
+ VB2_DEBUG("...done.\n");
+}
+
+static void VbBootDevTest(void)
+{
+ int key;
+
+ VB2_DEBUG("Testing VbBootDeveloperLegacyClamshell()...\n");
+
+ /* Proceed after timeout */
+ ResetMocks();
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING,
+ " warning screen");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0,
+ " recovery reason");
+ TEST_EQ(audio_looping_calls_left, 0, " used up audio");
+
+ /* Proceed to legacy after timeout if GBB flag set */
+ ResetMocks();
+ gbb.flags |= VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY |
+ VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout");
+ TEST_EQ(vbexlegacy_called, 1, " try legacy");
+ TEST_EQ(altfw_num, 0, " check altfw_num");
+
+ /* Proceed to legacy after timeout if GBB flag set */
+ ResetMocks();
+ gbb.flags |= VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY |
+ VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout");
+ TEST_EQ(vbexlegacy_called, 1, " try legacy");
+ TEST_EQ(altfw_num, 0, " check altfw_num");
+
+ /* Proceed to legacy after timeout if boot legacy and default boot
+ legacy are set */
+ ResetMocks();
+ vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT,
+ VB2_DEV_DEFAULT_BOOT_LEGACY);
+ vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout");
+ TEST_EQ(vbexlegacy_called, 1, " try legacy");
+ TEST_EQ(altfw_num, 0, " check altfw_num");
+
+ /* Proceed to legacy boot mode only if enabled */
+ ResetMocks();
+ vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT,
+ VB2_DEV_DEFAULT_BOOT_LEGACY);
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+
+ /* Proceed to USB after timeout if boot USB and default boot
+ USB are set */
+ ResetMocks();
+ vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT,
+ VB2_DEV_DEFAULT_BOOT_USB);
+ vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 1);
+ vbtlk_retval = VB2_SUCCESS;
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), 0, "Ctrl+U USB");
+
+ /* Proceed to USB boot mode only if enabled */
+ ResetMocks();
+ vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT,
+ VB2_DEV_DEFAULT_BOOT_USB);
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout");
+
+ /* If no USB tries fixed disk */
+ ResetMocks();
+ vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 1);
+ vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT,
+ VB2_DEV_DEFAULT_BOOT_USB);
+ vbtlk_expect_fixed = 1;
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+U enabled");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+
+ /* Up arrow is uninteresting / passed to VbCheckDisplayKey() */
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_UP;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Up arrow");
+
+ /* Shutdown requested in loop */
+ ResetMocks();
+ mock_gpio[0].gpio_flags = 0;
+ mock_gpio[0].count = 2;
+ mock_gpio[1].gpio_flags = GPIO_SHUTDOWN;
+ mock_gpio[1].count = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Shutdown requested");
+ TEST_NEQ(audio_looping_calls_left, 0, " aborts audio");
+
+ /* Shutdown requested by keyboard in loop */
+ ResetMocks();
+ mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Shutdown requested by keyboard");
+
+ /* Space asks to disable virtual dev switch */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED;
+ mock_keypress[0] = ' ';
+ mock_keypress[1] = VB_KEY_ENTER;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "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");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1,
+ " disable dev request");
+
+ /* Space-space doesn't disable it */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED;
+ mock_keypress[0] = ' ';
+ mock_keypress[1] = ' ';
+ mock_keypress[2] = VB_KEY_ESC;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "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();
+ sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED;
+ mock_keypress[0] = VB_KEY_ENTER;
+ mock_keypress[1] = VB_KEY_ENTER;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Enter ignored");
+
+ /* Enter does if GBB flag set */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED;
+ gbb.flags |= VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM;
+ mock_keypress[0] = VB_KEY_ENTER;
+ mock_keypress[1] = VB_KEY_ENTER;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Enter = tonorm");
+
+ /* Tonorm ignored if GBB forces dev switch on */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED;
+ gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON;
+ mock_keypress[0] = ' ';
+ mock_keypress[1] = VB_KEY_ENTER;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Can't tonorm gbb-dev");
+
+ /* Shutdown requested at tonorm screen */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED;
+ mock_keypress[0] = ' ';
+ MockGpioAfter(3, GPIO_SHUTDOWN);
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "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");
+
+ /* Shutdown requested by keyboard at tonorm screen */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED;
+ mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Shutdown requested by keyboard at nonorm");
+
+ /* Ctrl+D dismisses warning */
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_CTRL('D');
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Ctrl+D");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0,
+ " recovery reason");
+ TEST_NEQ(audio_looping_calls_left, 0, " aborts audio");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+
+ /* Ctrl+D doesn't boot legacy even if GBB flag is set */
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_CTRL('D');
+ gbb.flags |= VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Ctrl+D");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+
+ /* Ctrl+L tries legacy boot mode only if enabled */
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_CTRL('L');
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+L normal");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+
+ /* Enter altfw menu and time out */
+ ResetMocks();
+ MockGpioAfter(1000, GPIO_SHUTDOWN);
+ gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
+ mock_keypress[0] = VB_KEY_CTRL('L');
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_SHUTDOWN,
+ "Ctrl+L force legacy");
+ TEST_EQ(vbexlegacy_called, 0, " try legacy");
+
+ /* Enter altfw menu and select firmware 0 */
+ ResetMocks();
+ gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
+ mock_keypress[0] = VB_KEY_CTRL('L');
+ mock_keypress[1] = '0';
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+L force legacy");
+ TEST_EQ(vbexlegacy_called, 1, " try legacy");
+ TEST_EQ(altfw_num, 0, " check altfw_num");
+
+ /* Enter altfw menu and then exit it */
+ ResetMocks();
+ vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
+ mock_keypress[0] = VB_KEY_CTRL('L');
+ mock_keypress[1] = VB_KEY_ESC;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+L nv legacy");
+ TEST_EQ(vbexlegacy_called, 0, " try legacy");
+
+ /* Enter altfw menu and select firmware 0 */
+ ResetMocks();
+ vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
+ mock_keypress[0] = VB_KEY_CTRL('L');
+ mock_keypress[1] = '0';
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+L nv legacy");
+ TEST_EQ(vbexlegacy_called, 1, " try legacy");
+ TEST_EQ(altfw_num, 0, " check altfw_num");
+
+ /* Enter altfw menu and select firmware 0 */
+ ResetMocks();
+ fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY;
+ mock_keypress[0] = VB_KEY_CTRL('L');
+ mock_keypress[1] = '0';
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+L fwmp legacy");
+ TEST_EQ(vbexlegacy_called, 1, " fwmp legacy");
+ TEST_EQ(altfw_num, 0, " check altfw_num");
+
+ /* Pressing 1-9 boots alternative firmware only if enabled */
+ for (key = '1'; key <= '9'; key++) {
+ ResetMocks();
+ mock_keypress[0] = key;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "'1' normal");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+
+ ResetMocks();
+ gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
+ mock_keypress[0] = key;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+L force legacy");
+ TEST_EQ(vbexlegacy_called, 1, " try legacy");
+ TEST_EQ(altfw_num, key - '0', " check altfw_num");
+
+ ResetMocks();
+ vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
+ mock_keypress[0] = key;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+L nv legacy");
+ TEST_EQ(vbexlegacy_called, 1, " try legacy");
+ TEST_EQ(altfw_num, key - '0', " check altfw_num");
+
+ ResetMocks();
+ fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY;
+ mock_keypress[0] = key;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+L fwmp legacy");
+ TEST_EQ(vbexlegacy_called, 1, " fwmp legacy");
+ TEST_EQ(altfw_num, key - '0', " check altfw_num");
+ }
+
+ /* Ctrl+U boots USB only if enabled */
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_CTRL('U');
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+U normal");
+
+ /* Ctrl+U enabled, with good USB boot */
+ ResetMocks();
+ vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 1);
+ mock_keypress[0] = VB_KEY_CTRL('U');
+ vbtlk_retval = VB2_SUCCESS;
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), 0, "Ctrl+U USB");
+
+ /* Ctrl+U enabled via GBB */
+ ResetMocks();
+ gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_USB;
+ mock_keypress[0] = VB_KEY_CTRL('U');
+ vbtlk_retval = VB2_SUCCESS;
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), 0, "Ctrl+U force USB");
+
+ /* Ctrl+U enabled via FWMP */
+ ResetMocks();
+ fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_USB;
+ mock_keypress[0] = VB_KEY_CTRL('U');
+ vbtlk_retval = VB2_SUCCESS;
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), 0, "Ctrl+U force USB");
+
+ /* If no USB, eventually times out and tries fixed disk */
+ ResetMocks();
+ vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 1);
+ mock_keypress[0] = VB_KEY_CTRL('U');
+ /* TODO: Currently the test suite has no way of specifying the order in
+ which the expected VbTryLoadKernel calls occur. */
+ vbtlk_expect_fixed = 1;
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Ctrl+U enabled");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0,
+ " recovery reason");
+ TEST_EQ(audio_looping_calls_left, 0, " used up audio");
+
+ /* If dev mode is disabled, goes to TONORM screen repeatedly */
+ ResetMocks();
+ fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT;
+ mock_keypress[0] = VB_KEY_ESC; /* Just causes TONORM again */
+ mock_keypress[1] = VB_KEY_ENTER;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "FWMP dev disabled");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM,
+ " tonorm 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");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1,
+ " disable dev request");
+
+ /* Shutdown requested when dev disabled */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED;
+ fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT;
+ MockGpioAfter(1, GPIO_SHUTDOWN);
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Shutdown requested when dev disabled");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM,
+ " tonorm screen");
+
+ /* Shutdown requested by keyboard when dev disabled */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED;
+ fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT;
+ mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Shutdown requested by keyboard when dev disabled");
+
+ VB2_DEBUG("...done.\n");
+}
+
+static void VbBootDevVendorDataTest(void)
+{
+ /* Enter set vendor data and reboot */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = '4';
+ mock_keypress[2] = '3';
+ mock_keypress[3] = '2';
+ mock_keypress[4] = '1';
+ mock_keypress[5] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[6] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Enter set vendor data, don't confirm, esc");
+ TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called");
+ TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct");
+
+ /* Enter set vendor data; don't confirm and esc */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = '4';
+ mock_keypress[2] = '3';
+ mock_keypress[3] = '2';
+ mock_keypress[4] = '1';
+ mock_keypress[5] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[6] = VB_KEY_RIGHT; /* Select NO */
+ mock_keypress[7] = VB_KEY_ENTER; /* Do not confirm vendor data */
+ mock_keypress[8] = VB_KEY_ESC; /* Escape to boot */
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Enter set vendor data, don't confirm, esc");
+ TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called");
+
+ /* Enter set vendor data; esc, don't confirm, and change last character */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = '4';
+ mock_keypress[2] = '3';
+ mock_keypress[3] = '2';
+ mock_keypress[4] = '1';
+ mock_keypress[5] = VB_KEY_ENTER;
+ mock_keypress[6] = VB_KEY_RIGHT; /* Select NO */
+ mock_keypress[7] = VB_KEY_ENTER; /* Do not confirm vendor data */
+ mock_keypress[8] = VB_KEY_BACKSPACE; /* Remove last character */
+ mock_keypress[9] = 'B';
+ mock_keypress[10] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[11] = VB_KEY_ENTER; /* Confirm vendor data */
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Enter set vendor data esc, don't confirm, change last character");
+ TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called");
+ TEST_STR_EQ(set_vendor_data, "432B", " Vendor data correct");
+
+ /* Enter set vendor data; extra keys ignored */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = '4';
+ mock_keypress[2] = '3';
+ mock_keypress[3] = '2';
+ mock_keypress[4] = '1';
+ mock_keypress[5] = '5';
+ mock_keypress[6] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[7] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Enter set vendor data extra keys ignored");
+ TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called");
+ TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct");
+
+ /* Enter set vendor data; converts case */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = 'a';
+ mock_keypress[2] = 'B';
+ mock_keypress[3] = 'Y';
+ mock_keypress[4] = 'z';
+ mock_keypress[5] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[6] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Enter set vendor data converts case");
+ TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called");
+ TEST_STR_EQ(set_vendor_data, "ABYZ", " Vendor data correct");
+
+ /* Enter set vendor data; backspace works */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = 'A';
+ mock_keypress[2] = 'B';
+ mock_keypress[3] = 'C';
+ mock_keypress[4] = VB_KEY_BACKSPACE;
+ mock_keypress[5] = VB_KEY_BACKSPACE;
+ mock_keypress[6] = '3';
+ mock_keypress[7] = '2';
+ mock_keypress[8] = '1';
+ mock_keypress[9] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[10] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Enter set vendor data backspace works");
+ TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called");
+ TEST_STR_EQ(set_vendor_data, "A321", " Vendor data correct");
+
+ /* Enter set vendor data; invalid chars don't print */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = '4';
+ mock_keypress[2] = '-';
+ mock_keypress[3] = '^';
+ mock_keypress[4] = '&';
+ mock_keypress[5] = '$';
+ mock_keypress[6] = '.';
+ mock_keypress[7] = '3';
+ mock_keypress[8] = '2';
+ mock_keypress[9] = '1';
+ mock_keypress[10] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[11] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Enter set vendor data invalid chars don't print");
+ TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called");
+ TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct");
+
+ /* Enter set vendor data; invalid chars don't print with backspace */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = '4';
+ mock_keypress[2] = '-';
+ mock_keypress[3] = VB_KEY_BACKSPACE; /* Should delete 4 */
+ mock_keypress[4] = '3';
+ mock_keypress[5] = '2';
+ mock_keypress[6] = '1';
+ mock_keypress[7] = '0';
+ mock_keypress[8] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[9] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Enter set vendor data invalid chars don't print with backspace");
+ TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called");
+ TEST_STR_EQ(set_vendor_data, "3210", " Vendor data correct");
+
+ /* Enter set vendor data; backspace only doesn't underrun */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = 'A';
+ mock_keypress[2] = VB_KEY_BACKSPACE;
+ mock_keypress[3] = VB_KEY_BACKSPACE;
+ mock_keypress[4] = '4';
+ mock_keypress[5] = '3';
+ mock_keypress[6] = '2';
+ mock_keypress[7] = '1';
+ mock_keypress[8] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[9] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Enter set vendor data backspace only doesn't underrun");
+ TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called");
+ TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct");
+
+ /* Enter set vendor data; vowels not allowed after first char */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = 'A';
+ mock_keypress[2] = 'A';
+ mock_keypress[3] = 'B';
+ mock_keypress[4] = 'E';
+ mock_keypress[5] = 'i';
+ mock_keypress[6] = 'C';
+ mock_keypress[7] = 'O';
+ mock_keypress[8] = 'u';
+ mock_keypress[9] = 'D';
+ mock_keypress[10] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[11] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Enter set vendor data vowels not allowed after first char");
+ TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called");
+ TEST_STR_EQ(set_vendor_data, "ABCD", " Vendor data correct");
+
+ /* Enter set vendor data; too short */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = '1';
+ mock_keypress[2] = '2';
+ mock_keypress[3] = '3';
+ /* Set vendor data (nothing happens) */
+ mock_keypress[4] = VB_KEY_ENTER;
+ /* Confirm vendor data (nothing happens) */
+ mock_keypress[5] = VB_KEY_ENTER;
+ mock_keypress[6] = VB_KEY_ESC;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Enter set vendor data too short");
+ TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called");
+
+ /* Enter set vendor data; esc from set screen */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = VB_KEY_ESC;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Enter set vendor data esc from set screen");
+ TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called");
+
+ /* Enter set vendor data; esc from set screen with tag */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = '4';
+ mock_keypress[2] = '3';
+ mock_keypress[3] = '2';
+ mock_keypress[4] = '1';
+ mock_keypress[5] = VB_KEY_ESC;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Enter set vendor data esc from set screen with tag");
+ TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called");
+
+ /* Enter set vendor data; esc from confirm screen */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */
+ mock_keypress[1] = '4';
+ mock_keypress[2] = '3';
+ mock_keypress[3] = '2';
+ mock_keypress[4] = '1';
+ mock_keypress[5] = VB_KEY_ENTER; /* Set vendor data */
+ mock_keypress[6] = VB_KEY_ESC;
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Enter set vendor data esc from set screen");
+ TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called");
+
+ /* Escape from vendor data warning screen */
+ ResetMocks();
+ ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE;
+ mock_keypress[0] = VB_KEY_ESC; /* Enter vendor data setting */
+ vbtlk_expect_fixed = 1;
+ TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK,
+ "Enter set vendor data esc, don't confirm, change last character");
+ TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called");
+
+ VB2_DEBUG("...done.\n");
+}
+
+/*
+ * Helper function to test VbBootRecovery against a sequence of gpio events.
+ * caller specifies a sequence of gpio events and the expected confirm vs.
+ * reboot result.
+ *
+ * Non-asserted gpios are used for 5 events, then 'first' for 5 events,
+ * 'second' for 5 events, and 'third' for 5 events.
+ */
+static void VbBootRecTestGpio(uint32_t first, uint32_t second, uint32_t third,
+ uint32_t confirm, const char *msg)
+{
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY;
+ vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND;
+ trust_ec = 1;
+ mock_keypress[0] = VB_KEY_CTRL('D');
+ mock_gpio[0].gpio_flags = 0;
+ mock_gpio[0].count = 4;
+ mock_gpio[1].gpio_flags = first;
+ mock_gpio[1].count = 4;
+ mock_gpio[2].gpio_flags = second;
+ mock_gpio[2].count = 4;
+ mock_gpio[3].gpio_flags = third;
+ mock_gpio[3].count = 4;
+ vbtlk_expect_removable = 1;
+
+ if (confirm) {
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_REBOOT_EC_TO_RO, msg);
+ TEST_EQ(virtdev_set, 1, " virtual dev mode on");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_USB), !!USB_BOOT_ON_DEV,
+ " NV_DEV_BOOT_USB enabled");
+ } else {
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN, msg);
+ TEST_EQ(virtdev_set, 0, " virtual dev mode off");
+ }
+}
+
+static void VbBootRecTest(void)
+{
+ VB2_DEBUG("Testing VbBootRecoveryLegacyClamshell()...\n");
+
+ /* Shutdown requested in loop */
+ ResetMocks();
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Shutdown requested");
+
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0,
+ " recovery reason");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
+ " broken screen");
+
+ /* Shutdown requested by keyboard */
+ ResetMocks();
+ mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Shutdown requested by keyboard");
+
+ /* Ignore power button held on boot */
+ ResetMocks();
+ mock_gpio[0].gpio_flags = GPIO_SHUTDOWN;
+ mock_gpio[0].count = 10;
+ mock_gpio[1].gpio_flags = 0;
+ mock_gpio[1].count = 10;
+ mock_gpio[2].gpio_flags = GPIO_SHUTDOWN;
+ mock_gpio[2].count = 10;
+ mock_gpio[3].gpio_flags = 0;
+ mock_gpio[3].count = 100;
+ sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY;
+ trust_ec = 1;
+ vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND;
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Ignore power button held on boot");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
+ " insert screen");
+ /* Shutdown should happen while we're sending the 2nd block of events */
+
+ /* Broken screen */
+ ResetMocks();
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_num_disks[0] = 1;
+ mock_num_disks[1] = 1;
+ mock_num_disks[2] = 1;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Broken");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
+ " broken screen");
+
+ /* Broken screen even if dev switch is on */
+ ResetMocks();
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_num_disks[0] = 1;
+ mock_num_disks[1] = 1;
+ sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Broken (dev)");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
+ " broken screen");
+
+ /* Force insert screen with GBB flag */
+ ResetMocks();
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ gbb.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY;
+ vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND;
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Insert (forced by GBB)");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
+ " insert screen");
+
+ /* No removal if recovery button physically pressed */
+ ResetMocks();
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_num_disks[0] = 1;
+ mock_num_disks[1] = 1;
+ sd->flags |= VB2_SD_FLAG_MANUAL_RECOVERY;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "No remove in rec");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
+ " broken screen");
+
+ /* Removal if no disk initially found, but found on second attempt */
+ ResetMocks();
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_num_disks[0] = 0;
+ mock_num_disks[1] = 1;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Remove");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
+ " broken screen");
+
+ /* Bad disk count doesn't require removal */
+ ResetMocks();
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_num_disks[0] = -1;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Bad disk count");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
+ " broken screen");
+
+ /* Ctrl+D ignored for many reasons... */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY;
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_keypress[0] = VB_KEY_CTRL('D');
+ trust_ec = 0;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "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();
+ sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY | VB2_SD_FLAG_DEV_MODE_ENABLED;
+ trust_ec = 1;
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_keypress[0] = VB_KEY_CTRL('D');
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "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();
+ trust_ec = 1;
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_keypress[0] = VB_KEY_CTRL('D');
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "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");
+
+ /* Ctrl+D ignored because the physical presence switch is still pressed
+ and we don't like that. */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY;
+ trust_ec = 1;
+ mock_keypress[0] = VB_KEY_CTRL('D');
+ mock_gpio[0].gpio_flags = GPIO_PRESENCE;
+ mock_gpio[0].count = 100;
+ mock_gpio[1].gpio_flags = GPIO_PRESENCE | GPIO_SHUTDOWN;
+ mock_gpio[1].count = 100;
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Ctrl+D ignored if phys pres button is still pressed");
+ TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV,
+ " todev screen");
+
+ /* Ctrl+D then space means don't enable */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY;
+ MockGpioAfter(2, GPIO_SHUTDOWN);
+ vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND;
+ trust_ec = 1;
+ mock_keypress[0] = VB_KEY_CTRL('D');
+ mock_keypress[1] = ' ';
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "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();
+ sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY;
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND;
+ trust_ec = 1;
+ mock_keypress[0] = VB_KEY_CTRL('D');
+ mock_keypress[1] = VB_KEY_ENTER;
+ mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD;
+ vbtlk_expect_removable = 1;
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_REBOOT_EC_TO_RO,
+ "Ctrl+D todev confirm via enter");
+ TEST_EQ(virtdev_set, 1, " virtual dev mode on");
+
+ /*
+ * List of possiblities for shutdown and physical presence events that
+ * occur over time. Time advanced from left to right (where each
+ * represents the gpio[s] that are seen during a given iteration of
+ * the loop). The meaning of the characters:
+ *
+ * _ means no gpio
+ * s means shutdown gpio
+ * p means presence gpio
+ * B means both shutdown and presence gpio
+ *
+ * 1: ______ppp______ -> confirm
+ * 2: ______sss______ -> shutdown
+ * 3: ___pppsss______ -> confirm
+ * 4: ___sssppp______ -> shutdown
+ * 5: ___pppBBB______ -> confirm
+ * 6: ___pppBBBppp___ -> shutdown
+ * 7: ___pppBBBsss___ -> confirm
+ * 8: ___sssBBB______ -> confirm
+ * 9: ___sssBBBppp___ -> shutdown
+ * 10: ___sssBBBsss___ -> confirm
+ * 11: ______BBB______ -> confirm
+ * 12: ______BBBsss___ -> confirm
+ * 13: ______BBBppp___ -> shutdown
+ */
+
+ /* 1: Ctrl+D then presence means enable */
+ VbBootRecTestGpio(GPIO_PRESENCE, 0, 0, 1,
+ "Ctrl+D todev confirm via presence");
+
+ /* 2: Ctrl+D then shutdown means shutdown */
+ VbBootRecTestGpio(GPIO_SHUTDOWN, 0, 0, 0,
+ "Ctrl+D todev then shutdown");
+
+ /* 3: Ctrl+D then presence then shutdown means confirm */
+ VbBootRecTestGpio(GPIO_PRESENCE, GPIO_SHUTDOWN, 0, 1,
+ "Ctrl+D todev confirm via presence then shutdown");
+
+ /* 4: Ctrl+D then 2+ instance shutdown then presence means shutdown */
+ VbBootRecTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE, 0, 0,
+ "Ctrl+D todev then 2+ shutdown then presence");
+
+ /* 5: Ctrl+D then presence then shutdown+presence then none */
+ VbBootRecTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN, 0, 1,
+ "Ctrl+D todev confirm via presence, both, none");
+
+ /* 6: Ctrl+D then presence then shutdown+presence then presence */
+ VbBootRecTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN,
+ GPIO_PRESENCE, 0,
+ "Ctrl+D todev confirm via presence, both, presence");
+
+ /* 7: Ctrl+D then presence then shutdown+presence then shutdown */
+ VbBootRecTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN,
+ GPIO_SHUTDOWN, 1,
+ "Ctrl+D todev confirm via presence, both, shutdown");
+
+ /* 8: Ctrl+D then shutdown then shutdown+presence then none */
+ VbBootRecTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN, 0, 1,
+ "Ctrl+D todev then 2+ shutdown, both, none");
+
+ /* 9: Ctrl+D then shutdown then shutdown+presence then presence */
+ VbBootRecTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN,
+ GPIO_PRESENCE, 0,
+ "Ctrl+D todev then 2+ shutdown, both, presence");
+
+ /* 10: Ctrl+D then shutdown then shutdown+presence then shutdown */
+ VbBootRecTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN,
+ GPIO_SHUTDOWN, 1,
+ "Ctrl+D todev then 2+ shutdown, both, shutdown");
+
+ /* 11: Ctrl+D then shutdown+presence then none */
+ VbBootRecTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN, 0, 0, 1,
+ "Ctrl+D todev confirm via both then none");
+
+ /* 12: Ctrl+D then shutdown+presence then shutdown */
+ VbBootRecTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN, GPIO_SHUTDOWN, 0, 1,
+ "Ctrl+D todev confirm via both then shutdown");
+
+ /* 13: Ctrl+D then shutdown+presence then presence */
+ VbBootRecTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN, GPIO_PRESENCE, 0, 0,
+ "Ctrl+D todev confirm via both then presence");
+
+ /* Don't handle TPM error in enabling dev mode */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY;
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND;
+ trust_ec = 1;
+ mock_keypress[0] = VB_KEY_CTRL('D');
+ mock_keypress[1] = VB_KEY_ENTER;
+ mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD;
+ virtdev_fail = 1;
+ vbtlk_expect_removable = 1;
+ TEST_ABORT(VbBootRecoveryLegacyClamshell(ctx),
+ "Ctrl+D todev failure");
+ TEST_EQ(virtdev_set, 0, " virtual dev mode still off");
+
+ /* Test Diagnostic Mode via Ctrl-C - display available */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY;
+ trust_ec = 1;
+ vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND;
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_keypress[0] = VB_KEY_CTRL('C');
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0,
+ "todiag is zero");
+ vbtlk_expect_removable = 1;
+ if (DIAGNOSTIC_UI)
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_REBOOT,
+ "Ctrl+C todiag - enabled");
+ else
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Ctrl+C todiag - disabled");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), DIAGNOSTIC_UI,
+ " todiag is updated for Ctrl-C");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST), 0,
+ " todiag doesn't set unneeded DISPLAY_REQUEST");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
+ " insert screen");
+
+ /* Test Diagnostic Mode via F12 - display disabled */
+ ResetMocks();
+ sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY;
+ sd->flags &= ~VB2_SD_FLAG_DISPLAY_AVAILABLE;
+ trust_ec = 1;
+ vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND;
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_keypress[0] = VB_KEY_F(12);
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0,
+ "todiag is zero");
+ vbtlk_expect_removable = 1;
+ if (DIAGNOSTIC_UI)
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_REBOOT,
+ "F12 todiag - enabled");
+ else
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "F12 todiag - disabled");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), DIAGNOSTIC_UI,
+ " todiag is updated for F12");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST), 0,
+ " todiag doesn't set unneeded DISPLAY_REQUEST");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
+ " insert screen");
+
+ /* Test Diagnostic Mode via Ctrl-C OS broken - display available */
+ ResetMocks();
+ MockGpioAfter(10, GPIO_SHUTDOWN);
+ mock_keypress[0] = VB_KEY_CTRL('C');
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0,
+ "todiag is zero");
+ if (DIAGNOSTIC_UI)
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_REBOOT,
+ "Ctrl+C todiag os broken - enabled");
+ else
+ TEST_EQ(VbBootRecoveryLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN,
+ "Ctrl+C todiag os broken - disabled");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), DIAGNOSTIC_UI,
+ " todiag is updated for Ctrl-C");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST), 0,
+ " todiag doesn't set unneeded DISPLAY_REQUEST");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
+ " os broken screen");
+
+ VB2_DEBUG("...done.\n");
+}
+
+static void VbBootDiagTest(void)
+{
+ VB2_DEBUG("Testing VbBootDiagnosticLegacyClamshell()...\n");
+
+ /* No key pressed - timeout. */
+ ResetMocks();
+ TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Timeout");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG,
+ " confirm screen");
+ TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK,
+ " blank screen");
+ TEST_EQ(tpm_set_mode_called, 0, " no tpm call");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+ TEST_EQ(current_ticks, 30 * VB_USEC_PER_SEC,
+ " waited for 30 seconds");
+
+ /* Esc key pressed. */
+ ResetMocks();
+ mock_keypress[0] = VB_KEY_ESC;
+ TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Esc key");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG,
+ " confirm screen");
+ TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK,
+ " blank screen");
+ TEST_EQ(tpm_set_mode_called, 0, " no tpm call");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+ TEST_EQ(current_ticks, 0, " didn't wait at all");
+
+ /* Shutdown requested via lid close */
+ ResetMocks();
+ MockGpioAfter(10, GPIO_LID_CLOSED);
+ TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx),
+ VB2_REQUEST_SHUTDOWN, "Shutdown");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG,
+ " confirm screen");
+ TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK,
+ " blank screen");
+ TEST_EQ(tpm_set_mode_called, 0, " no tpm call");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+ TEST_TRUE(current_ticks < VB_USEC_PER_SEC, " didn't wait long");
+
+ /* Power button pressed but not released. */
+ ResetMocks();
+ mock_gpio[0].gpio_flags = GPIO_PRESENCE;
+ mock_gpio[0].count = ~0;
+ TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Power held");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG,
+ " confirm screen");
+ TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK,
+ " blank screen");
+ TEST_EQ(tpm_set_mode_called, 0, " no tpm call");
+ TEST_EQ(vbexlegacy_called, 0, " not legacy");
+
+ /* Power button is pressed and released. */
+ ResetMocks();
+ MockGpioAfter(3, GPIO_PRESENCE);
+ TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Confirm");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG,
+ " confirm screen");
+ TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK,
+ " blank screen");
+ TEST_EQ(tpm_set_mode_called, 1, " tpm call");
+ TEST_EQ(tpm_mode, VB2_TPM_MODE_DISABLED, " tpm disabled");
+ TEST_EQ(vbexlegacy_called, 1, " legacy");
+ TEST_EQ(altfw_num, VB_ALTFW_DIAGNOSTIC, " check altfw_num");
+ /*
+ * Ideally we'd that no recovery request was recorded, but
+ * VbExLegacy() can only fail or crash the tests.
+ */
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
+ VB2_RECOVERY_ALTFW_HASH_FAILED,
+ " recovery request");
+
+ /* Power button confirm, but now with a TPM failure. */
+ ResetMocks();
+ tpm_mode = VB2_TPM_MODE_DISABLED;
+ mock_gpio[0].gpio_flags = 0;
+ mock_gpio[0].count = 2;
+ mock_gpio[1].gpio_flags = GPIO_PRESENCE;
+ mock_gpio[1].count = 2;
+ TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), VB2_REQUEST_REBOOT,
+ "Confirm but tpm fail");
+ TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG,
+ " confirm screen");
+ TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK,
+ " blank screen");
+ TEST_EQ(tpm_set_mode_called, 1, " tpm call");
+ TEST_EQ(tpm_mode, VB2_TPM_MODE_DISABLED, " tpm disabled");
+ TEST_EQ(vbexlegacy_called, 0, " legacy not called");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
+ VB2_RECOVERY_TPM_DISABLE_FAILED,
+ " recovery request");
+
+ VB2_DEBUG("...done.\n");
+}
+
+
+int main(void)
+{
+ VbUserConfirmsTest();
+ VbBootDevTest();
+ VbBootDevVendorDataTest();
+ VbBootRecTest();
+ if (DIAGNOSTIC_UI)
+ VbBootDiagTest();
+
+ return gTestSuccess ? 0 : 255;
+}