From eb13c06d2ba27f09996168409472cade82807414 Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Wed, 6 Dec 2017 09:30:08 -0800 Subject: vboot_ui: Let keyboard power button shut down system This patch allows a power button on a keyboard to shut down the system when waiting for a user interaction at a firmware screen. The firmware menu, which is implemented by vboot_ui_menu, shouldn't be affected. BUG=b:70244028 BRANCH=none TEST=Verify power button on Fizz can shut down the system at recovery screen, broken screen, todev scree, and user confirmation screen using a USB keyboard and a servo. Verify recovery button can confirm dev mode transition. Run 'make runmisctests' successfully. Change-Id: Icc7d7a774da19acac3d2938d5748ad2323ba4856 Signed-off-by: Daisuke Nojiri Reviewed-on: https://chromium-review.googlesource.com/811444 Reviewed-by: Randall Spangler --- firmware/lib/vboot_ui.c | 35 ++++++++++++++++++----------------- tests/vboot_api_kernel2_tests.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/firmware/lib/vboot_ui.c b/firmware/lib/vboot_ui.c index a99945e5..c44b70b1 100644 --- a/firmware/lib/vboot_ui.c +++ b/firmware/lib/vboot_ui.c @@ -39,10 +39,13 @@ static void VbAllowUsbBoot(struct vb2_context *ctx) * * Returns true if a shutdown is required and false if no shutdown is required. */ -static int VbWantShutdown(uint32_t gbb_flags) +static int VbWantShutdown(uint32_t gbb_flags, uint32_t key) { uint32_t shutdown_request = VbExIsShutdownRequested(); + if (key == VB_BUTTON_POWER_SHORT_PRESS) + shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON; + /* If desired, ignore shutdown request due to lid closure. */ if (gbb_flags & GBB_FLAG_DISABLE_LID_SHUTDOWN) shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED; @@ -92,20 +95,19 @@ int VbUserConfirms(struct vb2_context *ctx, VbCommonParams *cparams, uint32_t confirm_flags) { VbSharedDataHeader *shared = - (VbSharedDataHeader *)cparams->shared_data_blob; + (VbSharedDataHeader *)cparams->shared_data_blob; uint32_t key; uint32_t key_flags; - uint32_t button; + uint32_t btn; int rec_button_was_pressed = 0; VB2_DEBUG("Entering(%x)\n", confirm_flags); /* Await further instructions */ while (1) { - if (VbWantShutdown(cparams->gbb->flags)) - return -1; key = VbExKeyboardReadWithFlags(&key_flags); - button = VbExGetSwitches(VB_INIT_FLAG_REC_BUTTON_PRESSED); + if (VbWantShutdown(cparams->gbb->flags, key)) + return -1; switch (key) { case '\r': /* If we require a trusted keyboard for confirmation, @@ -116,8 +118,7 @@ int VbUserConfirms(struct vb2_context *ctx, VbCommonParams *cparams, !(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) { VbExBeep(120, 400); break; - } - + } VB2_DEBUG("Yes (1)\n"); return 1; break; @@ -135,10 +136,11 @@ int VbUserConfirms(struct vb2_context *ctx, VbCommonParams *cparams, /* If the recovery button is physical, and is pressed, * this is also a YES, but must wait for release. */ + btn = VbExGetSwitches(VB_INIT_FLAG_REC_BUTTON_PRESSED); if (!(shared->flags & VBSD_BOOT_REC_SWITCH_VIRTUAL)) { - if (button) { + if (btn) { VB2_DEBUG("Rec button pressed\n"); - rec_button_was_pressed = 1; + rec_button_was_pressed = 1; } else if (rec_button_was_pressed) { VB2_DEBUG("Rec button (1)\n"); return 1; @@ -243,15 +245,13 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx, VbCommonParams *cparams) /* We'll loop until we finish the delay or are interrupted */ do { - uint32_t key; - - if (VbWantShutdown(gbb->flags)) { + uint32_t key = VbExKeyboardRead(); + if (VbWantShutdown(gbb->flags, key)) { VB2_DEBUG("VbBootDeveloper() - shutdown requested!\n"); VbAudioClose(audio); return VBERROR_SHUTDOWN_REQUESTED; } - key = VbExKeyboardRead(); switch (key) { case 0: /* nothing pressed */ @@ -445,8 +445,9 @@ static VbError_t recovery_ui(struct vb2_context *ctx, VbCommonParams *cparams) VbDisplayScreen(ctx, cparams, VB_SCREEN_OS_BROKEN, 0); VB2_DEBUG("VbBootRecovery() waiting for manual recovery\n"); while (1) { - VbCheckDisplayKey(ctx, cparams, VbExKeyboardRead()); - if (VbWantShutdown(cparams->gbb->flags)) + key = VbExKeyboardRead(); + VbCheckDisplayKey(ctx, cparams, key); + if (VbWantShutdown(cparams->gbb->flags, key)) return VBERROR_SHUTDOWN_REQUESTED; VbExSleepMs(REC_KEY_DELAY); } @@ -543,7 +544,7 @@ static VbError_t recovery_ui(struct vb2_context *ctx, VbCommonParams *cparams) } else { VbCheckDisplayKey(ctx, cparams, key); } - if (VbWantShutdown(cparams->gbb->flags)) + if (VbWantShutdown(cparams->gbb->flags, key)) return VBERROR_SHUTDOWN_REQUESTED; VbExSleepMs(REC_KEY_DELAY); } diff --git a/tests/vboot_api_kernel2_tests.c b/tests/vboot_api_kernel2_tests.c index 02a9087a..384c978d 100644 --- a/tests/vboot_api_kernel2_tests.c +++ b/tests/vboot_api_kernel2_tests.c @@ -214,6 +214,10 @@ static void VbUserConfirmsTest(void) shutdown_request_calls_left = 1; TEST_EQ(VbUserConfirms(&ctx, &cparams, 0), -1, "Shutdown requested"); + ResetMocks(); + mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS; + TEST_EQ(VbUserConfirms(&ctx, &cparams, 0), -1, "Shutdown requested"); + ResetMocks(); mock_keypress[0] = '\r'; TEST_EQ(VbUserConfirms(&ctx, &cparams, 0), 1, "Enter"); @@ -351,6 +355,13 @@ static void VbBootDevTest(void) "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(VbBootDeveloper(&ctx, &cparams), + VBERROR_SHUTDOWN_REQUESTED, + "Shutdown requested by keyboard"); + /* Space goes straight to recovery if no virtual dev switch */ ResetMocks(); mock_keypress[0] = ' '; @@ -428,6 +439,14 @@ static void VbBootDevTest(void) TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM, " tonorm screen"); + /* Shutdown requested by keyboard at tonorm screen */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; + mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS; + TEST_EQ(VbBootDeveloper(&ctx, &cparams), + VBERROR_SHUTDOWN_REQUESTED, + "Shutdown requested by keyboard at nonorm"); + /* Ctrl+D dismisses warning */ ResetMocks(); mock_keypress[0] = 0x04; @@ -534,6 +553,15 @@ static void VbBootDevTest(void) TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM, " tonorm screen"); + /* Shutdown requested by keyboard when dev disabled */ + ResetMocks(); + shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; + VbApiKernelGetFwmp()->flags |= FWMP_DEV_DISABLE_BOOT; + mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS; + TEST_EQ(VbBootDeveloper(&ctx, &cparams), + VBERROR_SHUTDOWN_REQUESTED, + "Shutdown requested by keyboard when dev disabled"); + printf("...done.\n"); } @@ -555,6 +583,14 @@ static void VbBootRecTest(void) TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, " broken screen"); + /* Shutdown requested by keyboard */ + ResetMocks(); + VbExEcEnteringMode(0, VB_EC_RECOVERY); + mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS; + TEST_EQ(VbBootRecovery(&ctx, &cparams), + VBERROR_SHUTDOWN_REQUESTED, + "Shutdown requested by keyboard"); + /* Remove disks */ ResetMocks(); shutdown_request_calls_left = 100; -- cgit v1.2.1