summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Delco <delco@google.com>2019-04-23 13:37:26 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-05-16 03:15:05 -0700
commit28c21d92edbea4af68b15c2722b5d79ae9255b65 (patch)
tree24aee676e9aa7ac4358158ceac8a6003028c1746
parent6eeddec87185eac611ceb3fb8003f04c503fd54e (diff)
downloadvboot-28c21d92edbea4af68b15c2722b5d79ae9255b65.tar.gz
firmware: replace recovery mode flag with physical presence
vboot can query the physical presence flag instead of the recovery mode flag. In general, the physical presence flag will map to the recovery mode button if a board has it, and otherwise will map to the physical presence button (usually the power button). Cq-Depend: chromium:1580454 BUG=b:129471321 BRANCH=None TEST=make runtests. Built firmware and slashed on sarien. Verified that displayed text references power button and that pressing power button initiates dev mode (vs. powering off the system). Change-Id: I22f29de192da67b8eece27cbdd5aa64e97717bfc Signed-off-by: Matt Delco <delco@google.com> Reviewed-on: https://chromium-review.googlesource.com/1580472 Commit-Ready: Matt Delco <delco@chromium.org> Tested-by: Matt Delco <delco@chromium.org> Reviewed-by: Matt Delco <delco@chromium.org>
-rw-r--r--firmware/include/vboot_api.h2
-rw-r--r--firmware/lib/include/vboot_kernel.h5
-rw-r--r--firmware/lib/vboot_ui.c55
-rw-r--r--tests/vboot_api_kernel2_tests.c423
4 files changed, 372 insertions, 113 deletions
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index 682e7fc5..c5b382ac 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -204,8 +204,6 @@ typedef struct VbCommonParams {
} VbCommonParams;
/* Flags for VbExGetSwitches() */
-/* Recovery button was pressed at boot time. */
-#define VB_SWITCH_FLAG_REC_BUTTON_PRESSED 0x00000002
/* Report if user is currently present (typically via power button) */
#define VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED 0x00000004
/* Allow USB boot on transition to dev */
diff --git a/firmware/lib/include/vboot_kernel.h b/firmware/lib/include/vboot_kernel.h
index 7a8087e4..fe8d7023 100644
--- a/firmware/lib/include/vboot_kernel.h
+++ b/firmware/lib/include/vboot_kernel.h
@@ -93,4 +93,9 @@ uint32_t vb2_get_fwmp_flags(void);
*/
void vb2_nv_commit(struct vb2_context *ctx);
+/**
+ * Reinitialize global state. This should only need to be called by init tests.
+ */
+void vb2_init_ui(void);
+
#endif /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */
diff --git a/firmware/lib/vboot_ui.c b/firmware/lib/vboot_ui.c
index 6009d90d..60afadc9 100644
--- a/firmware/lib/vboot_ui.c
+++ b/firmware/lib/vboot_ui.c
@@ -28,11 +28,15 @@
#include "vboot_ui_common.h"
/* Global variables */
-static int power_button_released;
+enum {
+ POWER_BUTTON_HELD_SINCE_BOOT = 0,
+ POWER_BUTTON_RELEASED,
+ POWER_BUTTON_PRESSED, /* must have been previously released */
+} power_button_state;
-static void vb2_init_ui(void)
+void vb2_init_ui(void)
{
- power_button_released = 0;
+ power_button_state = POWER_BUTTON_HELD_SINCE_BOOT;
}
static void VbAllowUsbBoot(struct vb2_context *ctx)
@@ -58,13 +62,17 @@ static int VbWantShutdown(struct vb2_context *ctx, uint32_t key)
/*
* Ignore power button push until after we have seen it released.
* This avoids shutting down immediately if the power button is still
- * being held on startup.
+ * being held on startup. After we've recognized a valid power button
+ * push then don't report the event until after the button is released.
*/
if (shutdown_request & VB_SHUTDOWN_REQUEST_POWER_BUTTON) {
- if (!power_button_released)
- shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON;
+ shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON;
+ if (power_button_state == POWER_BUTTON_RELEASED)
+ power_button_state = POWER_BUTTON_PRESSED;
} else {
- power_button_released = 1;
+ if (power_button_state == POWER_BUTTON_PRESSED)
+ shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON;
+ power_button_state = POWER_BUTTON_RELEASED;
}
if (key == VB_BUTTON_POWER_SHORT_PRESS)
@@ -107,15 +115,15 @@ int VbUserConfirms(struct vb2_context *ctx, uint32_t confirm_flags)
uint32_t key;
uint32_t key_flags;
uint32_t btn;
- int rec_button_was_pressed = 0;
+ int phys_presence_button_was_pressed = 0;
+ int shutdown_requested = 0;
VB2_DEBUG("Entering(%x)\n", confirm_flags);
/* Await further instructions */
- while (1) {
+ do {
key = VbExKeyboardReadWithFlags(&key_flags);
- if (VbWantShutdown(ctx, key))
- return -1;
+ shutdown_requested = VbWantShutdown(ctx, key);
switch (key) {
case VB_KEY_ENTER:
/* If we require a trusted keyboard for confirmation,
@@ -145,26 +153,28 @@ int VbUserConfirms(struct vb2_context *ctx, uint32_t confirm_flags)
return 0;
break;
default:
- /* If the recovery button is physical, and is pressed,
- * this is also a YES, but must wait for release.
+ /* If the physical presence button is physical, and is
+ * pressed, this is also a YES, but must wait for
+ * release.
*/
btn = VbExGetSwitches(
- VB_SWITCH_FLAG_REC_BUTTON_PRESSED);
+ VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED);
if (!(shared->flags & VBSD_BOOT_REC_SWITCH_VIRTUAL)) {
if (btn) {
- VB2_DEBUG("Rec button pressed\n");
- rec_button_was_pressed = 1;
- } else if (rec_button_was_pressed) {
- VB2_DEBUG("Rec button (1)\n");
+ VB2_DEBUG("Presence button pressed, "
+ "awaiting release\n");
+ phys_presence_button_was_pressed = 1;
+ } else if (phys_presence_button_was_pressed) {
+ VB2_DEBUG("Presence button released "
+ "(1)\n");
return 1;
}
}
VbCheckDisplayKey(ctx, key, NULL);
}
VbExSleepMs(CONFIRM_KEY_DELAY);
- }
+ } while (!shutdown_requested);
- /* Not reached, but compiler will complain without it */
return -1;
}
@@ -888,9 +898,9 @@ static VbError_t recovery_ui(struct vb2_context *ctx)
if (!(shared->flags &
VBSD_BOOT_REC_SWITCH_VIRTUAL) &&
VbExGetSwitches(
- VB_SWITCH_FLAG_REC_BUTTON_PRESSED)) {
+ VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED)) {
/*
- * Is the recovery button stuck? In
+ * Is the presence button stuck? In
* any case we don't like this. Beep
* and ignore.
*/
@@ -949,7 +959,6 @@ static VbError_t recovery_ui(struct vb2_context *ctx)
VbError_t VbBootRecovery(struct vb2_context *ctx)
{
- vb2_init_ui();
VbError_t retval = recovery_ui(ctx);
VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL);
return retval;
diff --git a/tests/vboot_api_kernel2_tests.c b/tests/vboot_api_kernel2_tests.c
index a3cbd487..cb2471f4 100644
--- a/tests/vboot_api_kernel2_tests.c
+++ b/tests/vboot_api_kernel2_tests.c
@@ -33,9 +33,6 @@ static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE];
static struct vb2_context ctx;
static struct vb2_shared_data *sd;
-static int shutdown_request_calls_left;
-static int shutdown_request_power_held;
-static int shutdown_via_lid_close;
static int audio_looping_calls_left;
static uint32_t vbtlk_retval;
static int vbexlegacy_called;
@@ -47,9 +44,17 @@ static uint32_t virtdev_retval;
static uint32_t mock_keypress[16];
static uint32_t mock_keyflags[8];
static uint32_t mock_keypress_count;
-static uint32_t mock_switches[8];
-static uint32_t mock_switches_count;
-static int mock_switches_are_stuck;
+
+#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];
@@ -60,9 +65,24 @@ static enum vb2_tpm_mode tpm_mode;
static char set_vendor_data[32];
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_init_ui();
memset(VbApiKernelGetFwmp(), 0, sizeof(struct RollbackSpaceFwmp));
memset(&shared_data, 0, sizeof(shared_data));
@@ -79,9 +99,6 @@ static void ResetMocks(void)
sd = vb2_get_sd(&ctx);
sd->vbsd = shared;
- shutdown_request_calls_left = -1;
- shutdown_request_power_held = -1;
- shutdown_via_lid_close = 0;
audio_looping_calls_left = 30;
vbtlk_retval = 1000;
vbexlegacy_called = 0;
@@ -98,11 +115,8 @@ static void ResetMocks(void)
memset(mock_keypress, 0, sizeof(mock_keypress));
memset(mock_keyflags, 0, sizeof(mock_keyflags));
mock_keypress_count = 0;
-
- memset(mock_switches, 0, sizeof(mock_switches));
- mock_switches_count = 0;
- mock_switches_are_stuck = 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;
@@ -114,23 +128,19 @@ static void ResetMocks(void)
uint32_t VbExIsShutdownRequested(void)
{
- if (shutdown_request_calls_left == 0)
- return shutdown_via_lid_close ?
- VB_SHUTDOWN_REQUEST_LID_CLOSED :
- VB_SHUTDOWN_REQUEST_POWER_BUTTON;
- else if (shutdown_request_calls_left > 0)
- shutdown_request_calls_left--;
-
- if (shutdown_request_power_held >= 0) {
- /* Hold power button for 10 calls, then release for 10. */
- if (shutdown_request_calls_left % 10 == 0)
- shutdown_request_power_held
- = !shutdown_request_power_held;
- if (shutdown_request_power_held)
- return VB_SHUTDOWN_REQUEST_POWER_BUTTON;
+ 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 0;
+ return result;
}
uint32_t VbExKeyboardRead(void)
@@ -150,12 +160,18 @@ uint32_t VbExKeyboardReadWithFlags(uint32_t *key_flags)
uint32_t VbExGetSwitches(uint32_t request_mask)
{
- if (mock_switches_are_stuck)
- return mock_switches[0] & request_mask;
- if (mock_switches_count < ARRAY_SIZE(mock_switches))
- return mock_switches[mock_switches_count++] & request_mask;
- else
+ uint32_t result = 0;
+ if (mock_gpio_count >= ARRAY_SIZE(mock_gpio))
return 0;
+ if ((request_mask & VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED) &&
+ (mock_gpio[mock_gpio_count].gpio_flags & GPIO_PRESENCE))
+ result |= VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED;
+ if (mock_gpio[mock_gpio_count].count > 0) {
+ --mock_gpio[mock_gpio_count].count;
+ } else {
+ ++mock_gpio_count;
+ }
+ return result;
}
int VbExLegacy(enum VbAltFwIndex_t _altfw_num)
@@ -259,12 +275,49 @@ int vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val)
/* 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)
{
printf("Testing VbUserConfirms()...\n");
ResetMocks();
- shutdown_request_calls_left = 1;
+ MockGpioAfter(1, GPIO_SHUTDOWN);
TEST_EQ(VbUserConfirms(&ctx, 0), -1, "Shutdown requested");
ResetMocks();
@@ -281,13 +334,13 @@ static void VbUserConfirmsTest(void)
ResetMocks();
mock_keypress[0] = ' ';
- shutdown_request_calls_left = 1;
+ MockGpioAfter(1, GPIO_SHUTDOWN);
TEST_EQ(VbUserConfirms(&ctx, VB_CONFIRM_SPACE_MEANS_NO), 0,
"Space means no");
ResetMocks();
mock_keypress[0] = ' ';
- shutdown_request_calls_left = 1;
+ MockGpioAfter(1, GPIO_SHUTDOWN);
TEST_EQ(VbUserConfirms(&ctx, 0), -1, "Space ignored");
ResetMocks();
@@ -305,24 +358,99 @@ static void VbUserConfirmsTest(void)
0, "Untrusted keyboard");
ResetMocks();
- mock_switches[0] = VB_SWITCH_FLAG_REC_BUTTON_PRESSED;
+ MockGpioAfter(0, GPIO_PRESENCE);
TEST_EQ(VbUserConfirms(&ctx,
VB_CONFIRM_SPACE_MEANS_NO |
VB_CONFIRM_MUST_TRUST_KEYBOARD),
- 1, "Recovery button");
+ 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_switches[0] = VB_SWITCH_FLAG_REC_BUTTON_PRESSED;
- mock_switches_are_stuck = 1;
+ 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");
-
printf("...done.\n");
}
@@ -414,7 +542,9 @@ static void VbBootDevTest(void)
/* Shutdown requested in loop */
ResetMocks();
- shutdown_request_calls_left = 2;
+ mock_gpio[0].gpio_flags = 0;
+ mock_gpio[0].count = 2;
+ mock_gpio[1].gpio_flags = GPIO_SHUTDOWN;
TEST_EQ(VbBootDeveloper(&ctx),
VBERROR_SHUTDOWN_REQUESTED,
"Shutdown requested");
@@ -495,7 +625,7 @@ static void VbBootDevTest(void)
ResetMocks();
shared->flags = VBSD_BOOT_DEV_SWITCH_ON;
mock_keypress[0] = ' ';
- shutdown_request_calls_left = 2;
+ MockGpioAfter(3, GPIO_SHUTDOWN);
TEST_EQ(VbBootDeveloper(&ctx),
VBERROR_SHUTDOWN_REQUESTED,
"Shutdown requested at tonorm");
@@ -536,7 +666,7 @@ static void VbBootDevTest(void)
/* Enter altfw menu and time out */
ResetMocks();
- shutdown_request_calls_left = 1000;
+ MockGpioAfter(1000, GPIO_SHUTDOWN);
sd->gbb_flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
mock_keypress[0] = VB_KEY_CTRL('L');
TEST_EQ(VbBootDeveloper(&ctx), VBERROR_SHUTDOWN_REQUESTED,
@@ -858,7 +988,7 @@ static void VbBootDevTest(void)
ResetMocks();
shared->flags = VBSD_BOOT_DEV_SWITCH_ON;
VbApiKernelGetFwmp()->flags |= FWMP_DEV_DISABLE_BOOT;
- shutdown_request_calls_left = 1;
+ MockGpioAfter(1, GPIO_SHUTDOWN);
TEST_EQ(VbBootDeveloper(&ctx),
VBERROR_SHUTDOWN_REQUESTED,
"Shutdown requested when dev disabled");
@@ -877,13 +1007,48 @@ static void VbBootDevTest(void)
printf("...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();
+ shared->flags = VBSD_BOOT_REC_SWITCH_ON;
+ vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
+ 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;
+
+ if (confirm) {
+ TEST_EQ(VbBootRecovery(&ctx), VBERROR_EC_REBOOT_TO_RO_REQUIRED,
+ msg);
+ TEST_EQ(virtdev_set, 1, " virtual dev mode on");
+ } else {
+ TEST_EQ(VbBootRecovery(&ctx), VBERROR_SHUTDOWN_REQUESTED, msg);
+ TEST_EQ(virtdev_set, 0, " virtual dev mode off");
+ }
+}
+
static void VbBootRecTest(void)
{
printf("Testing VbBootRecovery()...\n");
/* Shutdown requested in loop */
ResetMocks();
- shutdown_request_calls_left = 10;
+ MockGpioAfter(10, GPIO_SHUTDOWN);
VbExEcEnteringMode(0, VB_EC_RECOVERY);
TEST_EQ(VbBootRecovery(&ctx),
VBERROR_SHUTDOWN_REQUESTED,
@@ -905,8 +1070,14 @@ static void VbBootRecTest(void)
/* Ignore power button held on boot */
ResetMocks();
- shutdown_request_calls_left = 100;
- shutdown_request_power_held = 1;
+ 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;
shared->flags = VBSD_BOOT_REC_SWITCH_ON;
trust_ec = 1;
vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
@@ -915,17 +1086,12 @@ static void VbBootRecTest(void)
"Ignore power button held on boot");
TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
" insert screen");
- /*
- * shutdown_request_power_held holds power button for 10 calls, then
- * releases for 10, then holds again, so expect shutdown after 20:
- * 100 - 20 = 80.
- */
- TEST_EQ(shutdown_request_calls_left, 80,
- " ignore held button");
+ /* Shutdown should happen while we're sending the 2nd block of events */
+ TEST_EQ(mock_gpio_count, 3, " ignore held button");
/* Broken screen */
ResetMocks();
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
mock_num_disks[0] = 1;
mock_num_disks[1] = 1;
mock_num_disks[2] = 1;
@@ -938,7 +1104,7 @@ static void VbBootRecTest(void)
/* Broken screen even if dev switch is on */
ResetMocks();
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
mock_num_disks[0] = 1;
mock_num_disks[1] = 1;
shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
@@ -951,7 +1117,7 @@ static void VbBootRecTest(void)
/* Force insert screen with GBB flag */
ResetMocks();
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
sd->gbb_flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY;
vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
TEST_EQ(VbBootRecovery(&ctx),
@@ -962,7 +1128,7 @@ static void VbBootRecTest(void)
/* No removal if recovery button physically pressed */
ResetMocks();
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
mock_num_disks[0] = 1;
mock_num_disks[1] = 1;
shared->flags |= VBSD_BOOT_REC_SWITCH_ON;
@@ -975,7 +1141,7 @@ static void VbBootRecTest(void)
/* Removal if no disk initially found, but found on second attempt */
ResetMocks();
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
mock_num_disks[0] = 0;
mock_num_disks[1] = 1;
vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
@@ -987,10 +1153,9 @@ static void VbBootRecTest(void)
/* Bad disk count doesn't require removal */
ResetMocks();
- shutdown_request_calls_left = 100;
+ MockGpioAfter(10, GPIO_SHUTDOWN);
mock_num_disks[0] = -1;
vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
- shutdown_request_calls_left = 10;
TEST_EQ(VbBootRecovery(&ctx),
VBERROR_SHUTDOWN_REQUESTED,
"Bad disk count");
@@ -1000,7 +1165,7 @@ static void VbBootRecTest(void)
/* Ctrl+D ignored for many reasons... */
ResetMocks();
shared->flags = VBSD_BOOT_REC_SWITCH_ON;
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
mock_keypress[0] = VB_KEY_CTRL('D');
trust_ec = 0;
TEST_EQ(VbBootRecovery(&ctx),
@@ -1013,7 +1178,7 @@ static void VbBootRecTest(void)
ResetMocks();
shared->flags = VBSD_BOOT_REC_SWITCH_ON | VBSD_BOOT_DEV_SWITCH_ON;
trust_ec = 1;
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
mock_keypress[0] = VB_KEY_CTRL('D');
TEST_EQ(VbBootRecovery(&ctx),
VBERROR_SHUTDOWN_REQUESTED,
@@ -1024,7 +1189,7 @@ static void VbBootRecTest(void)
ResetMocks();
trust_ec = 1;
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
mock_keypress[0] = VB_KEY_CTRL('D');
TEST_EQ(VbBootRecovery(&ctx),
VBERROR_SHUTDOWN_REQUESTED,
@@ -1033,25 +1198,27 @@ static void VbBootRecTest(void)
TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV,
" todev screen");
- /* Ctrl+D ignored because the physical recovery switch is still pressed
+ /* Ctrl+D ignored because the physical presence switch is still pressed
* and we don't like that.
*/
ResetMocks();
shared->flags = VBSD_BOOT_REC_SWITCH_ON;
trust_ec = 1;
- shutdown_request_calls_left = 100;
mock_keypress[0] = VB_KEY_CTRL('D');
- mock_switches[0] = VB_SWITCH_FLAG_REC_BUTTON_PRESSED;
+ 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;
TEST_EQ(VbBootRecovery(&ctx),
VBERROR_SHUTDOWN_REQUESTED,
- "Ctrl+D ignored if phys rec button is still pressed");
+ "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();
shared->flags = VBSD_BOOT_REC_SWITCH_ON;
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
trust_ec = 1;
mock_keypress[0] = VB_KEY_CTRL('D');
@@ -1070,20 +1237,102 @@ static void VbBootRecTest(void)
/* Ctrl+D then enter means enable */
ResetMocks();
shared->flags = VBSD_BOOT_REC_SWITCH_ON;
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
trust_ec = 1;
mock_keypress[0] = VB_KEY_CTRL('D');
mock_keypress[1] = VB_KEY_ENTER;
mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD;
TEST_EQ(VbBootRecovery(&ctx), VBERROR_EC_REBOOT_TO_RO_REQUIRED,
- "Ctrl+D todev confirm");
+ "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");
+
/* Handle TPM error in enabling dev mode */
ResetMocks();
shared->flags = VBSD_BOOT_REC_SWITCH_ON;
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
trust_ec = 1;
mock_keypress[0] = VB_KEY_CTRL('D');
@@ -1099,7 +1348,7 @@ static void VbBootRecTest(void)
shared->flags = VBSD_BOOT_REC_SWITCH_ON;
trust_ec = 1;
vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
mock_keypress[0] = VB_KEY_CTRL('C');
TEST_EQ(vb2_nv_get(&ctx, VB2_NV_DIAG_REQUEST), 0,
"todiag is zero");
@@ -1124,7 +1373,7 @@ static void VbBootRecTest(void)
shared->flags = VBSD_BOOT_REC_SWITCH_ON | VBSD_OPROM_MATTERS;
trust_ec = 1;
vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
mock_keypress[0] = VB_KEY_F(12);
TEST_EQ(vb2_nv_get(&ctx, VB2_NV_DIAG_REQUEST), 0,
"todiag is zero");
@@ -1146,7 +1395,7 @@ static void VbBootRecTest(void)
/* Test Diagnostic Mode via Ctrl-C OS broken */
ResetMocks();
shared->flags = 0;
- shutdown_request_calls_left = 100;
+ MockGpioAfter(100, GPIO_SHUTDOWN);
mock_keypress[0] = VB_KEY_CTRL('C');
TEST_EQ(vb2_nv_get(&ctx, VB2_NV_DIAG_REQUEST), 0,
"todiag is zero");
@@ -1198,8 +1447,7 @@ static void VbBootDiagTest(void)
/* Shutdown requested via lid close */
ResetMocks();
- shutdown_via_lid_close = 1;
- shutdown_request_calls_left = 10;
+ MockGpioAfter(10, GPIO_LID_CLOSED);
TEST_EQ(VbBootDiagnostic(&ctx), VBERROR_SHUTDOWN_REQUESTED, "Shutdown");
TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG,
" confirm screen");
@@ -1211,8 +1459,8 @@ static void VbBootDiagTest(void)
/* Power button pressed but not released. */
ResetMocks();
- mock_switches_are_stuck = 1;
- mock_switches[0] = VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED;
+ mock_gpio[0].gpio_flags = GPIO_PRESENCE;
+ mock_gpio[0].count = ~0;
TEST_EQ(VbBootDiagnostic(&ctx), VBERROR_REBOOT_REQUIRED, "Power held");
TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG,
" confirm screen");
@@ -1223,9 +1471,7 @@ static void VbBootDiagTest(void)
/* Power button is pressed and released. */
ResetMocks();
- mock_switches[0] = 0;
- mock_switches[1] = VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED;
- mock_switches[2] = 0;
+ MockGpioAfter(3, GPIO_PRESENCE);
TEST_EQ(VbBootDiagnostic(&ctx), VBERROR_REBOOT_REQUIRED, "Confirm");
TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG,
" confirm screen");
@@ -1246,9 +1492,10 @@ static void VbBootDiagTest(void)
/* Power button confirm, but now with a tpm failure. */
ResetMocks();
tpm_mode = VB2_TPM_MODE_DISABLED;
- mock_switches[0] = 0;
- mock_switches[1] = VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED;
- mock_switches[2] = 0;
+ 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(VbBootDiagnostic(&ctx), VBERROR_REBOOT_REQUIRED,
"Confirm but tpm fail");
TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG,