From f15845a77700a03ee89fa064b796d95ff5fa5406 Mon Sep 17 00:00:00 2001 From: Hsuan Ting Chen Date: Tue, 21 Jan 2020 14:40:15 +0800 Subject: vboot: Rename legacy UIs According to crbug.com/1033815, rename files and entry point functions for two legacy UIs. Ideally, these UIs will be deprecated after the detachable UI revamp (b:146399181) is done. common: - rename vboot_ui_common.{c,h} to vboot_ui_legacy_common.{c,h} LEGACY_CLAMSHELL_UI: - rename vboot_ui.c to vboot_ui_legacy_clamshell.c - rename vboot_ui_wilco.c to vboot_ui_legacy_wilco.c - rename VbBootRecovery() to VbBootRecoveryLegacyClamshell() - rename VbBootDiagnostic() to VbBootDiagnosticLegacyClamshell() - rename VbBootDeveloper() to VbBootDeveloperLegacyClamshell() LEGACY_MENU_UI: - rename vboot_ui_menu.c to vboot_ui_legacy_menu.c - rename vboot_ui_menu_private.h to vboot_ui_legacy_menu_private.h - rename VbBootRecoveryMenu() to VbBootRecoveryLegacyMenu() - rename VbBootDeveloperMenu() to VbBootDeveloperLegacyMenu() BRANCH=none BUG=b:146399181,chromium:1033815 TEST=USE="legacy_clamshell_ui" emerge-nami vboot_reference TEST=USE="legacy_menu_ui" emerge-nami vboot_reference Change-Id: I70dafbab0070b19ed963d2a4ba63a95f4a0f3224 Signed-off-by: Hsuan Ting Chen Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2008980 Reviewed-by: Yu-Ping Wu Reviewed-by: Joel Kitching --- firmware/lib/include/vboot_kernel.h | 20 +- firmware/lib/include/vboot_ui_common.h | 75 -- firmware/lib/include/vboot_ui_legacy_common.h | 75 ++ .../lib/include/vboot_ui_legacy_menu_private.h | 94 +++ firmware/lib/include/vboot_ui_legacy_wilco.h | 30 + firmware/lib/include/vboot_ui_menu_private.h | 93 --- firmware/lib/include/vboot_ui_wilco.h | 30 - firmware/lib/vboot_api_kernel.c | 10 +- firmware/lib/vboot_ui.c | 558 ------------- firmware/lib/vboot_ui_common.c | 113 --- firmware/lib/vboot_ui_legacy_clamshell.c | 556 +++++++++++++ firmware/lib/vboot_ui_legacy_common.c | 113 +++ firmware/lib/vboot_ui_legacy_menu.c | 919 +++++++++++++++++++++ firmware/lib/vboot_ui_legacy_wilco.c | 350 ++++++++ firmware/lib/vboot_ui_menu.c | 919 --------------------- firmware/lib/vboot_ui_wilco.c | 350 -------- 16 files changed, 2152 insertions(+), 2153 deletions(-) delete mode 100644 firmware/lib/include/vboot_ui_common.h create mode 100644 firmware/lib/include/vboot_ui_legacy_common.h create mode 100644 firmware/lib/include/vboot_ui_legacy_menu_private.h create mode 100644 firmware/lib/include/vboot_ui_legacy_wilco.h delete mode 100644 firmware/lib/include/vboot_ui_menu_private.h delete mode 100644 firmware/lib/include/vboot_ui_wilco.h delete mode 100644 firmware/lib/vboot_ui.c delete mode 100644 firmware/lib/vboot_ui_common.c create mode 100644 firmware/lib/vboot_ui_legacy_clamshell.c create mode 100644 firmware/lib/vboot_ui_legacy_common.c create mode 100644 firmware/lib/vboot_ui_legacy_menu.c create mode 100644 firmware/lib/vboot_ui_legacy_wilco.c delete mode 100644 firmware/lib/vboot_ui_menu.c delete mode 100644 firmware/lib/vboot_ui_wilco.c (limited to 'firmware') diff --git a/firmware/lib/include/vboot_kernel.h b/firmware/lib/include/vboot_kernel.h index 567c10ad..c147c316 100644 --- a/firmware/lib/include/vboot_kernel.h +++ b/firmware/lib/include/vboot_kernel.h @@ -54,29 +54,29 @@ int VbUserConfirms(struct vb2_context *ctx, uint32_t confirm_flags); vb2_error_t VbBootNormal(struct vb2_context *ctx); /** - * Handle a developer-mode boot. + * Handle a developer-mode boot using legacy clamshell UI. */ -vb2_error_t VbBootDeveloper(struct vb2_context *ctx); +vb2_error_t VbBootDeveloperLegacyClamshell(struct vb2_context *ctx); /** - * Handle a diagnostic-mode boot. + * Handle a diagnostic-mode boot using legacy clamshell UI. */ -vb2_error_t VbBootDiagnostic(struct vb2_context *ctx); +vb2_error_t VbBootDiagnosticLegacyClamshell(struct vb2_context *ctx); /** - * Handle a recovery-mode boot. + * Handle a recovery-mode boot using legacy clamshell UI. */ -vb2_error_t VbBootRecovery(struct vb2_context *ctx); +vb2_error_t VbBootRecoveryLegacyClamshell(struct vb2_context *ctx); /** - * Handle a developer-mode boot using detachable menu ui + * Handle a developer-mode boot using legacy menu UI. */ -vb2_error_t VbBootDeveloperMenu(struct vb2_context *ctx); +vb2_error_t VbBootDeveloperLegacyMenu(struct vb2_context *ctx); /** - * Handle a recovery-mode boot using detachable menu ui + * Handle a recovery-mode boot using legacy menu UI. */ -vb2_error_t VbBootRecoveryMenu(struct vb2_context *ctx); +vb2_error_t VbBootRecoveryLegacyMenu(struct vb2_context *ctx); /** * Writes modified secdata spaces and nvdata. diff --git a/firmware/lib/include/vboot_ui_common.h b/firmware/lib/include/vboot_ui_common.h deleted file mode 100644 index 2587980b..00000000 --- a/firmware/lib/include/vboot_ui_common.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright 2018 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. - * - * Common code used by both vboot_ui and vboot_ui_menu. - */ - -#ifndef VBOOT_REFERENCE_VBOOT_UI_COMMON_H_ -#define VBOOT_REFERENCE_VBOOT_UI_COMMON_H_ - -#define KEY_DELAY_MS 20 /* Delay between key scans in UI loops */ - -enum vb2_beep_type { - VB_BEEP_FAILED, /* Permitted but the operation failed */ - VB_BEEP_NOT_ALLOWED, /* Operation disabled by user setting */ -}; - -/** - * Reinitialize global state. This should only need to be called - * by vboot_ui::vb2_init_ui() for init tests. - */ -void vb2_reset_power_button(void); - -/** - * Emit beeps to indicate an error - */ -void vb2_error_beep(enum vb2_beep_type beep); - -/** - * Prints a message to screen, logs a possibly different message to log, - * and beeps to notify user. - * - * @print_msg Display message. NULL message will be ignored. - * @log_msg Log message. If NULL, uses @print_msg (if that's not NULL). - * @beep Type of beep sound. - */ -void vb2_error_notify(const char *print_msg, - const char *log_msg, - enum vb2_beep_type beep); - -/** Display an error and beep to indicate that altfw is not available */ -void vb2_error_no_altfw(void); - -/** - * Jump to a bootloader if possible - * - * This checks if the operation is permitted. If it is, then it jumps to the - * selected bootloader and execution continues there, never returning. - * - * Will beep and return if one of the following is true: - * - operation is not permitted (allowed == 0) - * - vboot data fails to commit - * - secdata_kernel fails to lock - * - bootloader cannot be found - * - bootloader fails to start - * - * @param ctx Context pointer - * @param allowed 1 if allowed, 0 if not allowed - * @param altfw_num Number of bootloader to start (0=any, 1=first, etc.) - */ -void vb2_try_altfw(struct vb2_context *ctx, int allowed, - enum VbAltFwIndex_t altfw_num); - -/** - * Checks GBB flags against VbExIsShutdownRequested() shutdown request to - * determine if a shutdown is required. - * - * Returns zero or more of the following flags (if any are set then typically - * shutdown is required): - * VB_SHUTDOWN_REQUEST_LID_CLOSED - * VB_SHUTDOWN_REQUEST_POWER_BUTTON - */ -int vb2_want_shutdown(struct vb2_context *ctx, uint32_t key); - -#endif /* VBOOT_REFERENCE_VBOOT_UI_COMMON_H_ */ diff --git a/firmware/lib/include/vboot_ui_legacy_common.h b/firmware/lib/include/vboot_ui_legacy_common.h new file mode 100644 index 00000000..ae081ae1 --- /dev/null +++ b/firmware/lib/include/vboot_ui_legacy_common.h @@ -0,0 +1,75 @@ +/* Copyright 2018 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. + * + * Common code used by both legacy_clamshell_ui and legacy_menu_ui. + */ + +#ifndef VBOOT_REFERENCE_VBOOT_UI_COMMON_H_ +#define VBOOT_REFERENCE_VBOOT_UI_COMMON_H_ + +#define KEY_DELAY_MS 20 /* Delay between key scans in UI loops */ + +enum vb2_beep_type { + VB_BEEP_FAILED, /* Permitted but the operation failed */ + VB_BEEP_NOT_ALLOWED, /* Operation disabled by user setting */ +}; + +/** + * Reinitialize global state. This should only need to be called + * by vboot_ui::vb2_init_ui() for init tests. + */ +void vb2_reset_power_button(void); + +/** + * Emit beeps to indicate an error + */ +void vb2_error_beep(enum vb2_beep_type beep); + +/** + * Prints a message to screen, logs a possibly different message to log, + * and beeps to notify user. + * + * @print_msg Display message. NULL message will be ignored. + * @log_msg Log message. If NULL, uses @print_msg (if that's not NULL). + * @beep Type of beep sound. + */ +void vb2_error_notify(const char *print_msg, + const char *log_msg, + enum vb2_beep_type beep); + +/** Display an error and beep to indicate that altfw is not available */ +void vb2_error_no_altfw(void); + +/** + * Jump to a bootloader if possible + * + * This checks if the operation is permitted. If it is, then it jumps to the + * selected bootloader and execution continues there, never returning. + * + * Will beep and return if one of the following is true: + * - operation is not permitted (allowed == 0) + * - vboot data fails to commit + * - secdata_kernel fails to lock + * - bootloader cannot be found + * - bootloader fails to start + * + * @param ctx Context pointer + * @param allowed 1 if allowed, 0 if not allowed + * @param altfw_num Number of bootloader to start (0=any, 1=first, etc.) + */ +void vb2_try_altfw(struct vb2_context *ctx, int allowed, + enum VbAltFwIndex_t altfw_num); + +/** + * Checks GBB flags against VbExIsShutdownRequested() shutdown request to + * determine if a shutdown is required. + * + * Returns zero or more of the following flags (if any are set then typically + * shutdown is required): + * VB_SHUTDOWN_REQUEST_LID_CLOSED + * VB_SHUTDOWN_REQUEST_POWER_BUTTON + */ +int vb2_want_shutdown(struct vb2_context *ctx, uint32_t key); + +#endif /* VBOOT_REFERENCE_VBOOT_UI_COMMON_H_ */ diff --git a/firmware/lib/include/vboot_ui_legacy_menu_private.h b/firmware/lib/include/vboot_ui_legacy_menu_private.h new file mode 100644 index 00000000..76edd655 --- /dev/null +++ b/firmware/lib/include/vboot_ui_legacy_menu_private.h @@ -0,0 +1,94 @@ +/* Copyright 2017 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. + * + * Private declarations for vboot_ui_legacy_menu.c. Defined here for easier + * testing. + */ + +#ifndef VBOOT_REFERENCE_VBOOT_UI_LEGACY_MENU_PRIVATE_H_ +#define VBOOT_REFERENCE_VBOOT_UI_LEGACY_MENU_PRIVATE_H_ + +#include "2api.h" +#include "vboot_api.h" + +struct vb2_menu_item { + const char *text; + vb2_error_t (*action)(struct vb2_context *ctx); +}; + +struct vb2_menu { + const char *name; + uint16_t size; + uint16_t screen; + struct vb2_menu_item *items; +}; + +typedef enum _VB_MENU { + VB_MENU_DEV_WARNING, + VB_MENU_DEV, + VB_MENU_TO_NORM, + VB_MENU_TO_DEV, + VB_MENU_LANGUAGES, + VB_MENU_OPTIONS, + VB_MENU_RECOVERY_INSERT, + VB_MENU_RECOVERY_NO_GOOD, + VB_MENU_RECOVERY_BROKEN, + VB_MENU_TO_NORM_CONFIRMED, + VB_MENU_ALT_FW, + VB_MENU_COUNT, +} VB_MENU; + +typedef enum _VB_DEV_WARNING_MENU { + VB_WARN_OPTIONS, + VB_WARN_DBG_INFO, + VB_WARN_ENABLE_VER, + VB_WARN_POWER_OFF, + VB_WARN_LANGUAGE, + VB_WARN_COUNT, +} VB_DEV_WARNING_MENU; + +typedef enum _VB_DEV_MENU { + VB_DEV_NETWORK, + VB_DEV_LEGACY, + VB_DEV_USB, + VB_DEV_DISK, + VB_DEV_CANCEL, + VB_DEV_POWER_OFF, + VB_DEV_LANGUAGE, + VB_DEV_COUNT, +} VB_DEV_MENU; + +typedef enum _VB_TO_NORM_MENU { + VB_TO_NORM_CONFIRM, + VB_TO_NORM_CANCEL, + VB_TO_NORM_POWER_OFF, + VB_TO_NORM_LANGUAGE, + VB_TO_NORM_COUNT, +} VB_TO_NORM_MENU; + +typedef enum _VB_TO_DEV_MENU { + VB_TO_DEV_CONFIRM, + VB_TO_DEV_CANCEL, + VB_TO_DEV_POWER_OFF, + VB_TO_DEV_LANGUAGE, + VB_TO_DEV_COUNT, +} VB_TO_DEV_MENU; + +// TODO: currently we're only supporting +// english. Will need to somehow find mapping +// from language to localization index. +typedef enum _VB_LANGUAGES_MENU { + VB_LANGUAGES_EN_US, + VB_LANGUAGES_COUNT, +} VB_LANGUAGES_MENU; + +typedef enum _VB_OPTIONS_MENU { + VB_OPTIONS_DBG_INFO, + VB_OPTIONS_CANCEL, + VB_OPTIONS_POWER_OFF, + VB_OPTIONS_LANGUAGE, + VB_OPTIONS_COUNT, +} VB_OPTIONS_MENU; + +#endif /* VBOOT_REFERENCE_VBOOT_UI_LEGACY_MENU_PRIVATE_H_ */ diff --git a/firmware/lib/include/vboot_ui_legacy_wilco.h b/firmware/lib/include/vboot_ui_legacy_wilco.h new file mode 100644 index 00000000..d6b77965 --- /dev/null +++ b/firmware/lib/include/vboot_ui_legacy_wilco.h @@ -0,0 +1,30 @@ +/* Copyright 2020 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. + * + * Wilco-specific feature support for vboot_ui + */ + +#ifndef VBOOT_REFERENCE_VBOOT_UI_WILCO_H_ +#define VBOOT_REFERENCE_VBOOT_UI_WILCO_H_ + +/* + * User interface for setting the vendor data in VPD + */ +vb2_error_t vb2_vendor_data_ui(struct vb2_context *ctx); + +/* + * Determine whether the user has pressed the keys to enter diagnostics mode + */ +vb2_error_t vb2_check_diagnostic_key(struct vb2_context *ctx, uint32_t key); + +/* + * User interface for confirming launch of diagnostics rom + * + * This asks the user to confirm the launch of the diagnostics rom. The user + * can press the power button to confirm or press escape. There is a 30-second + * timeout which acts the same as escape. + */ +vb2_error_t vb2_diagnostics_ui(struct vb2_context *ctx); + +#endif /* VBOOT_REFERENCE_VBOOT_UI_WILCO_H_ */ diff --git a/firmware/lib/include/vboot_ui_menu_private.h b/firmware/lib/include/vboot_ui_menu_private.h deleted file mode 100644 index 09688b48..00000000 --- a/firmware/lib/include/vboot_ui_menu_private.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright 2017 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. - * - * Private declarations for vboot_ui_menu.c. Defined here for easier testing. - */ - -#ifndef VBOOT_REFERENCE_VBOOT_UI_MENU_PRIVATE_H_ -#define VBOOT_REFERENCE_VBOOT_UI_MENU_PRIVATE_H_ - -#include "2api.h" -#include "vboot_api.h" - -struct vb2_menu_item { - const char *text; - vb2_error_t (*action)(struct vb2_context *ctx); -}; - -struct vb2_menu { - const char *name; - uint16_t size; - uint16_t screen; - struct vb2_menu_item *items; -}; - -typedef enum _VB_MENU { - VB_MENU_DEV_WARNING, - VB_MENU_DEV, - VB_MENU_TO_NORM, - VB_MENU_TO_DEV, - VB_MENU_LANGUAGES, - VB_MENU_OPTIONS, - VB_MENU_RECOVERY_INSERT, - VB_MENU_RECOVERY_NO_GOOD, - VB_MENU_RECOVERY_BROKEN, - VB_MENU_TO_NORM_CONFIRMED, - VB_MENU_ALT_FW, - VB_MENU_COUNT, -} VB_MENU; - -typedef enum _VB_DEV_WARNING_MENU { - VB_WARN_OPTIONS, - VB_WARN_DBG_INFO, - VB_WARN_ENABLE_VER, - VB_WARN_POWER_OFF, - VB_WARN_LANGUAGE, - VB_WARN_COUNT, -} VB_DEV_WARNING_MENU; - -typedef enum _VB_DEV_MENU { - VB_DEV_NETWORK, - VB_DEV_LEGACY, - VB_DEV_USB, - VB_DEV_DISK, - VB_DEV_CANCEL, - VB_DEV_POWER_OFF, - VB_DEV_LANGUAGE, - VB_DEV_COUNT, -} VB_DEV_MENU; - -typedef enum _VB_TO_NORM_MENU { - VB_TO_NORM_CONFIRM, - VB_TO_NORM_CANCEL, - VB_TO_NORM_POWER_OFF, - VB_TO_NORM_LANGUAGE, - VB_TO_NORM_COUNT, -} VB_TO_NORM_MENU; - -typedef enum _VB_TO_DEV_MENU { - VB_TO_DEV_CONFIRM, - VB_TO_DEV_CANCEL, - VB_TO_DEV_POWER_OFF, - VB_TO_DEV_LANGUAGE, - VB_TO_DEV_COUNT, -} VB_TO_DEV_MENU; - -// TODO: currently we're only supporting -// english. Will need to somehow find mapping -// from language to localization index. -typedef enum _VB_LANGUAGES_MENU { - VB_LANGUAGES_EN_US, - VB_LANGUAGES_COUNT, -} VB_LANGUAGES_MENU; - -typedef enum _VB_OPTIONS_MENU { - VB_OPTIONS_DBG_INFO, - VB_OPTIONS_CANCEL, - VB_OPTIONS_POWER_OFF, - VB_OPTIONS_LANGUAGE, - VB_OPTIONS_COUNT, -} VB_OPTIONS_MENU; - -#endif /* VBOOT_REFERENCE_VBOOT_UI_MENU_PRIVATE_H_ */ diff --git a/firmware/lib/include/vboot_ui_wilco.h b/firmware/lib/include/vboot_ui_wilco.h deleted file mode 100644 index d6b77965..00000000 --- a/firmware/lib/include/vboot_ui_wilco.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2020 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. - * - * Wilco-specific feature support for vboot_ui - */ - -#ifndef VBOOT_REFERENCE_VBOOT_UI_WILCO_H_ -#define VBOOT_REFERENCE_VBOOT_UI_WILCO_H_ - -/* - * User interface for setting the vendor data in VPD - */ -vb2_error_t vb2_vendor_data_ui(struct vb2_context *ctx); - -/* - * Determine whether the user has pressed the keys to enter diagnostics mode - */ -vb2_error_t vb2_check_diagnostic_key(struct vb2_context *ctx, uint32_t key); - -/* - * User interface for confirming launch of diagnostics rom - * - * This asks the user to confirm the launch of the diagnostics rom. The user - * can press the power button to confirm or press escape. There is a 30-second - * timeout which acts the same as escape. - */ -vb2_error_t vb2_diagnostics_ui(struct vb2_context *ctx); - -#endif /* VBOOT_REFERENCE_VBOOT_UI_WILCO_H_ */ diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index 1c7d974c..57a827cb 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -397,9 +397,9 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx, /* Recovery boot. This has UI. */ if (LEGACY_MENU_UI) - rv = VbBootRecoveryMenu(ctx); + rv = VbBootRecoveryLegacyMenu(ctx); else - rv = VbBootRecovery(ctx); + rv = VbBootRecoveryLegacyClamshell(ctx); } else if (DIAGNOSTIC_UI && vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) { vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 0); @@ -409,7 +409,7 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx, * needed. This mode is also 1-shot so it's placed * before developer mode. */ - rv = VbBootDiagnostic(ctx); + rv = VbBootDiagnosticLegacyClamshell(ctx); /* * The diagnostic menu should either boot a rom, or * return either of reboot or shutdown. The following @@ -420,9 +420,9 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx, } else if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) { /* Developer boot. This has UI. */ if (LEGACY_MENU_UI) - rv = VbBootDeveloperMenu(ctx); + rv = VbBootDeveloperLegacyMenu(ctx); else - rv = VbBootDeveloper(ctx); + rv = VbBootDeveloperLegacyClamshell(ctx); } else { /* Normal boot */ rv = VbBootNormal(ctx); diff --git a/firmware/lib/vboot_ui.c b/firmware/lib/vboot_ui.c deleted file mode 100644 index 1d8e5e5d..00000000 --- a/firmware/lib/vboot_ui.c +++ /dev/null @@ -1,558 +0,0 @@ -/* 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. - * - * High-level firmware wrapper API - user interface for RW firmware - */ - -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2rsa.h" -#include "2secdata.h" -#include "2sysincludes.h" -#include "load_kernel_fw.h" -#include "tlcl.h" -#include "utility.h" -#include "vb2_common.h" -#include "vboot_api.h" -#include "vboot_audio.h" -#include "vboot_display.h" -#include "vboot_kernel.h" -#include "vboot_struct.h" -#include "vboot_test.h" -#include "vboot_ui_common.h" -#include "vboot_ui_wilco.h" - -static vb2_error_t VbTryUsb(struct vb2_context *ctx) -{ - int retval = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE); - if (VB2_SUCCESS == retval) { - VB2_DEBUG("VbBootDeveloper() - booting USB\n"); - } else { - vb2_error_notify("Could not boot from USB\n", - "VbBootDeveloper() - no kernel found on USB\n", - VB_BEEP_FAILED); - } - return retval; -} - -int VbUserConfirms(struct vb2_context *ctx, uint32_t confirm_flags) -{ - uint32_t key; - uint32_t key_flags; - uint32_t btn; - int phys_presence_button_was_pressed = 0; - int shutdown_requested = 0; - - VB2_DEBUG("Entering(%x)\n", confirm_flags); - - /* Await further instructions */ - do { - key = VbExKeyboardReadWithFlags(&key_flags); - shutdown_requested = vb2_want_shutdown(ctx, key); - switch (key) { - case VB_KEY_ENTER: - /* If we are using a trusted keyboard or a trusted - * keyboard is not required then return yes, otherwise - * keep waiting (for instance if the user is using a - * USB keyboard). - */ - if (!(confirm_flags & VB_CONFIRM_MUST_TRUST_KEYBOARD) || - (key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) { - VB2_DEBUG("Yes (1)\n"); - return 1; - } - - /* - * If physical presence is confirmed using the keyboard, - * beep and notify the user when the ENTER key comes - * from an untrusted keyboard. - * - * If physical presence is confirmed using a physical - * button, the existing message on the screen will - * instruct the user which button to push. Silently - * ignore any ENTER presses. - */ - if (PHYSICAL_PRESENCE_KEYBOARD) - vb2_error_notify("Please use internal keyboard " - "to confirm\n", - "VbUserConfirms() - " - "Trusted keyboard is required\n", - VB_BEEP_NOT_ALLOWED); - - break; - case ' ': - VB2_DEBUG("Space (%d)\n", - confirm_flags & VB_CONFIRM_SPACE_MEANS_NO); - if (confirm_flags & VB_CONFIRM_SPACE_MEANS_NO) - return 0; - break; - case VB_KEY_ESC: - VB2_DEBUG("No (0)\n"); - return 0; - default: - /* If the physical presence button is physical, and is - * pressed, this is also a YES, but must wait for - * release. - */ - if (!PHYSICAL_PRESENCE_KEYBOARD) { - btn = VbExGetSwitches( - VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED); - if (btn) { - 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(KEY_DELAY_MS); - } while (!shutdown_requested); - - return -1; -} - -/* - * User interface for selecting alternative firmware - * - * This shows the user a list of bootloaders and allows selection of one of - * them. We loop forever until something is chosen or Escape is pressed. - */ -static vb2_error_t vb2_altfw_ui(struct vb2_context *ctx) -{ - int active = 1; - - VbDisplayScreen(ctx, VB_SCREEN_ALT_FW_PICK, 0, NULL); - - /* We'll loop until the user decides what to do */ - do { - uint32_t key = VbExKeyboardRead(); - - if (vb2_want_shutdown(ctx, key)) { - VB2_DEBUG("VbBootDeveloper() - shutdown requested!\n"); - return VBERROR_SHUTDOWN_REQUESTED; - } - switch (key) { - case 0: - /* nothing pressed */ - break; - case VB_KEY_ESC: - /* Escape pressed - return to developer screen */ - VB2_DEBUG("VbBootDeveloper() - user pressed Esc:" - "exit to Developer screen\n"); - active = 0; - break; - /* We allow selection of the default '0' bootloader here */ - case '0'...'9': - VB2_DEBUG("VbBootDeveloper() - " - "user pressed key '%c': Boot alternative " - "firmware\n", key); - /* - * This will not return if successful. Drop out to - * developer mode on failure. - */ - vb2_try_altfw(ctx, 1, key - '0'); - active = 0; - break; - default: - VB2_DEBUG("VbBootDeveloper() - pressed key %#x\n", key); - VbCheckDisplayKey(ctx, key, NULL); - break; - } - VbExSleepMs(KEY_DELAY_MS); - } while (active); - - /* Back to developer screen */ - VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0, NULL); - - return 0; -} - -static const char dev_disable_msg[] = - "Developer mode is disabled on this device by system policy.\n" - "For more information, see http://dev.chromium.org/chromium-os/fwmp\n" - "\n"; - -static vb2_error_t vb2_developer_ui(struct vb2_context *ctx) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - - uint32_t disable_dev_boot = 0; - uint32_t use_usb = 0; - uint32_t use_legacy = 0; - uint32_t ctrl_d_pressed = 0; - - VB2_DEBUG("Entering\n"); - - /* Check if USB booting is allowed */ - uint32_t allow_usb = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_USB); - uint32_t allow_legacy = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY); - - /* Check if the default is to boot using disk, usb, or legacy */ - uint32_t default_boot = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT); - - if (default_boot == VB2_DEV_DEFAULT_BOOT_USB) - use_usb = 1; - if (default_boot == VB2_DEV_DEFAULT_BOOT_LEGACY) - use_legacy = 1; - - /* Handle GBB flag override */ - if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) - allow_usb = 1; - if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY) - allow_legacy = 1; - if (gbb->flags & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) { - use_legacy = 1; - use_usb = 0; - } - - /* Handle FWMP override */ - if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_USB)) - allow_usb = 1; - if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY)) - allow_legacy = 1; - if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_DISABLE_BOOT)) { - if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { - VB2_DEBUG("FWMP_DEV_DISABLE_BOOT rejected by " - "FORCE_DEV_SWITCH_ON\n"); - } else { - disable_dev_boot = 1; - } - } - - /* If dev mode is disabled, only allow TONORM */ - while (disable_dev_boot) { - VB2_DEBUG("dev_disable_boot is set\n"); - VbDisplayScreen(ctx, - VB_SCREEN_DEVELOPER_TO_NORM, 0, NULL); - VbExDisplayDebugInfo(dev_disable_msg, 0); - - /* Ignore space in VbUserConfirms()... */ - switch (VbUserConfirms(ctx, 0)) { - case 1: - VB2_DEBUG("leaving dev-mode\n"); - vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); - VbDisplayScreen(ctx, - VB_SCREEN_TO_NORM_CONFIRMED, 0, NULL); - VbExSleepMs(5000); - return VBERROR_REBOOT_REQUIRED; - case -1: - VB2_DEBUG("shutdown requested\n"); - return VBERROR_SHUTDOWN_REQUESTED; - default: - /* Ignore user attempt to cancel */ - VB2_DEBUG("ignore cancel TONORM\n"); - } - } - - if ((ctx->flags & VB2_CONTEXT_VENDOR_DATA_SETTABLE) && - VENDOR_DATA_LENGTH > 0) { - vb2_error_t ret; - VB2_DEBUG("VbBootDeveloper() - Vendor data not set\n"); - ret = vb2_vendor_data_ui(ctx); - if (ret) - return ret; - } - - /* Show the dev mode warning screen */ - VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0, NULL); - - /* Initialize audio/delay context */ - vb2_audio_start(ctx); - - /* We'll loop until we finish the delay or are interrupted */ - do { - uint32_t key = VbExKeyboardRead(); - if (vb2_want_shutdown(ctx, key)) { - VB2_DEBUG("VbBootDeveloper() - shutdown requested!\n"); - return VBERROR_SHUTDOWN_REQUESTED; - } - - switch (key) { - case 0: - /* nothing pressed */ - break; - case VB_KEY_ENTER: - /* Only disable virtual dev switch if allowed by GBB */ - if (!(gbb->flags & VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM)) - break; - __attribute__ ((fallthrough)); - case ' ': - /* See if we should disable virtual dev-mode switch. */ - VB2_DEBUG("sd->flags=%#x\n", sd->flags); - - /* Sanity check, should never fail. */ - VB2_ASSERT(sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED); - - /* Stop the countdown while we go ask... */ - if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { - /* - * TONORM won't work (only for - * non-shipping devices). - */ - vb2_error_notify( - "WARNING: TONORM prohibited by " - "GBB FORCE_DEV_SWITCH_ON.\n", - NULL, VB_BEEP_NOT_ALLOWED); - break; - } - VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_TO_NORM, - 0, NULL); - /* Ignore space in VbUserConfirms()... */ - switch (VbUserConfirms(ctx, 0)) { - case 1: - VB2_DEBUG("leaving dev-mode\n"); - vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); - VbDisplayScreen(ctx, - VB_SCREEN_TO_NORM_CONFIRMED, 0, NULL); - VbExSleepMs(5000); - return VBERROR_REBOOT_REQUIRED; - case -1: - VB2_DEBUG("shutdown requested\n"); - return VBERROR_SHUTDOWN_REQUESTED; - default: - /* Stay in dev-mode */ - VB2_DEBUG("stay in dev-mode\n"); - VbDisplayScreen(ctx, - VB_SCREEN_DEVELOPER_WARNING, 0, NULL); - /* Start new countdown */ - vb2_audio_start(ctx); - } - break; - case VB_KEY_CTRL('D'): - /* Ctrl+D = dismiss warning; advance to timeout */ - VB2_DEBUG("VbBootDeveloper() - " - "user pressed Ctrl+D; skip delay\n"); - ctrl_d_pressed = 1; - goto fallout; - case VB_KEY_CTRL('L'): - VB2_DEBUG("VbBootDeveloper() - " - "user pressed Ctrl+L; Try alt firmware\n"); - if (allow_legacy) { - vb2_error_t ret; - - ret = vb2_altfw_ui(ctx); - if (ret) - return ret; - } else { - vb2_error_no_altfw(); - } - break; - case VB_KEY_CTRL_ENTER: - /* - * The Ctrl-Enter is special for Lumpy test purpose; - * fall through to Ctrl+U handler. - */ - case VB_KEY_CTRL('U'): - /* Ctrl+U = try USB boot, or beep if failure */ - VB2_DEBUG("VbBootDeveloper() - " - "user pressed Ctrl+U; try USB\n"); - if (!allow_usb) { - vb2_error_notify( - "WARNING: Booting from external media " - "(USB/SD) has not been enabled. Refer " - "to the developer-mode documentation " - "for details.\n", - "VbBootDeveloper() - " - "USB booting is disabled\n", - VB_BEEP_NOT_ALLOWED); - } else { - /* - * Clear the screen to show we get the Ctrl+U - * key press. - */ - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - if (VB2_SUCCESS == VbTryUsb(ctx)) { - return VB2_SUCCESS; - } else { - /* Show dev mode warning screen again */ - VbDisplayScreen(ctx, - VB_SCREEN_DEVELOPER_WARNING, - 0, NULL); - } - } - break; - /* We allow selection of the default '0' bootloader here */ - case '0'...'9': - VB2_DEBUG("VbBootDeveloper() - " - "user pressed key '%c': Boot alternative " - "firmware\n", key); - vb2_try_altfw(ctx, allow_legacy, key - '0'); - break; - default: - VB2_DEBUG("VbBootDeveloper() - pressed key %#x\n", key); - VbCheckDisplayKey(ctx, key, NULL); - break; - } - - VbExSleepMs(KEY_DELAY_MS); - } while(vb2_audio_looping()); - - fallout: - - /* If defaulting to legacy boot, try that unless Ctrl+D was pressed */ - if (use_legacy && !ctrl_d_pressed) { - VB2_DEBUG("VbBootDeveloper() - defaulting to legacy\n"); - vb2_try_altfw(ctx, allow_legacy, 0); - } - - if ((use_usb && !ctrl_d_pressed) && allow_usb) { - if (VB2_SUCCESS == VbTryUsb(ctx)) { - return VB2_SUCCESS; - } - } - - /* Timeout or Ctrl+D; attempt loading from fixed disk */ - VB2_DEBUG("VbBootDeveloper() - trying fixed disk\n"); - return VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED); -} - -vb2_error_t VbBootDeveloper(struct vb2_context *ctx) -{ - vb2_reset_power_button(); - vb2_error_t retval = vb2_developer_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - return retval; -} - -vb2_error_t VbBootDiagnostic(struct vb2_context *ctx) -{ - vb2_reset_power_button(); - vb2_error_t retval = vb2_diagnostics_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - return retval; -} - -static vb2_error_t recovery_ui(struct vb2_context *ctx) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - uint32_t retval; - uint32_t key; - const char release_button_msg[] = - "Release the recovery button and try again\n"; - const char recovery_pressed_msg[] = - "^D but recovery switch is pressed\n"; - - VB2_DEBUG("VbBootRecovery() start\n"); - - if (!vb2_allow_recovery(ctx)) { - /* - * We have to save the reason here so that it will survive - * coming up three-finger-salute. We're saving it in - * VB2_RECOVERY_SUBCODE to avoid a recovery loop. - * If we save the reason in VB2_RECOVERY_REQUEST, we will come - * back here, thus, we won't be able to give a user a chance to - * reboot to workaround a boot hiccup. - */ - VB2_DEBUG("VbBootRecovery() saving recovery reason (%#x)\n", - sd->recovery_reason); - vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, sd->recovery_reason); - - /* - * Non-manual recovery mode is meant to be left via three-finger - * salute (into manual recovery mode). Need to commit nvdata - * changes immediately. Ignore commit errors in recovery mode. - */ - vb2_commit_data(ctx); - - VbDisplayScreen(ctx, VB_SCREEN_OS_BROKEN, 0, NULL); - VB2_DEBUG("VbBootRecovery() waiting for manual recovery\n"); - while (1) { - key = VbExKeyboardRead(); - VbCheckDisplayKey(ctx, key, NULL); - if (vb2_want_shutdown(ctx, key)) - return VBERROR_SHUTDOWN_REQUESTED; - else if ((retval = - vb2_check_diagnostic_key(ctx, key)) != - VB2_SUCCESS) - return retval; - VbExSleepMs(KEY_DELAY_MS); - } - } - - /* Loop and wait for a recovery image */ - VB2_DEBUG("VbBootRecovery() waiting for a recovery image\n"); - while (1) { - retval = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE); - - if (VB2_SUCCESS == retval) - break; /* Found a recovery kernel */ - - enum VbScreenType_t next_screen = - retval == VB2_ERROR_LK_NO_DISK_FOUND ? - VB_SCREEN_RECOVERY_INSERT : VB_SCREEN_RECOVERY_NO_GOOD; - VbDisplayScreen(ctx, next_screen, 0, NULL); - - key = VbExKeyboardRead(); - /* - * We might want to enter dev-mode from the Insert - * screen if all of the following are true: - * - user pressed Ctrl-D - * - we can honor the virtual dev switch - * - not already in dev mode - * - user forced recovery mode - */ - if (key == VB_KEY_CTRL('D') && - !(sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) && - (sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY)) { - if (!PHYSICAL_PRESENCE_KEYBOARD && - VbExGetSwitches( - VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED)) { - /* - * Is the presence button stuck? In any case - * we don't like this. Beep and ignore. - */ - vb2_error_notify(release_button_msg, - recovery_pressed_msg, - VB_BEEP_NOT_ALLOWED); - continue; - } - - /* Ask the user to confirm entering dev-mode */ - VbDisplayScreen(ctx, VB_SCREEN_RECOVERY_TO_DEV, - 0, NULL); - /* SPACE means no... */ - uint32_t vbc_flags = VB_CONFIRM_SPACE_MEANS_NO | - VB_CONFIRM_MUST_TRUST_KEYBOARD; - switch (VbUserConfirms(ctx, vbc_flags)) { - case 1: - VB2_DEBUG("Enabling dev-mode...\n"); - if (VB2_SUCCESS != vb2_enable_developer_mode(ctx)) - return VBERROR_TPM_SET_BOOT_MODE_STATE; - VB2_DEBUG("Reboot so it will take effect\n"); - if (USB_BOOT_ON_DEV) - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 1); - return VBERROR_EC_REBOOT_TO_RO_REQUIRED; - case -1: - VB2_DEBUG("Shutdown requested\n"); - return VBERROR_SHUTDOWN_REQUESTED; - default: /* zero, actually */ - VB2_DEBUG("Not enabling dev-mode\n"); - break; - } - } else if ((retval = vb2_check_diagnostic_key(ctx, key)) != - VB2_SUCCESS) { - return retval; - } else { - VbCheckDisplayKey(ctx, key, NULL); - } - if (vb2_want_shutdown(ctx, key)) - return VBERROR_SHUTDOWN_REQUESTED; - VbExSleepMs(KEY_DELAY_MS); - } - - return VB2_SUCCESS; -} - -vb2_error_t VbBootRecovery(struct vb2_context *ctx) -{ - vb2_error_t retval = recovery_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - return retval; -} diff --git a/firmware/lib/vboot_ui_common.c b/firmware/lib/vboot_ui_common.c deleted file mode 100644 index 65f3b368..00000000 --- a/firmware/lib/vboot_ui_common.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright 2018 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. - * - * High-level firmware wrapper API - user interface for RW firmware - */ - -#include "2common.h" -#include "2misc.h" -#include "2sysincludes.h" -#include "vboot_api.h" -#include "vboot_kernel.h" -#include "vboot_test.h" -#include "vboot_ui_common.h" - -static enum { - POWER_BUTTON_HELD_SINCE_BOOT = 0, - POWER_BUTTON_RELEASED, - POWER_BUTTON_PRESSED, /* Must have been previously released */ -} power_button_state; - -void vb2_reset_power_button(void) { - power_button_state = POWER_BUTTON_HELD_SINCE_BOOT; -} - -void vb2_error_beep(enum vb2_beep_type beep) -{ - switch (beep) { - case VB_BEEP_FAILED: - VbExBeep(250, 200); - break; - default: - case VB_BEEP_NOT_ALLOWED: - VbExBeep(120, 400); - VbExSleepMs(120); - VbExBeep(120, 400); - break; - } -} - -void vb2_error_notify(const char *print_msg, - const char *log_msg, - enum vb2_beep_type beep) -{ - if (print_msg) - VbExDisplayDebugInfo(print_msg, 0); - if (!log_msg) - log_msg = print_msg; - if (log_msg) - VB2_DEBUG(log_msg); - vb2_error_beep(beep); -} - -void vb2_error_no_altfw(void) -{ - VB2_DEBUG("Legacy boot is disabled\n"); - VbExDisplayDebugInfo("WARNING: Booting legacy BIOS has not been " - "enabled. Refer to the developer-mode " - "documentation for details.\n", 0); - vb2_error_beep(VB_BEEP_NOT_ALLOWED); -} - -void vb2_try_altfw(struct vb2_context *ctx, int allowed, - enum VbAltFwIndex_t altfw_num) -{ - if (!allowed) { - vb2_error_no_altfw(); - return; - } - - if (vb2_commit_data(ctx)) { - vb2_error_notify("Error committing data on legacy boot.\n", - NULL, VB_BEEP_FAILED); - return; - } - - /* Will not return if successful */ - VbExLegacy(altfw_num); - - vb2_error_notify("Legacy boot failed. Missing BIOS?\n", NULL, - VB_BEEP_FAILED); -} - -int vb2_want_shutdown(struct vb2_context *ctx, uint32_t key) -{ - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - uint32_t shutdown_request = VbExIsShutdownRequested(); - - /* - * 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. 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) { - shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON; - if (power_button_state == POWER_BUTTON_RELEASED) - power_button_state = POWER_BUTTON_PRESSED; - } else { - 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) - shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON; - - /* If desired, ignore shutdown request due to lid closure. */ - if (gbb->flags & VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN) - shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED; - - return shutdown_request; -} diff --git a/firmware/lib/vboot_ui_legacy_clamshell.c b/firmware/lib/vboot_ui_legacy_clamshell.c new file mode 100644 index 00000000..cc0c4175 --- /dev/null +++ b/firmware/lib/vboot_ui_legacy_clamshell.c @@ -0,0 +1,556 @@ +/* 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. + * + * High-level firmware wrapper API - user interface for RW firmware + */ + +#include "2common.h" +#include "2misc.h" +#include "2nvstorage.h" +#include "2rsa.h" +#include "2secdata.h" +#include "2sysincludes.h" +#include "load_kernel_fw.h" +#include "tlcl.h" +#include "utility.h" +#include "vb2_common.h" +#include "vboot_api.h" +#include "vboot_audio.h" +#include "vboot_display.h" +#include "vboot_kernel.h" +#include "vboot_struct.h" +#include "vboot_test.h" +#include "vboot_ui_legacy_common.h" +#include "vboot_ui_legacy_wilco.h" + +static vb2_error_t VbTryUsb(struct vb2_context *ctx) +{ + int retval = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE); + if (VB2_SUCCESS == retval) { + VB2_DEBUG("developer UI - booting USB\n"); + } else { + vb2_error_notify("Could not boot from USB\n", + "developer UI - no kernel found on USB\n", + VB_BEEP_FAILED); + } + return retval; +} + +int VbUserConfirms(struct vb2_context *ctx, uint32_t confirm_flags) +{ + uint32_t key; + uint32_t key_flags; + uint32_t btn; + int phys_presence_button_was_pressed = 0; + int shutdown_requested = 0; + + VB2_DEBUG("Entering(%x)\n", confirm_flags); + + /* Await further instructions */ + do { + key = VbExKeyboardReadWithFlags(&key_flags); + shutdown_requested = vb2_want_shutdown(ctx, key); + switch (key) { + case VB_KEY_ENTER: + /* If we are using a trusted keyboard or a trusted + * keyboard is not required then return yes, otherwise + * keep waiting (for instance if the user is using a + * USB keyboard). + */ + if (!(confirm_flags & VB_CONFIRM_MUST_TRUST_KEYBOARD) || + (key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) { + VB2_DEBUG("Yes (1)\n"); + return 1; + } + + /* + * If physical presence is confirmed using the keyboard, + * beep and notify the user when the ENTER key comes + * from an untrusted keyboard. + * + * If physical presence is confirmed using a physical + * button, the existing message on the screen will + * instruct the user which button to push. Silently + * ignore any ENTER presses. + */ + if (PHYSICAL_PRESENCE_KEYBOARD) + vb2_error_notify("Please use internal keyboard " + "to confirm\n", + "VbUserConfirms() - " + "Trusted keyboard is required\n", + VB_BEEP_NOT_ALLOWED); + + break; + case ' ': + VB2_DEBUG("Space (%d)\n", + confirm_flags & VB_CONFIRM_SPACE_MEANS_NO); + if (confirm_flags & VB_CONFIRM_SPACE_MEANS_NO) + return 0; + break; + case VB_KEY_ESC: + VB2_DEBUG("No (0)\n"); + return 0; + default: + /* If the physical presence button is physical, and is + * pressed, this is also a YES, but must wait for + * release. + */ + if (!PHYSICAL_PRESENCE_KEYBOARD) { + btn = VbExGetSwitches( + VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED); + if (btn) { + 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(KEY_DELAY_MS); + } while (!shutdown_requested); + + return -1; +} + +/* + * User interface for selecting alternative firmware + * + * This shows the user a list of bootloaders and allows selection of one of + * them. We loop forever until something is chosen or Escape is pressed. + */ +static vb2_error_t vb2_altfw_ui(struct vb2_context *ctx) +{ + int active = 1; + + VbDisplayScreen(ctx, VB_SCREEN_ALT_FW_PICK, 0, NULL); + + /* We'll loop until the user decides what to do */ + do { + uint32_t key = VbExKeyboardRead(); + + if (vb2_want_shutdown(ctx, key)) { + VB2_DEBUG("developer UI - shutdown requested!\n"); + return VBERROR_SHUTDOWN_REQUESTED; + } + switch (key) { + case 0: + /* nothing pressed */ + break; + case VB_KEY_ESC: + /* Escape pressed - return to developer screen */ + VB2_DEBUG("developer UI - user pressed Esc; " + "exit to Developer screen\n"); + active = 0; + break; + /* We allow selection of the default '0' bootloader here */ + case '0'...'9': + VB2_DEBUG("developer UI - user pressed key '%c';" + "Boot alternative firmware\n", key); + /* + * This will not return if successful. Drop out to + * developer mode on failure. + */ + vb2_try_altfw(ctx, 1, key - '0'); + active = 0; + break; + default: + VB2_DEBUG("developer UI - pressed key %#x\n", key); + VbCheckDisplayKey(ctx, key, NULL); + break; + } + VbExSleepMs(KEY_DELAY_MS); + } while (active); + + /* Back to developer screen */ + VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0, NULL); + + return 0; +} + +static const char dev_disable_msg[] = + "Developer mode is disabled on this device by system policy.\n" + "For more information, see http://dev.chromium.org/chromium-os/fwmp\n" + "\n"; + +static vb2_error_t vb2_developer_ui(struct vb2_context *ctx) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); + struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); + + uint32_t disable_dev_boot = 0; + uint32_t use_usb = 0; + uint32_t use_legacy = 0; + uint32_t ctrl_d_pressed = 0; + + VB2_DEBUG("Entering\n"); + + /* Check if USB booting is allowed */ + uint32_t allow_usb = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_USB); + uint32_t allow_legacy = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY); + + /* Check if the default is to boot using disk, usb, or legacy */ + uint32_t default_boot = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT); + + if (default_boot == VB2_DEV_DEFAULT_BOOT_USB) + use_usb = 1; + if (default_boot == VB2_DEV_DEFAULT_BOOT_LEGACY) + use_legacy = 1; + + /* Handle GBB flag override */ + if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) + allow_usb = 1; + if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY) + allow_legacy = 1; + if (gbb->flags & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) { + use_legacy = 1; + use_usb = 0; + } + + /* Handle FWMP override */ + if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_USB)) + allow_usb = 1; + if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY)) + allow_legacy = 1; + if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_DISABLE_BOOT)) { + if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { + VB2_DEBUG("FWMP_DEV_DISABLE_BOOT rejected by " + "FORCE_DEV_SWITCH_ON\n"); + } else { + disable_dev_boot = 1; + } + } + + /* If dev mode is disabled, only allow TONORM */ + while (disable_dev_boot) { + VB2_DEBUG("dev_disable_boot is set\n"); + VbDisplayScreen(ctx, + VB_SCREEN_DEVELOPER_TO_NORM, 0, NULL); + VbExDisplayDebugInfo(dev_disable_msg, 0); + + /* Ignore space in VbUserConfirms()... */ + switch (VbUserConfirms(ctx, 0)) { + case 1: + VB2_DEBUG("leaving dev-mode\n"); + vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); + VbDisplayScreen(ctx, + VB_SCREEN_TO_NORM_CONFIRMED, 0, NULL); + VbExSleepMs(5000); + return VBERROR_REBOOT_REQUIRED; + case -1: + VB2_DEBUG("shutdown requested\n"); + return VBERROR_SHUTDOWN_REQUESTED; + default: + /* Ignore user attempt to cancel */ + VB2_DEBUG("ignore cancel TONORM\n"); + } + } + + if ((ctx->flags & VB2_CONTEXT_VENDOR_DATA_SETTABLE) && + VENDOR_DATA_LENGTH > 0) { + vb2_error_t ret; + VB2_DEBUG("developer UI - Vendor data not set\n"); + ret = vb2_vendor_data_ui(ctx); + if (ret) + return ret; + } + + /* Show the dev mode warning screen */ + VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0, NULL); + + /* Initialize audio/delay context */ + vb2_audio_start(ctx); + + /* We'll loop until we finish the delay or are interrupted */ + do { + uint32_t key = VbExKeyboardRead(); + if (vb2_want_shutdown(ctx, key)) { + VB2_DEBUG("developer UI - shutdown requested!\n"); + return VBERROR_SHUTDOWN_REQUESTED; + } + + switch (key) { + case 0: + /* nothing pressed */ + break; + case VB_KEY_ENTER: + /* Only disable virtual dev switch if allowed by GBB */ + if (!(gbb->flags & VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM)) + break; + __attribute__ ((fallthrough)); + case ' ': + /* See if we should disable virtual dev-mode switch. */ + VB2_DEBUG("sd->flags=%#x\n", sd->flags); + + /* Sanity check, should never fail. */ + VB2_ASSERT(sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED); + + /* Stop the countdown while we go ask... */ + if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { + /* + * TONORM won't work (only for + * non-shipping devices). + */ + vb2_error_notify( + "WARNING: TONORM prohibited by " + "GBB FORCE_DEV_SWITCH_ON.\n", + NULL, VB_BEEP_NOT_ALLOWED); + break; + } + VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_TO_NORM, + 0, NULL); + /* Ignore space in VbUserConfirms()... */ + switch (VbUserConfirms(ctx, 0)) { + case 1: + VB2_DEBUG("leaving dev-mode\n"); + vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); + VbDisplayScreen(ctx, + VB_SCREEN_TO_NORM_CONFIRMED, 0, NULL); + VbExSleepMs(5000); + return VBERROR_REBOOT_REQUIRED; + case -1: + VB2_DEBUG("shutdown requested\n"); + return VBERROR_SHUTDOWN_REQUESTED; + default: + /* Stay in dev-mode */ + VB2_DEBUG("stay in dev-mode\n"); + VbDisplayScreen(ctx, + VB_SCREEN_DEVELOPER_WARNING, 0, NULL); + /* Start new countdown */ + vb2_audio_start(ctx); + } + break; + case VB_KEY_CTRL('D'): + /* Ctrl+D = dismiss warning; advance to timeout */ + VB2_DEBUG("developer UI - user pressed Ctrl+D; " + "skip delay\n"); + ctrl_d_pressed = 1; + goto fallout; + case VB_KEY_CTRL('L'): + VB2_DEBUG("developer UI - user pressed Ctrl+L; " + "Try alt firmware\n"); + if (allow_legacy) { + vb2_error_t ret; + + ret = vb2_altfw_ui(ctx); + if (ret) + return ret; + } else { + vb2_error_no_altfw(); + } + break; + case VB_KEY_CTRL_ENTER: + /* + * The Ctrl-Enter is special for Lumpy test purpose; + * fall through to Ctrl+U handler. + */ + case VB_KEY_CTRL('U'): + /* Ctrl+U = try USB boot, or beep if failure */ + VB2_DEBUG("developer UI - user pressed Ctrl+U; " + "try USB\n"); + if (!allow_usb) { + vb2_error_notify( + "WARNING: Booting from external media " + "(USB/SD) has not been enabled. Refer " + "to the developer-mode documentation " + "for details.\n", + "developer UI - " + "USB booting is disabled\n", + VB_BEEP_NOT_ALLOWED); + } else { + /* + * Clear the screen to show we get the Ctrl+U + * key press. + */ + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); + if (VB2_SUCCESS == VbTryUsb(ctx)) { + return VB2_SUCCESS; + } else { + /* Show dev mode warning screen again */ + VbDisplayScreen(ctx, + VB_SCREEN_DEVELOPER_WARNING, + 0, NULL); + } + } + break; + /* We allow selection of the default '0' bootloader here */ + case '0'...'9': + VB2_DEBUG("developer UI - user pressed key '%c'; " + "Boot alternative firmware\n", key); + vb2_try_altfw(ctx, allow_legacy, key - '0'); + break; + default: + VB2_DEBUG("developer UI - pressed key %#x\n", key); + VbCheckDisplayKey(ctx, key, NULL); + break; + } + + VbExSleepMs(KEY_DELAY_MS); + } while(vb2_audio_looping()); + + fallout: + + /* If defaulting to legacy boot, try that unless Ctrl+D was pressed */ + if (use_legacy && !ctrl_d_pressed) { + VB2_DEBUG("developer UI - defaulting to legacy\n"); + vb2_try_altfw(ctx, allow_legacy, 0); + } + + if ((use_usb && !ctrl_d_pressed) && allow_usb) { + if (VB2_SUCCESS == VbTryUsb(ctx)) { + return VB2_SUCCESS; + } + } + + /* Timeout or Ctrl+D; attempt loading from fixed disk */ + VB2_DEBUG("developer UI - trying fixed disk\n"); + return VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED); +} + +vb2_error_t VbBootDeveloperLegacyClamshell(struct vb2_context *ctx) +{ + vb2_reset_power_button(); + vb2_error_t retval = vb2_developer_ui(ctx); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); + return retval; +} + +vb2_error_t VbBootDiagnosticLegacyClamshell(struct vb2_context *ctx) +{ + vb2_reset_power_button(); + vb2_error_t retval = vb2_diagnostics_ui(ctx); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); + return retval; +} + +static vb2_error_t recovery_ui(struct vb2_context *ctx) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); + uint32_t retval; + uint32_t key; + const char release_button_msg[] = + "Release the recovery button and try again\n"; + const char recovery_pressed_msg[] = + "^D but recovery switch is pressed\n"; + + VB2_DEBUG("recovery UI - start\n"); + + if (!vb2_allow_recovery(ctx)) { + /* + * We have to save the reason here so that it will survive + * coming up three-finger-salute. We're saving it in + * VB2_RECOVERY_SUBCODE to avoid a recovery loop. + * If we save the reason in VB2_RECOVERY_REQUEST, we will come + * back here, thus, we won't be able to give a user a chance to + * reboot to workaround a boot hiccup. + */ + VB2_DEBUG("recovery UI - saving recovery reason (%#x)\n", + sd->recovery_reason); + vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, sd->recovery_reason); + + /* + * Non-manual recovery mode is meant to be left via three-finger + * salute (into manual recovery mode). Need to commit nvdata + * changes immediately. Ignore commit errors in recovery mode. + */ + vb2_commit_data(ctx); + + VbDisplayScreen(ctx, VB_SCREEN_OS_BROKEN, 0, NULL); + VB2_DEBUG("recovery UI - waiting for manual recovery\n"); + while (1) { + key = VbExKeyboardRead(); + VbCheckDisplayKey(ctx, key, NULL); + if (vb2_want_shutdown(ctx, key)) + return VBERROR_SHUTDOWN_REQUESTED; + else if ((retval = + vb2_check_diagnostic_key(ctx, key)) != + VB2_SUCCESS) + return retval; + VbExSleepMs(KEY_DELAY_MS); + } + } + + /* Loop and wait for a recovery image */ + VB2_DEBUG("recovery UI - waiting for a recovery image\n"); + while (1) { + retval = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE); + + if (VB2_SUCCESS == retval) + break; /* Found a recovery kernel */ + + enum VbScreenType_t next_screen = + retval == VB2_ERROR_LK_NO_DISK_FOUND ? + VB_SCREEN_RECOVERY_INSERT : VB_SCREEN_RECOVERY_NO_GOOD; + VbDisplayScreen(ctx, next_screen, 0, NULL); + + key = VbExKeyboardRead(); + /* + * We might want to enter dev-mode from the Insert + * screen if all of the following are true: + * - user pressed Ctrl-D + * - we can honor the virtual dev switch + * - not already in dev mode + * - user forced recovery mode + */ + if (key == VB_KEY_CTRL('D') && + !(sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) && + (sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY)) { + if (!PHYSICAL_PRESENCE_KEYBOARD && + VbExGetSwitches( + VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED)) { + /* + * Is the presence button stuck? In any case + * we don't like this. Beep and ignore. + */ + vb2_error_notify(release_button_msg, + recovery_pressed_msg, + VB_BEEP_NOT_ALLOWED); + continue; + } + + /* Ask the user to confirm entering dev-mode */ + VbDisplayScreen(ctx, VB_SCREEN_RECOVERY_TO_DEV, + 0, NULL); + /* SPACE means no... */ + uint32_t vbc_flags = VB_CONFIRM_SPACE_MEANS_NO | + VB_CONFIRM_MUST_TRUST_KEYBOARD; + switch (VbUserConfirms(ctx, vbc_flags)) { + case 1: + VB2_DEBUG("Enabling dev-mode...\n"); + if (VB2_SUCCESS != vb2_enable_developer_mode(ctx)) + return VBERROR_TPM_SET_BOOT_MODE_STATE; + VB2_DEBUG("Reboot so it will take effect\n"); + if (USB_BOOT_ON_DEV) + vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 1); + return VBERROR_EC_REBOOT_TO_RO_REQUIRED; + case -1: + VB2_DEBUG("Shutdown requested\n"); + return VBERROR_SHUTDOWN_REQUESTED; + default: /* zero, actually */ + VB2_DEBUG("Not enabling dev-mode\n"); + break; + } + } else if ((retval = vb2_check_diagnostic_key(ctx, key)) != + VB2_SUCCESS) { + return retval; + } else { + VbCheckDisplayKey(ctx, key, NULL); + } + if (vb2_want_shutdown(ctx, key)) + return VBERROR_SHUTDOWN_REQUESTED; + VbExSleepMs(KEY_DELAY_MS); + } + + return VB2_SUCCESS; +} + +vb2_error_t VbBootRecoveryLegacyClamshell(struct vb2_context *ctx) +{ + vb2_error_t retval = recovery_ui(ctx); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); + return retval; +} diff --git a/firmware/lib/vboot_ui_legacy_common.c b/firmware/lib/vboot_ui_legacy_common.c new file mode 100644 index 00000000..8b6a1799 --- /dev/null +++ b/firmware/lib/vboot_ui_legacy_common.c @@ -0,0 +1,113 @@ +/* Copyright 2018 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. + * + * High-level firmware wrapper API - user interface for RW firmware + */ + +#include "2common.h" +#include "2misc.h" +#include "2sysincludes.h" +#include "vboot_api.h" +#include "vboot_kernel.h" +#include "vboot_test.h" +#include "vboot_ui_legacy_common.h" + +static enum { + POWER_BUTTON_HELD_SINCE_BOOT = 0, + POWER_BUTTON_RELEASED, + POWER_BUTTON_PRESSED, /* Must have been previously released */ +} power_button_state; + +void vb2_reset_power_button(void) { + power_button_state = POWER_BUTTON_HELD_SINCE_BOOT; +} + +void vb2_error_beep(enum vb2_beep_type beep) +{ + switch (beep) { + case VB_BEEP_FAILED: + VbExBeep(250, 200); + break; + default: + case VB_BEEP_NOT_ALLOWED: + VbExBeep(120, 400); + VbExSleepMs(120); + VbExBeep(120, 400); + break; + } +} + +void vb2_error_notify(const char *print_msg, + const char *log_msg, + enum vb2_beep_type beep) +{ + if (print_msg) + VbExDisplayDebugInfo(print_msg, 0); + if (!log_msg) + log_msg = print_msg; + if (log_msg) + VB2_DEBUG(log_msg); + vb2_error_beep(beep); +} + +void vb2_error_no_altfw(void) +{ + VB2_DEBUG("Legacy boot is disabled\n"); + VbExDisplayDebugInfo("WARNING: Booting legacy BIOS has not been " + "enabled. Refer to the developer-mode " + "documentation for details.\n", 0); + vb2_error_beep(VB_BEEP_NOT_ALLOWED); +} + +void vb2_try_altfw(struct vb2_context *ctx, int allowed, + enum VbAltFwIndex_t altfw_num) +{ + if (!allowed) { + vb2_error_no_altfw(); + return; + } + + if (vb2_commit_data(ctx)) { + vb2_error_notify("Error committing data on legacy boot.\n", + NULL, VB_BEEP_FAILED); + return; + } + + /* Will not return if successful */ + VbExLegacy(altfw_num); + + vb2_error_notify("Legacy boot failed. Missing BIOS?\n", NULL, + VB_BEEP_FAILED); +} + +int vb2_want_shutdown(struct vb2_context *ctx, uint32_t key) +{ + struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); + uint32_t shutdown_request = VbExIsShutdownRequested(); + + /* + * 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. 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) { + shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON; + if (power_button_state == POWER_BUTTON_RELEASED) + power_button_state = POWER_BUTTON_PRESSED; + } else { + 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) + shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON; + + /* If desired, ignore shutdown request due to lid closure. */ + if (gbb->flags & VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN) + shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED; + + return shutdown_request; +} diff --git a/firmware/lib/vboot_ui_legacy_menu.c b/firmware/lib/vboot_ui_legacy_menu.c new file mode 100644 index 00000000..2635a7f3 --- /dev/null +++ b/firmware/lib/vboot_ui_legacy_menu.c @@ -0,0 +1,919 @@ +/* Copyright 2017 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. + * + * High-level firmware wrapper API - user interface for RW firmware + */ + +#include "2common.h" +#include "2misc.h" +#include "2nvstorage.h" +#include "2rsa.h" +#include "2secdata.h" +#include "2sysincludes.h" +#include "load_kernel_fw.h" +#include "utility.h" +#include "vb2_common.h" +#include "vboot_api.h" +#include "vboot_audio.h" +#include "vboot_display.h" +#include "vboot_kernel.h" +#include "vboot_struct.h" +#include "vboot_ui_legacy_common.h" +#include "vboot_ui_legacy_menu_private.h" + +static const char dev_disable_msg[] = + "Developer mode is disabled on this device by system policy.\n" + "For more information, see http://dev.chromium.org/chromium-os/fwmp\n" + "\n"; + +static VB_MENU current_menu, prev_menu; +static int current_menu_idx, disabled_idx_mask, usb_nogood, force_redraw; +static uint32_t default_boot; +static uint32_t disable_dev_boot; +static uint32_t altfw_allowed; +static struct vb2_menu menus[]; +static const char no_legacy[] = "Legacy boot failed. Missing BIOS?\n"; + +/** + * Checks GBB flags against VbExIsShutdownRequested() shutdown request to + * determine if a shutdown is required. + * + * Returns true if a shutdown is required and false if no shutdown is required. + */ +static int VbWantShutdownMenu(struct vb2_context *ctx) +{ + struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); + uint32_t shutdown_request = VbExIsShutdownRequested(); + + /* If desired, ignore shutdown request due to lid closure. */ + if (gbb->flags & VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN) + shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED; + + /* + * In detachables, disabling shutdown due to power button. + * We are using it for selection instead. + */ + shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON; + + return !!shutdown_request; +} + +/* (Re-)Draw the menu identified by current_menu[_idx] to the screen. */ +static vb2_error_t vb2_draw_current_screen(struct vb2_context *ctx) { + vb2_error_t ret = VbDisplayMenu(ctx, menus[current_menu].screen, + force_redraw, current_menu_idx, disabled_idx_mask); + force_redraw = 0; + return ret; +} + +/* Flash the screen to black to catch user awareness, then redraw menu. */ +static void vb2_flash_screen(struct vb2_context *ctx) +{ + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); + VbExSleepMs(50); + vb2_draw_current_screen(ctx); +} + +static void vb2_log_menu_change(void) +{ + if (menus[current_menu].size) + VB2_DEBUG("================ %s Menu ================ [ %s ]\n", + menus[current_menu].name, + menus[current_menu].items[current_menu_idx].text); + else + VB2_DEBUG("=============== %s Screen ===============\n", + menus[current_menu].name); +} + +/** + * Switch to a new menu (but don't draw it yet). + * + * @param new_current_menu: new menu to set current_menu to + * @param new_current_menu_idx: new idx to set current_menu_idx to + */ +static void vb2_change_menu(VB_MENU new_current_menu, + int new_current_menu_idx) +{ + prev_menu = current_menu; + current_menu = new_current_menu; + + /* Reconfigure disabled_idx_mask for the new menu */ + disabled_idx_mask = 0; + /* Disable Network Boot Option */ + if (current_menu == VB_MENU_DEV) + disabled_idx_mask |= 1 << VB_DEV_NETWORK; + /* Disable cancel option if enterprise disabled dev mode */ + if (current_menu == VB_MENU_TO_NORM && + disable_dev_boot == 1) + disabled_idx_mask |= 1 << VB_TO_NORM_CANCEL; + + /* Enable menu items for the selected bootloaders */ + if (current_menu == VB_MENU_ALT_FW) { + disabled_idx_mask = ~(VbExGetAltFwIdxMask() >> 1); + + /* Make sure 'cancel' is shown even with an invalid mask */ + disabled_idx_mask &= (1 << VB_ALTFW_COUNT) - 1; + } + /* We assume that there is at least one enabled item */ + while ((1 << new_current_menu_idx) & disabled_idx_mask) + new_current_menu_idx++; + if (new_current_menu_idx < menus[current_menu].size) + current_menu_idx = new_current_menu_idx; + + vb2_log_menu_change(); +} + +/************************ + * Menu Actions * + ************************/ + +/* Boot from internal disk if allowed. */ +static vb2_error_t boot_disk_action(struct vb2_context *ctx) +{ + if (disable_dev_boot) { + vb2_flash_screen(ctx); + vb2_error_notify("Developer mode disabled\n", NULL, + VB_BEEP_NOT_ALLOWED); + return VBERROR_KEEP_LOOPING; + } + VB2_DEBUG("trying fixed disk\n"); + return VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED); +} + +/* Boot legacy BIOS if allowed and available. */ +static vb2_error_t boot_legacy_action(struct vb2_context *ctx) +{ + if (disable_dev_boot) { + vb2_flash_screen(ctx); + vb2_error_notify("Developer mode disabled\n", NULL, + VB_BEEP_NOT_ALLOWED); + return VBERROR_KEEP_LOOPING; + } + + if (!altfw_allowed) { + vb2_flash_screen(ctx); + vb2_error_notify("WARNING: Booting legacy BIOS has not " + "been enabled. Refer to the developer" + "-mode documentation for details.\n", + "Legacy boot is disabled\n", + VB_BEEP_NOT_ALLOWED); + return VBERROR_KEEP_LOOPING; + } + + vb2_try_altfw(ctx, 1, VB_ALTFW_DEFAULT); + vb2_flash_screen(ctx); + return VBERROR_KEEP_LOOPING; +} + +/* Boot from USB or SD card if allowed and available. */ +static vb2_error_t boot_usb_action(struct vb2_context *ctx) +{ + const char no_kernel[] = "No bootable kernel found on USB/SD.\n"; + + if (disable_dev_boot) { + vb2_flash_screen(ctx); + vb2_error_notify("Developer mode disabled\n", NULL, + VB_BEEP_NOT_ALLOWED); + return VBERROR_KEEP_LOOPING; + } + + if (!vb2_nv_get(ctx, VB2_NV_DEV_BOOT_USB) && + !(vb2_get_gbb(ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) && + !vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_USB)) { + vb2_flash_screen(ctx); + vb2_error_notify("WARNING: Booting from external media " + "(USB/SD) has not been enabled. Refer " + "to the developer-mode documentation " + "for details.\n", + "USB booting is disabled\n", + VB_BEEP_NOT_ALLOWED); + return VBERROR_KEEP_LOOPING; + } + + if (VB2_SUCCESS == VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE)) { + VB2_DEBUG("booting USB\n"); + return VB2_SUCCESS; + } + + vb2_flash_screen(ctx); + vb2_error_notify(no_kernel, NULL, VB_BEEP_FAILED); + return VBERROR_KEEP_LOOPING; +} + +static vb2_error_t enter_developer_menu(struct vb2_context *ctx) +{ + int menu_idx; + switch(default_boot) { + default: + case VB2_DEV_DEFAULT_BOOT_DISK: + menu_idx = VB_DEV_DISK; + break; + case VB2_DEV_DEFAULT_BOOT_USB: + menu_idx = VB_DEV_USB; + break; + case VB2_DEV_DEFAULT_BOOT_LEGACY: + menu_idx = VB_DEV_LEGACY; + break; + } + vb2_change_menu(VB_MENU_DEV, menu_idx); + vb2_draw_current_screen(ctx); + return VBERROR_KEEP_LOOPING; +} + +static vb2_error_t enter_dev_warning_menu(struct vb2_context *ctx) +{ + vb2_change_menu(VB_MENU_DEV_WARNING, VB_WARN_POWER_OFF); + vb2_draw_current_screen(ctx); + return VBERROR_KEEP_LOOPING; +} + +static vb2_error_t enter_language_menu(struct vb2_context *ctx) +{ + vb2_change_menu(VB_MENU_LANGUAGES, + vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX)); + vb2_draw_current_screen(ctx); + return VBERROR_KEEP_LOOPING; +} + +static vb2_error_t enter_recovery_base_screen(struct vb2_context *ctx) +{ + if (!vb2_allow_recovery(ctx)) + vb2_change_menu(VB_MENU_RECOVERY_BROKEN, 0); + else if (usb_nogood) + vb2_change_menu(VB_MENU_RECOVERY_NO_GOOD, 0); + else + vb2_change_menu(VB_MENU_RECOVERY_INSERT, 0); + vb2_draw_current_screen(ctx); + return VBERROR_KEEP_LOOPING; +} + +static vb2_error_t enter_options_menu(struct vb2_context *ctx) +{ + vb2_change_menu(VB_MENU_OPTIONS, VB_OPTIONS_CANCEL); + vb2_draw_current_screen(ctx); + return VBERROR_KEEP_LOOPING; +} + +static vb2_error_t enter_to_dev_menu(struct vb2_context *ctx) +{ + const char dev_already_on[] = + "WARNING: TODEV rejected, developer mode is already on.\n"; + if (vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) { + vb2_flash_screen(ctx); + vb2_error_notify(dev_already_on, NULL, VB_BEEP_NOT_ALLOWED); + return VBERROR_KEEP_LOOPING; + } + vb2_change_menu(VB_MENU_TO_DEV, VB_TO_DEV_CANCEL); + vb2_draw_current_screen(ctx); + return VBERROR_KEEP_LOOPING; +} + +static vb2_error_t enter_to_norm_menu(struct vb2_context *ctx) +{ + vb2_change_menu(VB_MENU_TO_NORM, VB_TO_NORM_CONFIRM); + vb2_draw_current_screen(ctx); + /* Make sure user knows dev mode disabled */ + if (disable_dev_boot) + VbExDisplayDebugInfo(dev_disable_msg, 0); + return VBERROR_KEEP_LOOPING; +} + +/* Boot alternative bootloader if allowed and available. */ +static vb2_error_t enter_altfw_menu(struct vb2_context *ctx) +{ + VB2_DEBUG("enter_altfw_menu()\n"); + if (disable_dev_boot) { + vb2_flash_screen(ctx); + vb2_error_beep(VB_BEEP_NOT_ALLOWED); + return VBERROR_KEEP_LOOPING; + } + if (!altfw_allowed) { + vb2_flash_screen(ctx); + vb2_error_no_altfw(); + return VBERROR_KEEP_LOOPING; + } + vb2_change_menu(VB_MENU_ALT_FW, 0); + vb2_draw_current_screen(ctx); + + return VBERROR_KEEP_LOOPING; +} + +static vb2_error_t debug_info_action(struct vb2_context *ctx) +{ + force_redraw = 1; + VbDisplayDebugInfo(ctx); + return VBERROR_KEEP_LOOPING; +} + +/* Action when selecting a language entry in the language menu. */ +static vb2_error_t language_action(struct vb2_context *ctx) +{ + /* Write selected language ID back to NVRAM. */ + vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, current_menu_idx); + + /* + * Non-manual recovery mode is meant to be left via three-finger + * salute (into manual recovery mode). Need to commit nvdata + * changes immediately. Ignore commit errors in recovery mode. + */ + if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE) && + !vb2_allow_recovery(ctx)) + vb2_commit_data(ctx); + + /* Return to previous menu. */ + switch (prev_menu) { + case VB_MENU_DEV_WARNING: + return enter_dev_warning_menu(ctx); + case VB_MENU_DEV: + return enter_developer_menu(ctx); + case VB_MENU_TO_NORM: + return enter_to_norm_menu(ctx); + case VB_MENU_TO_DEV: + return enter_to_dev_menu(ctx); + case VB_MENU_OPTIONS: + return enter_options_menu(ctx); + default: + /* This should never happen. */ + VB2_DEBUG("ERROR: prev_menu state corrupted, force shutdown\n"); + return VBERROR_SHUTDOWN_REQUESTED; + } +} + +/* Action when selecting a bootloader in the alternative firmware menu. */ +static vb2_error_t altfw_action(struct vb2_context *ctx) +{ + vb2_try_altfw(ctx, 1, current_menu_idx + 1); + vb2_flash_screen(ctx); + VB2_DEBUG(no_legacy); + VbExDisplayDebugInfo(no_legacy, 0); + + return VBERROR_KEEP_LOOPING; +} + +/* Action that enables developer mode and reboots. */ +static vb2_error_t to_dev_action(struct vb2_context *ctx) +{ + /* Sanity check, should never happen. */ + if ((vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) || + !vb2_allow_recovery(ctx)) + return VBERROR_KEEP_LOOPING; + + VB2_DEBUG("Enabling dev-mode...\n"); + if (VB2_SUCCESS != vb2_enable_developer_mode(ctx)) + return VBERROR_TPM_SET_BOOT_MODE_STATE; + + /* This was meant for headless devices, shouldn't really matter here. */ + if (USB_BOOT_ON_DEV) + vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 1); + + VB2_DEBUG("Reboot so it will take effect\n"); + return VBERROR_REBOOT_REQUIRED; +} + +/* Action that disables developer mode, shows TO_NORM_CONFIRMED and reboots. */ +static vb2_error_t to_norm_action(struct vb2_context *ctx) +{ + if (vb2_get_gbb(ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { + vb2_flash_screen(ctx); + vb2_error_notify("WARNING: TONORM prohibited by " + "GBB FORCE_DEV_SWITCH_ON.\n", NULL, + VB_BEEP_NOT_ALLOWED); + return VBERROR_KEEP_LOOPING; + } + + VB2_DEBUG("leaving dev-mode.\n"); + vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); + vb2_change_menu(VB_MENU_TO_NORM_CONFIRMED, 0); + vb2_draw_current_screen(ctx); + VbExSleepMs(5000); + return VBERROR_REBOOT_REQUIRED; +} + +/* Action that will power off the system. */ +static vb2_error_t power_off_action(struct vb2_context *ctx) +{ + VB2_DEBUG("Power off requested from screen %#x\n", + menus[current_menu].screen); + return VBERROR_SHUTDOWN_REQUESTED; +} + +/** + * Updates current_menu_idx upon an up/down key press, taking into + * account disabled indices (from disabled_idx_mask). The cursor + * will not wrap, meaning that we block on the 0 or max index when + * we hit the ends of the menu. + * + * @param key VOL_KEY_UP = increase index selection + * VOL_KEY_DOWN = decrease index selection. + * Every other key has no effect now. + */ +static void vb2_update_selection(uint32_t key) { + int idx; + + switch (key) { + case VB_BUTTON_VOL_UP_SHORT_PRESS: + case VB_KEY_UP: + idx = current_menu_idx - 1; + while (idx >= 0 && + ((1 << idx) & disabled_idx_mask)) + idx--; + /* Only update if idx is valid */ + if (idx >= 0) + current_menu_idx = idx; + break; + case VB_BUTTON_VOL_DOWN_SHORT_PRESS: + case VB_KEY_DOWN: + idx = current_menu_idx + 1; + while (idx < menus[current_menu].size && + ((1 << idx) & disabled_idx_mask)) + idx++; + /* Only update if idx is valid */ + if (idx < menus[current_menu].size) + current_menu_idx = idx; + break; + default: + VB2_DEBUG("ERROR: %s called with key %#x!\n", __func__, key); + break; + } + + vb2_log_menu_change(); +} + +static vb2_error_t vb2_handle_menu_input(struct vb2_context *ctx, + uint32_t key, uint32_t key_flags) +{ + switch (key) { + case 0: + /* nothing pressed */ + break; + case '\t': + /* Tab = display debug info */ + return debug_info_action(ctx); + case VB_KEY_ESC: + /* Esc = redraw screen (to clear old debug info) */ + vb2_draw_current_screen(ctx); + break; + case VB_KEY_UP: + case VB_KEY_DOWN: + case VB_BUTTON_VOL_UP_SHORT_PRESS: + case VB_BUTTON_VOL_DOWN_SHORT_PRESS: + /* Untrusted (USB keyboard) input disabled for TO_DEV menu. */ + if (current_menu == VB_MENU_TO_DEV && + !(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) { + vb2_flash_screen(ctx); + vb2_error_notify("Please use the on-device volume " + "buttons to navigate\n", + "vb2_handle_menu_input() - Untrusted " + "(USB keyboard) input disabled\n", + VB_BEEP_NOT_ALLOWED); + break; + } + + /* Menuless screens enter OPTIONS on volume button press. */ + if (!menus[current_menu].size) { + enter_options_menu(ctx); + break; + } + + vb2_update_selection(key); + vb2_draw_current_screen(ctx); + break; + case VB_BUTTON_POWER_SHORT_PRESS: + case VB_KEY_ENTER: + /* Menuless screens shut down on power button press. */ + if (!menus[current_menu].size) + return VBERROR_SHUTDOWN_REQUESTED; + + return menus[current_menu].items[current_menu_idx].action(ctx); + default: + VB2_DEBUG("pressed key %#x\n", key); + break; + } + + if (VbWantShutdownMenu(ctx)) { + VB2_DEBUG("shutdown requested!\n"); + return VBERROR_SHUTDOWN_REQUESTED; + } + + return VBERROR_KEEP_LOOPING; +} + +/* Master table of all menus. Menus with size == 0 count as menuless screens. */ +static struct vb2_menu menus[VB_MENU_COUNT] = { + [VB_MENU_DEV_WARNING] = { + .name = "Developer Warning", + .size = VB_WARN_COUNT, + .screen = VB_SCREEN_DEVELOPER_WARNING_MENU, + .items = (struct vb2_menu_item[]){ + [VB_WARN_OPTIONS] = { + .text = "Developer Options", + .action = enter_developer_menu, + }, + [VB_WARN_DBG_INFO] = { + .text = "Show Debug Info", + .action = debug_info_action, + }, + [VB_WARN_ENABLE_VER] = { + .text = "Enable OS Verification", + .action = enter_to_norm_menu, + }, + [VB_WARN_POWER_OFF] = { + .text = "Power Off", + .action = power_off_action, + }, + [VB_WARN_LANGUAGE] = { + .text = "Language", + .action = enter_language_menu, + }, + }, + }, + [VB_MENU_DEV] = { + .name = "Developer Boot Options", + .size = VB_DEV_COUNT, + .screen = VB_SCREEN_DEVELOPER_MENU, + .items = (struct vb2_menu_item[]){ + [VB_DEV_NETWORK] = { + .text = "Boot From Network", + .action = NULL, /* unimplemented */ + }, + [VB_DEV_LEGACY] = { + .text = "Boot Legacy BIOS", + .action = enter_altfw_menu, + }, + [VB_DEV_USB] = { + .text = "Boot From USB or SD Card", + .action = boot_usb_action, + }, + [VB_DEV_DISK] = { + .text = "Boot From Internal Disk", + .action = boot_disk_action, + }, + [VB_DEV_CANCEL] = { + .text = "Cancel", + .action = enter_dev_warning_menu, + }, + [VB_DEV_POWER_OFF] = { + .text = "Power Off", + .action = power_off_action, + }, + [VB_DEV_LANGUAGE] = { + .text = "Language", + .action = enter_language_menu, + }, + }, + }, + [VB_MENU_TO_NORM] = { + .name = "TO_NORM Confirmation", + .size = VB_TO_NORM_COUNT, + .screen = VB_SCREEN_DEVELOPER_TO_NORM_MENU, + .items = (struct vb2_menu_item[]){ + [VB_TO_NORM_CONFIRM] = { + .text = "Confirm Enabling OS Verification", + .action = to_norm_action, + }, + [VB_TO_NORM_CANCEL] = { + .text = "Cancel", + .action = enter_dev_warning_menu, + }, + [VB_TO_NORM_POWER_OFF] = { + .text = "Power Off", + .action = power_off_action, + }, + [VB_TO_NORM_LANGUAGE] = { + .text = "Language", + .action = enter_language_menu, + }, + }, + }, + [VB_MENU_TO_DEV] = { + .name = "TO_DEV Confirmation", + .size = VB_TO_DEV_COUNT, + .screen = VB_SCREEN_RECOVERY_TO_DEV_MENU, + .items = (struct vb2_menu_item[]){ + [VB_TO_DEV_CONFIRM] = { + .text = "Confirm Disabling OS Verification", + .action = to_dev_action, + }, + [VB_TO_DEV_CANCEL] = { + .text = "Cancel", + .action = enter_recovery_base_screen, + }, + [VB_TO_DEV_POWER_OFF] = { + .text = "Power Off", + .action = power_off_action, + }, + [VB_TO_DEV_LANGUAGE] = { + .text = "Language", + .action = enter_language_menu, + }, + }, + }, + [VB_MENU_LANGUAGES] = { + .name = "Language Selection", + .screen = VB_SCREEN_LANGUAGES_MENU, + /* Rest is filled out dynamically by vb2_init_menus() */ + }, + [VB_MENU_OPTIONS] = { + .name = "Options", + .size = VB_OPTIONS_COUNT, + .screen = VB_SCREEN_OPTIONS_MENU, + .items = (struct vb2_menu_item[]){ + [VB_OPTIONS_DBG_INFO] = { + .text = "Show Debug Info", + .action = debug_info_action, + }, + [VB_OPTIONS_CANCEL] = { + .text = "Cancel", + .action = enter_recovery_base_screen, + }, + [VB_OPTIONS_POWER_OFF] = { + .text = "Power Off", + .action = power_off_action, + }, + [VB_OPTIONS_LANGUAGE] = { + .text = "Language", + .action = enter_language_menu, + }, + }, + }, + [VB_MENU_RECOVERY_INSERT] = { + .name = "Recovery INSERT", + .size = 0, + .screen = VB_SCREEN_RECOVERY_INSERT, + .items = NULL, + }, + [VB_MENU_RECOVERY_NO_GOOD] = { + .name = "Recovery NO_GOOD", + .size = 0, + .screen = VB_SCREEN_RECOVERY_NO_GOOD, + .items = NULL, + }, + [VB_MENU_RECOVERY_BROKEN] = { + .name = "Non-manual Recovery (BROKEN)", + .size = 0, + .screen = VB_SCREEN_OS_BROKEN, + .items = NULL, + }, + [VB_MENU_TO_NORM_CONFIRMED] = { + .name = "TO_NORM Interstitial", + .size = 0, + .screen = VB_SCREEN_TO_NORM_CONFIRMED, + .items = NULL, + }, + [VB_MENU_ALT_FW] = { + .name = "Alternative Firmware Selection", + .screen = VB_SCREEN_ALT_FW_MENU, + .size = VB_ALTFW_COUNT + 1, + .items = (struct vb2_menu_item[]) {{ + .text = "Bootloader 1", + .action = altfw_action, + }, { + .text = "Bootloader 2", + .action = altfw_action, + }, { + .text = "Bootloader 3", + .action = altfw_action, + }, { + .text = "Bootloader 4", + .action = altfw_action, + }, { + .text = "Bootloader 5", + .action = altfw_action, + }, { + .text = "Bootloader 6", + .action = altfw_action, + }, { + .text = "Bootloader 7", + .action = altfw_action, + }, { + .text = "Bootloader 8", + .action = altfw_action, + }, { + .text = "Bootloader 9", + .action = altfw_action, + }, { + .text = "Cancel", + .action = enter_developer_menu, + }, + }, + }, +}; + +/* Initialize menu state. Must be called once before displaying any menus. */ +static vb2_error_t vb2_init_menus(struct vb2_context *ctx) +{ + struct vb2_menu_item *items; + uint32_t count; + int i; + + /* Initialize language menu with the correct amount of entries. */ + if (VB2_SUCCESS != VbExGetLocalizationCount(&count) || count == 0) + count = 1; /* Fall back to 1 language entry on failure */ + + items = malloc(count * sizeof(struct vb2_menu_item)); + if (!items) + return VB2_ERROR_UNKNOWN; + + for (i = 0; i < count; i++) { + /* The actual language is drawn by the bootloader */ + items[i].text = "Some Language"; + items[i].action = language_action; + } + menus[VB_MENU_LANGUAGES].size = count; + menus[VB_MENU_LANGUAGES].items = items; + + return VB2_SUCCESS; +} + +/** + * Main function that handles developer warning menu functionality + * + * @param ctx Vboot2 context + * @return VB2_SUCCESS, or non-zero error code if error. + */ +static vb2_error_t vb2_developer_legacy_menu(struct vb2_context *ctx) +{ + struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); + vb2_error_t ret; + + /* Check if the default is to boot using disk, usb, or legacy */ + default_boot = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT); + if (gbb->flags & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) + default_boot = VB2_DEV_DEFAULT_BOOT_LEGACY; + + /* Check if developer mode is disabled by FWMP */ + disable_dev_boot = 0; + if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_DISABLE_BOOT)) { + if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { + VB2_DEBUG("FWMP_DEV_DISABLE_BOOT rejected by" + "FORCE_DEV_SWITCH_ON\n"); + } else { + /* If dev mode is disabled, only allow TONORM */ + disable_dev_boot = 1; + VB2_DEBUG("dev_disable_boot is set.\n"); + } + } + + altfw_allowed = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY) || + (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY) || + vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY); + + /* Show appropriate initial menu */ + if (disable_dev_boot) + enter_to_norm_menu(ctx); + else + enter_dev_warning_menu(ctx); + + /* Get audio/delay context */ + vb2_audio_start(ctx); + + /* We'll loop until we finish the delay or are interrupted */ + do { + uint32_t key = VbExKeyboardRead(); + + switch (key) { + case VB_BUTTON_VOL_DOWN_LONG_PRESS: + case VB_KEY_CTRL('D'): + /* Ctrl+D = boot from internal disk */ + ret = boot_disk_action(ctx); + break; + case VB_KEY_CTRL('L'): + /* Ctrl+L = boot alternative bootloader */ + ret = enter_altfw_menu(ctx); + break; + case VB_BUTTON_VOL_UP_LONG_PRESS: + case VB_KEY_CTRL('U'): + /* Ctrl+U = boot from USB or SD card */ + ret = boot_usb_action(ctx); + break; + /* We allow selection of the default '0' bootloader here */ + case '0'...'9': + VB2_DEBUG("developer UI - " + "user pressed key '%c': Boot alternative " + "firmware\n", key); + vb2_try_altfw(ctx, altfw_allowed, key - '0'); + ret = VBERROR_KEEP_LOOPING; + break; + default: + ret = vb2_handle_menu_input(ctx, key, 0); + break; + } + + /* We may have loaded a kernel or decided to shut down now. */ + if (ret != VBERROR_KEEP_LOOPING) + return ret; + + /* Reset 30 second timer whenever we see a new key. */ + if (key != 0) + vb2_audio_start(ctx); + + VbExSleepMs(KEY_DELAY_MS); + + /* If dev mode was disabled, loop forever (never timeout) */ + } while (disable_dev_boot ? 1 : vb2_audio_looping()); + + if (default_boot == VB2_DEV_DEFAULT_BOOT_LEGACY) + boot_legacy_action(ctx); /* Doesn't return on success. */ + + if (default_boot == VB2_DEV_DEFAULT_BOOT_USB) + if (VB2_SUCCESS == boot_usb_action(ctx)) + return VB2_SUCCESS; + + return boot_disk_action(ctx); +} + +/* Developer mode entry point. */ +vb2_error_t VbBootDeveloperLegacyMenu(struct vb2_context *ctx) +{ + vb2_error_t retval = vb2_init_menus(ctx); + if (VB2_SUCCESS != retval) + return retval; + retval = vb2_developer_legacy_menu(ctx); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); + return retval; +} + +/* Main function that handles non-manual recovery (BROKEN) menu functionality */ +static vb2_error_t broken_ui(struct vb2_context *ctx) +{ + VbSharedDataHeader *vbsd = vb2_get_sd(ctx)->vbsd; + + /* + * Temporarily stash recovery reason in subcode so we'll still know what + * to display if the user reboots into manual recovery from here. Commit + * immediately since the user may hard-reset out of here. + */ + VB2_DEBUG("saving recovery reason (%#x)\n", vbsd->recovery_reason); + vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, vbsd->recovery_reason); + + /* Ignore commit errors in recovery mode. */ + vb2_commit_data(ctx); + + enter_recovery_base_screen(ctx); + + /* Loop and wait for the user to reset or shut down. */ + VB2_DEBUG("waiting for manual recovery\n"); + while (1) { + uint32_t key = VbExKeyboardRead(); + vb2_error_t ret = vb2_handle_menu_input(ctx, key, 0); + if (ret != VBERROR_KEEP_LOOPING) + return ret; + } +} + +/** + * Main function that handles recovery menu functionality + * + * @param ctx Vboot2 context + * @return VB2_SUCCESS, or non-zero error code if error. + */ +static vb2_error_t recovery_ui(struct vb2_context *ctx) +{ + uint32_t key; + uint32_t key_flags; + vb2_error_t ret; + + /* Loop and wait for a recovery image */ + VB2_DEBUG("waiting for a recovery image\n"); + usb_nogood = -1; + while (1) { + ret = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE); + + if (VB2_SUCCESS == ret) + return ret; /* Found a recovery kernel */ + + if (usb_nogood != (ret != VB2_ERROR_LK_NO_DISK_FOUND)) { + /* USB state changed, force back to base screen */ + usb_nogood = ret != VB2_ERROR_LK_NO_DISK_FOUND; + enter_recovery_base_screen(ctx); + } + + key = VbExKeyboardReadWithFlags(&key_flags); + if (key == VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS) { + if (key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD) + enter_to_dev_menu(ctx); + else + VB2_DEBUG("ERROR: untrusted combo?!\n"); + } else { + ret = vb2_handle_menu_input(ctx, key, key_flags); + if (ret != VBERROR_KEEP_LOOPING) + return ret; + } + VbExSleepMs(KEY_DELAY_MS); + } +} + +/* Recovery mode entry point. */ +vb2_error_t VbBootRecoveryLegacyMenu(struct vb2_context *ctx) +{ + vb2_error_t retval = vb2_init_menus(ctx); + if (VB2_SUCCESS != retval) + return retval; + if (vb2_allow_recovery(ctx)) + retval = recovery_ui(ctx); + else + retval = broken_ui(ctx); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); + return retval; +} diff --git a/firmware/lib/vboot_ui_legacy_wilco.c b/firmware/lib/vboot_ui_legacy_wilco.c new file mode 100644 index 00000000..b814c249 --- /dev/null +++ b/firmware/lib/vboot_ui_legacy_wilco.c @@ -0,0 +1,350 @@ +/* Copyright 2020 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. + * + * Common code used by both vboot_ui and Wilco-specific + * feature support for vboot_ui + */ + +#include "2common.h" +#include "2nvstorage.h" +#include "2sysincludes.h" +#include "vboot_api.h" +#include "vboot_display.h" +#include "vboot_ui_legacy_common.h" +#include "vboot_ui_legacy_wilco.h" + +static inline int is_vowel(uint32_t key) +{ + return key == 'A' || key == 'E' || key == 'I' || + key == 'O' || key == 'U'; +} + +static int vendor_data_length(char *data_value) +{ + for (int len = 0; len <= VENDOR_DATA_LENGTH; len++) { + if (data_value[len] == '\0') + return len; + } + + return VENDOR_DATA_LENGTH; +} + +/* + * Prompt the user to enter the serial number + */ +static vb2_error_t vb2_enter_vendor_data_ui(struct vb2_context *ctx, + char *data_value) +{ + int len = vendor_data_length(data_value); + VbScreenData data = {.vendor_data = {data_value, 1}}; + + VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, 1, &data); + + /* We'll loop until the user decides what to do */ + do { + uint32_t key = VbExKeyboardRead(); + + if (vb2_want_shutdown(ctx, key)) { + VB2_DEBUG("Vendor Data UI - shutdown requested!\n"); + return VBERROR_SHUTDOWN_REQUESTED; + } + switch (key) { + case 0: + /* Nothing pressed */ + break; + case VB_KEY_ESC: + /* Escape pressed - return to developer screen */ + VB2_DEBUG("Vendor Data UI - user pressed Esc: " + "exit to Developer screen\n"); + data_value[0] = '\0'; + return VB2_SUCCESS; + case 'a'...'z': + key = toupper(key); + __attribute__ ((fallthrough)); + case '0'...'9': + case 'A'...'Z': + if ((len > 0 && is_vowel(key)) || + len >= VENDOR_DATA_LENGTH) { + vb2_error_beep(VB_BEEP_NOT_ALLOWED); + } else { + data_value[len++] = key; + data_value[len] = '\0'; + VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, + 1, &data); + } + + VB2_DEBUG("Vendor Data UI - vendor_data: %s\n", + data_value); + break; + case VB_KEY_BACKSPACE: + if (len > 0) { + data_value[--len] = '\0'; + VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, + 1, &data); + } + + VB2_DEBUG("Vendor Data UI - vendor_data: %s\n", + data_value); + break; + case VB_KEY_ENTER: + if (len == VENDOR_DATA_LENGTH) { + /* Enter pressed - confirm input */ + VB2_DEBUG("Vendor Data UI - user pressed " + "Enter: confirm vendor data\n"); + return VB2_SUCCESS; + } else { + vb2_error_beep(VB_BEEP_NOT_ALLOWED); + } + break; + default: + VB2_DEBUG("Vendor Data UI - pressed key %#x\n", key); + VbCheckDisplayKey(ctx, key, &data); + break; + } + VbExSleepMs(KEY_DELAY_MS); + } while (1); + + return VB2_SUCCESS; +} + +/* + * Prompt the user to confirm the serial number and write to memory + */ +static vb2_error_t vb2_confirm_vendor_data_ui(struct vb2_context *ctx, + char* data_value, VbScreenData *data) +{ + VbDisplayScreen(ctx, VB_SCREEN_CONFIRM_VENDOR_DATA, 1, data); + /* We'll loop until the user decides what to do */ + do { + uint32_t key_confirm = VbExKeyboardRead(); + + if (vb2_want_shutdown(ctx, key_confirm)) { + VB2_DEBUG("Confirm Vendor Data UI " + "- shutdown requested!\n"); + return VBERROR_SHUTDOWN_REQUESTED; + } + switch (key_confirm) { + case 0: + /* Nothing pressed */ + break; + case VB_KEY_ESC: + /* Escape pressed - return to developer screen */ + VB2_DEBUG("Confirm Vendor Data UI - user " + "pressed Esc: exit to Developer screen\n"); + return VB2_SUCCESS; + case VB_KEY_RIGHT: + case VB_KEY_LEFT: + data->vendor_data.selected_index = + data->vendor_data.selected_index ^ 1; + VbDisplayScreen(ctx, VB_SCREEN_CONFIRM_VENDOR_DATA, + 1, data); + VB2_DEBUG("selected_index:%d\n", + data->vendor_data.selected_index); + break; + case VB_KEY_ENTER: + /* Enter pressed - write vendor data */ + if (data->vendor_data.selected_index == 0) { + VB2_DEBUG("Confirm Vendor Data UI - user " + "selected YES: " + "write vendor data (%s) to VPD\n", + data_value); + vb2_error_t ret = VbExSetVendorData(data_value); + + if (ret == VB2_SUCCESS) { + vb2_nv_set(ctx, + VB2_NV_DISABLE_DEV_REQUEST, + 1); + return VBERROR_REBOOT_REQUIRED; + } else { + vb2_error_notify( + "ERROR: Vendor data was not " + "set.\n" + "System will now shutdown\n", + NULL, VB_BEEP_FAILED); + VbExSleepMs(5000); + return VBERROR_SHUTDOWN_REQUESTED; + } + } else { + VB2_DEBUG("Confirm Vendor Data UI - user " + "selected NO: " + "Returning to set screen\n"); + return VB2_SUCCESS; + } + default: + VB2_DEBUG("Confirm Vendor Data UI - pressed " + "key %#x\n", key_confirm); + VbCheckDisplayKey(ctx, key_confirm, data); + break; + } + VbExSleepMs(KEY_DELAY_MS); + } while (1); + return VB2_SUCCESS; +} + +vb2_error_t vb2_vendor_data_ui(struct vb2_context *ctx) +{ + char data_value[VENDOR_DATA_LENGTH + 1]; + + VbScreenData data = {.vendor_data = {data_value, 0}}; + VbDisplayScreen(ctx, VB_COMPLETE_VENDOR_DATA, 0, NULL); + + do { + uint32_t key_set = VbExKeyboardRead(); + + if (vb2_want_shutdown(ctx, key_set)) { + VB2_DEBUG("Vendor Data UI - shutdown requested!\n"); + return VBERROR_SHUTDOWN_REQUESTED; + } + + switch (key_set) { + case 0: + /* Nothing pressed - do nothing. */ + break; + case VB_KEY_ESC: + /* ESC pressed - boot normally */ + VB2_DEBUG("Vendor Data UI - boot normally\n"); + return VB2_SUCCESS; + break; + case VB_KEY_ENTER: + data_value[0] = '\0'; + do { + /* ENTER pressed - + enter vendor data set screen */ + VB2_DEBUG("Vendor Data UI - Enter VD set " + "screen\n"); + vb2_error_t ret = vb2_enter_vendor_data_ui( + ctx, data_value); + + if (ret) + return ret; + + /* Vendor data was not entered just return */ + if (vendor_data_length(data_value) == 0) { + return VB2_SUCCESS; + } + + /* Reset confirmation answer to YES */ + data.vendor_data.selected_index = 0; + + ret = vb2_confirm_vendor_data_ui( + ctx, data_value, &data); + + if (ret) + return ret; + + /* Break if vendor data confirmed */ + if (data.vendor_data.selected_index == 0) + return VB2_SUCCESS; + } while (1); + break; + default: + break; + } + } while (1); + return VB2_SUCCESS; +} + +vb2_error_t vb2_check_diagnostic_key(struct vb2_context *ctx, + uint32_t key) { + if (DIAGNOSTIC_UI && (key == VB_KEY_CTRL('C') || key == VB_KEY_F(12))) { + VB2_DEBUG("Diagnostic mode requested, rebooting\n"); + vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); + + return VBERROR_REBOOT_REQUIRED; + } + + return VB2_SUCCESS; +} + +vb2_error_t vb2_diagnostics_ui(struct vb2_context *ctx) +{ + int active = 1; + int power_button_was_released = 0; + int power_button_was_pressed = 0; + vb2_error_t result = VBERROR_REBOOT_REQUIRED; + int action_confirmed = 0; + uint64_t start_time_us; + + VbDisplayScreen(ctx, VB_SCREEN_CONFIRM_DIAG, 0, NULL); + + start_time_us = VbExGetTimer(); + + /* We'll loop until the user decides what to do */ + do { + uint32_t key = VbExKeyboardRead(); + /* + * VbExIsShutdownRequested() is almost an adequate substitute + * for adding a new flag to VbExGetSwitches(). The main + * issue is that the former doesn't consult the power button + * on detachables, and this function wants to see for itself + * that the power button isn't currently pressed. + */ + if (VbExGetSwitches(VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED)) { + /* Wait for a release before registering a press. */ + if (power_button_was_released) + power_button_was_pressed = 1; + } else { + power_button_was_released = 1; + if (power_button_was_pressed) { + VB2_DEBUG("vb2_diagnostics_ui() - power released\n"); + action_confirmed = 1; + active = 0; + break; + } + } + + /* Check the lid and ignore the power button. */ + if (vb2_want_shutdown(ctx, 0) & ~VB_SHUTDOWN_REQUEST_POWER_BUTTON) { + VB2_DEBUG("vb2_diagnostics_ui() - shutdown request\n"); + result = VBERROR_SHUTDOWN_REQUESTED; + active = 0; + break; + } + + switch (key) { + case 0: + /* Nothing pressed */ + break; + case VB_KEY_ESC: + /* Escape pressed - reboot */ + VB2_DEBUG("vb2_diagnostics_ui() - user pressed Esc\n"); + active = 0; + break; + default: + VB2_DEBUG("vb2_diagnostics_ui() - pressed key %#x\n", + key); + VbCheckDisplayKey(ctx, key, NULL); + break; + } + if (VbExGetTimer() - start_time_us >= 30 * VB_USEC_PER_SEC) { + VB2_DEBUG("vb2_diagnostics_ui() - timeout\n"); + break; + } + if (active) { + VbExSleepMs(KEY_DELAY_MS); + } + } while (active); + + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); + + if (action_confirmed) { + VB2_DEBUG("Diagnostic requested, running\n"); + + if (vb2ex_tpm_set_mode(VB2_TPM_MODE_DISABLED) != + VB2_SUCCESS) { + VB2_DEBUG("Failed to disable TPM\n"); + vb2api_fail(ctx, VB2_RECOVERY_TPM_DISABLE_FAILED, 0); + } else { + vb2_try_altfw(ctx, 1, VB_ALTFW_DIAGNOSTIC); + VB2_DEBUG("Diagnostic failed to run\n"); + /* + * Assuming failure was due to bad hash, though + * the rom could just be missing or invalid. + */ + vb2api_fail(ctx, VB2_RECOVERY_ALTFW_HASH_FAILED, 0); + } + } + + return result; +} diff --git a/firmware/lib/vboot_ui_menu.c b/firmware/lib/vboot_ui_menu.c deleted file mode 100644 index 8b6ed18e..00000000 --- a/firmware/lib/vboot_ui_menu.c +++ /dev/null @@ -1,919 +0,0 @@ -/* Copyright 2017 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. - * - * High-level firmware wrapper API - user interface for RW firmware - */ - -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2rsa.h" -#include "2secdata.h" -#include "2sysincludes.h" -#include "load_kernel_fw.h" -#include "utility.h" -#include "vb2_common.h" -#include "vboot_api.h" -#include "vboot_audio.h" -#include "vboot_display.h" -#include "vboot_kernel.h" -#include "vboot_struct.h" -#include "vboot_ui_common.h" -#include "vboot_ui_menu_private.h" - -static const char dev_disable_msg[] = - "Developer mode is disabled on this device by system policy.\n" - "For more information, see http://dev.chromium.org/chromium-os/fwmp\n" - "\n"; - -static VB_MENU current_menu, prev_menu; -static int current_menu_idx, disabled_idx_mask, usb_nogood, force_redraw; -static uint32_t default_boot; -static uint32_t disable_dev_boot; -static uint32_t altfw_allowed; -static struct vb2_menu menus[]; -static const char no_legacy[] = "Legacy boot failed. Missing BIOS?\n"; - -/** - * Checks GBB flags against VbExIsShutdownRequested() shutdown request to - * determine if a shutdown is required. - * - * Returns true if a shutdown is required and false if no shutdown is required. - */ -static int VbWantShutdownMenu(struct vb2_context *ctx) -{ - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - uint32_t shutdown_request = VbExIsShutdownRequested(); - - /* If desired, ignore shutdown request due to lid closure. */ - if (gbb->flags & VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN) - shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED; - - /* - * In detachables, disabling shutdown due to power button. - * We are using it for selection instead. - */ - shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON; - - return !!shutdown_request; -} - -/* (Re-)Draw the menu identified by current_menu[_idx] to the screen. */ -static vb2_error_t vb2_draw_current_screen(struct vb2_context *ctx) { - vb2_error_t ret = VbDisplayMenu(ctx, menus[current_menu].screen, - force_redraw, current_menu_idx, disabled_idx_mask); - force_redraw = 0; - return ret; -} - -/* Flash the screen to black to catch user awareness, then redraw menu. */ -static void vb2_flash_screen(struct vb2_context *ctx) -{ - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - VbExSleepMs(50); - vb2_draw_current_screen(ctx); -} - -static void vb2_log_menu_change(void) -{ - if (menus[current_menu].size) - VB2_DEBUG("================ %s Menu ================ [ %s ]\n", - menus[current_menu].name, - menus[current_menu].items[current_menu_idx].text); - else - VB2_DEBUG("=============== %s Screen ===============\n", - menus[current_menu].name); -} - -/** - * Switch to a new menu (but don't draw it yet). - * - * @param new_current_menu: new menu to set current_menu to - * @param new_current_menu_idx: new idx to set current_menu_idx to - */ -static void vb2_change_menu(VB_MENU new_current_menu, - int new_current_menu_idx) -{ - prev_menu = current_menu; - current_menu = new_current_menu; - - /* Reconfigure disabled_idx_mask for the new menu */ - disabled_idx_mask = 0; - /* Disable Network Boot Option */ - if (current_menu == VB_MENU_DEV) - disabled_idx_mask |= 1 << VB_DEV_NETWORK; - /* Disable cancel option if enterprise disabled dev mode */ - if (current_menu == VB_MENU_TO_NORM && - disable_dev_boot == 1) - disabled_idx_mask |= 1 << VB_TO_NORM_CANCEL; - - /* Enable menu items for the selected bootloaders */ - if (current_menu == VB_MENU_ALT_FW) { - disabled_idx_mask = ~(VbExGetAltFwIdxMask() >> 1); - - /* Make sure 'cancel' is shown even with an invalid mask */ - disabled_idx_mask &= (1 << VB_ALTFW_COUNT) - 1; - } - /* We assume that there is at least one enabled item */ - while ((1 << new_current_menu_idx) & disabled_idx_mask) - new_current_menu_idx++; - if (new_current_menu_idx < menus[current_menu].size) - current_menu_idx = new_current_menu_idx; - - vb2_log_menu_change(); -} - -/************************ - * Menu Actions * - ************************/ - -/* Boot from internal disk if allowed. */ -static vb2_error_t boot_disk_action(struct vb2_context *ctx) -{ - if (disable_dev_boot) { - vb2_flash_screen(ctx); - vb2_error_notify("Developer mode disabled\n", NULL, - VB_BEEP_NOT_ALLOWED); - return VBERROR_KEEP_LOOPING; - } - VB2_DEBUG("trying fixed disk\n"); - return VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED); -} - -/* Boot legacy BIOS if allowed and available. */ -static vb2_error_t boot_legacy_action(struct vb2_context *ctx) -{ - if (disable_dev_boot) { - vb2_flash_screen(ctx); - vb2_error_notify("Developer mode disabled\n", NULL, - VB_BEEP_NOT_ALLOWED); - return VBERROR_KEEP_LOOPING; - } - - if (!altfw_allowed) { - vb2_flash_screen(ctx); - vb2_error_notify("WARNING: Booting legacy BIOS has not " - "been enabled. Refer to the developer" - "-mode documentation for details.\n", - "Legacy boot is disabled\n", - VB_BEEP_NOT_ALLOWED); - return VBERROR_KEEP_LOOPING; - } - - vb2_try_altfw(ctx, 1, VB_ALTFW_DEFAULT); - vb2_flash_screen(ctx); - return VBERROR_KEEP_LOOPING; -} - -/* Boot from USB or SD card if allowed and available. */ -static vb2_error_t boot_usb_action(struct vb2_context *ctx) -{ - const char no_kernel[] = "No bootable kernel found on USB/SD.\n"; - - if (disable_dev_boot) { - vb2_flash_screen(ctx); - vb2_error_notify("Developer mode disabled\n", NULL, - VB_BEEP_NOT_ALLOWED); - return VBERROR_KEEP_LOOPING; - } - - if (!vb2_nv_get(ctx, VB2_NV_DEV_BOOT_USB) && - !(vb2_get_gbb(ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) && - !vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_USB)) { - vb2_flash_screen(ctx); - vb2_error_notify("WARNING: Booting from external media " - "(USB/SD) has not been enabled. Refer " - "to the developer-mode documentation " - "for details.\n", - "USB booting is disabled\n", - VB_BEEP_NOT_ALLOWED); - return VBERROR_KEEP_LOOPING; - } - - if (VB2_SUCCESS == VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE)) { - VB2_DEBUG("booting USB\n"); - return VB2_SUCCESS; - } - - vb2_flash_screen(ctx); - vb2_error_notify(no_kernel, NULL, VB_BEEP_FAILED); - return VBERROR_KEEP_LOOPING; -} - -static vb2_error_t enter_developer_menu(struct vb2_context *ctx) -{ - int menu_idx; - switch(default_boot) { - default: - case VB2_DEV_DEFAULT_BOOT_DISK: - menu_idx = VB_DEV_DISK; - break; - case VB2_DEV_DEFAULT_BOOT_USB: - menu_idx = VB_DEV_USB; - break; - case VB2_DEV_DEFAULT_BOOT_LEGACY: - menu_idx = VB_DEV_LEGACY; - break; - } - vb2_change_menu(VB_MENU_DEV, menu_idx); - vb2_draw_current_screen(ctx); - return VBERROR_KEEP_LOOPING; -} - -static vb2_error_t enter_dev_warning_menu(struct vb2_context *ctx) -{ - vb2_change_menu(VB_MENU_DEV_WARNING, VB_WARN_POWER_OFF); - vb2_draw_current_screen(ctx); - return VBERROR_KEEP_LOOPING; -} - -static vb2_error_t enter_language_menu(struct vb2_context *ctx) -{ - vb2_change_menu(VB_MENU_LANGUAGES, - vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX)); - vb2_draw_current_screen(ctx); - return VBERROR_KEEP_LOOPING; -} - -static vb2_error_t enter_recovery_base_screen(struct vb2_context *ctx) -{ - if (!vb2_allow_recovery(ctx)) - vb2_change_menu(VB_MENU_RECOVERY_BROKEN, 0); - else if (usb_nogood) - vb2_change_menu(VB_MENU_RECOVERY_NO_GOOD, 0); - else - vb2_change_menu(VB_MENU_RECOVERY_INSERT, 0); - vb2_draw_current_screen(ctx); - return VBERROR_KEEP_LOOPING; -} - -static vb2_error_t enter_options_menu(struct vb2_context *ctx) -{ - vb2_change_menu(VB_MENU_OPTIONS, VB_OPTIONS_CANCEL); - vb2_draw_current_screen(ctx); - return VBERROR_KEEP_LOOPING; -} - -static vb2_error_t enter_to_dev_menu(struct vb2_context *ctx) -{ - const char dev_already_on[] = - "WARNING: TODEV rejected, developer mode is already on.\n"; - if (vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) { - vb2_flash_screen(ctx); - vb2_error_notify(dev_already_on, NULL, VB_BEEP_NOT_ALLOWED); - return VBERROR_KEEP_LOOPING; - } - vb2_change_menu(VB_MENU_TO_DEV, VB_TO_DEV_CANCEL); - vb2_draw_current_screen(ctx); - return VBERROR_KEEP_LOOPING; -} - -static vb2_error_t enter_to_norm_menu(struct vb2_context *ctx) -{ - vb2_change_menu(VB_MENU_TO_NORM, VB_TO_NORM_CONFIRM); - vb2_draw_current_screen(ctx); - /* Make sure user knows dev mode disabled */ - if (disable_dev_boot) - VbExDisplayDebugInfo(dev_disable_msg, 0); - return VBERROR_KEEP_LOOPING; -} - -/* Boot alternative bootloader if allowed and available. */ -static vb2_error_t enter_altfw_menu(struct vb2_context *ctx) -{ - VB2_DEBUG("enter_altfw_menu()\n"); - if (disable_dev_boot) { - vb2_flash_screen(ctx); - vb2_error_beep(VB_BEEP_NOT_ALLOWED); - return VBERROR_KEEP_LOOPING; - } - if (!altfw_allowed) { - vb2_flash_screen(ctx); - vb2_error_no_altfw(); - return VBERROR_KEEP_LOOPING; - } - vb2_change_menu(VB_MENU_ALT_FW, 0); - vb2_draw_current_screen(ctx); - - return VBERROR_KEEP_LOOPING; -} - -static vb2_error_t debug_info_action(struct vb2_context *ctx) -{ - force_redraw = 1; - VbDisplayDebugInfo(ctx); - return VBERROR_KEEP_LOOPING; -} - -/* Action when selecting a language entry in the language menu. */ -static vb2_error_t language_action(struct vb2_context *ctx) -{ - /* Write selected language ID back to NVRAM. */ - vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, current_menu_idx); - - /* - * Non-manual recovery mode is meant to be left via three-finger - * salute (into manual recovery mode). Need to commit nvdata - * changes immediately. Ignore commit errors in recovery mode. - */ - if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE) && - !vb2_allow_recovery(ctx)) - vb2_commit_data(ctx); - - /* Return to previous menu. */ - switch (prev_menu) { - case VB_MENU_DEV_WARNING: - return enter_dev_warning_menu(ctx); - case VB_MENU_DEV: - return enter_developer_menu(ctx); - case VB_MENU_TO_NORM: - return enter_to_norm_menu(ctx); - case VB_MENU_TO_DEV: - return enter_to_dev_menu(ctx); - case VB_MENU_OPTIONS: - return enter_options_menu(ctx); - default: - /* This should never happen. */ - VB2_DEBUG("ERROR: prev_menu state corrupted, force shutdown\n"); - return VBERROR_SHUTDOWN_REQUESTED; - } -} - -/* Action when selecting a bootloader in the alternative firmware menu. */ -static vb2_error_t altfw_action(struct vb2_context *ctx) -{ - vb2_try_altfw(ctx, 1, current_menu_idx + 1); - vb2_flash_screen(ctx); - VB2_DEBUG(no_legacy); - VbExDisplayDebugInfo(no_legacy, 0); - - return VBERROR_KEEP_LOOPING; -} - -/* Action that enables developer mode and reboots. */ -static vb2_error_t to_dev_action(struct vb2_context *ctx) -{ - /* Sanity check, should never happen. */ - if ((vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) || - !vb2_allow_recovery(ctx)) - return VBERROR_KEEP_LOOPING; - - VB2_DEBUG("Enabling dev-mode...\n"); - if (VB2_SUCCESS != vb2_enable_developer_mode(ctx)) - return VBERROR_TPM_SET_BOOT_MODE_STATE; - - /* This was meant for headless devices, shouldn't really matter here. */ - if (USB_BOOT_ON_DEV) - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 1); - - VB2_DEBUG("Reboot so it will take effect\n"); - return VBERROR_REBOOT_REQUIRED; -} - -/* Action that disables developer mode, shows TO_NORM_CONFIRMED and reboots. */ -static vb2_error_t to_norm_action(struct vb2_context *ctx) -{ - if (vb2_get_gbb(ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { - vb2_flash_screen(ctx); - vb2_error_notify("WARNING: TONORM prohibited by " - "GBB FORCE_DEV_SWITCH_ON.\n", NULL, - VB_BEEP_NOT_ALLOWED); - return VBERROR_KEEP_LOOPING; - } - - VB2_DEBUG("leaving dev-mode.\n"); - vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); - vb2_change_menu(VB_MENU_TO_NORM_CONFIRMED, 0); - vb2_draw_current_screen(ctx); - VbExSleepMs(5000); - return VBERROR_REBOOT_REQUIRED; -} - -/* Action that will power off the system. */ -static vb2_error_t power_off_action(struct vb2_context *ctx) -{ - VB2_DEBUG("Power off requested from screen %#x\n", - menus[current_menu].screen); - return VBERROR_SHUTDOWN_REQUESTED; -} - -/** - * Updates current_menu_idx upon an up/down key press, taking into - * account disabled indices (from disabled_idx_mask). The cursor - * will not wrap, meaning that we block on the 0 or max index when - * we hit the ends of the menu. - * - * @param key VOL_KEY_UP = increase index selection - * VOL_KEY_DOWN = decrease index selection. - * Every other key has no effect now. - */ -static void vb2_update_selection(uint32_t key) { - int idx; - - switch (key) { - case VB_BUTTON_VOL_UP_SHORT_PRESS: - case VB_KEY_UP: - idx = current_menu_idx - 1; - while (idx >= 0 && - ((1 << idx) & disabled_idx_mask)) - idx--; - /* Only update if idx is valid */ - if (idx >= 0) - current_menu_idx = idx; - break; - case VB_BUTTON_VOL_DOWN_SHORT_PRESS: - case VB_KEY_DOWN: - idx = current_menu_idx + 1; - while (idx < menus[current_menu].size && - ((1 << idx) & disabled_idx_mask)) - idx++; - /* Only update if idx is valid */ - if (idx < menus[current_menu].size) - current_menu_idx = idx; - break; - default: - VB2_DEBUG("ERROR: %s called with key %#x!\n", __func__, key); - break; - } - - vb2_log_menu_change(); -} - -static vb2_error_t vb2_handle_menu_input(struct vb2_context *ctx, - uint32_t key, uint32_t key_flags) -{ - switch (key) { - case 0: - /* nothing pressed */ - break; - case '\t': - /* Tab = display debug info */ - return debug_info_action(ctx); - case VB_KEY_ESC: - /* Esc = redraw screen (to clear old debug info) */ - vb2_draw_current_screen(ctx); - break; - case VB_KEY_UP: - case VB_KEY_DOWN: - case VB_BUTTON_VOL_UP_SHORT_PRESS: - case VB_BUTTON_VOL_DOWN_SHORT_PRESS: - /* Untrusted (USB keyboard) input disabled for TO_DEV menu. */ - if (current_menu == VB_MENU_TO_DEV && - !(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) { - vb2_flash_screen(ctx); - vb2_error_notify("Please use the on-device volume " - "buttons to navigate\n", - "vb2_handle_menu_input() - Untrusted " - "(USB keyboard) input disabled\n", - VB_BEEP_NOT_ALLOWED); - break; - } - - /* Menuless screens enter OPTIONS on volume button press. */ - if (!menus[current_menu].size) { - enter_options_menu(ctx); - break; - } - - vb2_update_selection(key); - vb2_draw_current_screen(ctx); - break; - case VB_BUTTON_POWER_SHORT_PRESS: - case VB_KEY_ENTER: - /* Menuless screens shut down on power button press. */ - if (!menus[current_menu].size) - return VBERROR_SHUTDOWN_REQUESTED; - - return menus[current_menu].items[current_menu_idx].action(ctx); - default: - VB2_DEBUG("pressed key %#x\n", key); - break; - } - - if (VbWantShutdownMenu(ctx)) { - VB2_DEBUG("shutdown requested!\n"); - return VBERROR_SHUTDOWN_REQUESTED; - } - - return VBERROR_KEEP_LOOPING; -} - -/* Master table of all menus. Menus with size == 0 count as menuless screens. */ -static struct vb2_menu menus[VB_MENU_COUNT] = { - [VB_MENU_DEV_WARNING] = { - .name = "Developer Warning", - .size = VB_WARN_COUNT, - .screen = VB_SCREEN_DEVELOPER_WARNING_MENU, - .items = (struct vb2_menu_item[]){ - [VB_WARN_OPTIONS] = { - .text = "Developer Options", - .action = enter_developer_menu, - }, - [VB_WARN_DBG_INFO] = { - .text = "Show Debug Info", - .action = debug_info_action, - }, - [VB_WARN_ENABLE_VER] = { - .text = "Enable OS Verification", - .action = enter_to_norm_menu, - }, - [VB_WARN_POWER_OFF] = { - .text = "Power Off", - .action = power_off_action, - }, - [VB_WARN_LANGUAGE] = { - .text = "Language", - .action = enter_language_menu, - }, - }, - }, - [VB_MENU_DEV] = { - .name = "Developer Boot Options", - .size = VB_DEV_COUNT, - .screen = VB_SCREEN_DEVELOPER_MENU, - .items = (struct vb2_menu_item[]){ - [VB_DEV_NETWORK] = { - .text = "Boot From Network", - .action = NULL, /* unimplemented */ - }, - [VB_DEV_LEGACY] = { - .text = "Boot Legacy BIOS", - .action = enter_altfw_menu, - }, - [VB_DEV_USB] = { - .text = "Boot From USB or SD Card", - .action = boot_usb_action, - }, - [VB_DEV_DISK] = { - .text = "Boot From Internal Disk", - .action = boot_disk_action, - }, - [VB_DEV_CANCEL] = { - .text = "Cancel", - .action = enter_dev_warning_menu, - }, - [VB_DEV_POWER_OFF] = { - .text = "Power Off", - .action = power_off_action, - }, - [VB_DEV_LANGUAGE] = { - .text = "Language", - .action = enter_language_menu, - }, - }, - }, - [VB_MENU_TO_NORM] = { - .name = "TO_NORM Confirmation", - .size = VB_TO_NORM_COUNT, - .screen = VB_SCREEN_DEVELOPER_TO_NORM_MENU, - .items = (struct vb2_menu_item[]){ - [VB_TO_NORM_CONFIRM] = { - .text = "Confirm Enabling OS Verification", - .action = to_norm_action, - }, - [VB_TO_NORM_CANCEL] = { - .text = "Cancel", - .action = enter_dev_warning_menu, - }, - [VB_TO_NORM_POWER_OFF] = { - .text = "Power Off", - .action = power_off_action, - }, - [VB_TO_NORM_LANGUAGE] = { - .text = "Language", - .action = enter_language_menu, - }, - }, - }, - [VB_MENU_TO_DEV] = { - .name = "TO_DEV Confirmation", - .size = VB_TO_DEV_COUNT, - .screen = VB_SCREEN_RECOVERY_TO_DEV_MENU, - .items = (struct vb2_menu_item[]){ - [VB_TO_DEV_CONFIRM] = { - .text = "Confirm Disabling OS Verification", - .action = to_dev_action, - }, - [VB_TO_DEV_CANCEL] = { - .text = "Cancel", - .action = enter_recovery_base_screen, - }, - [VB_TO_DEV_POWER_OFF] = { - .text = "Power Off", - .action = power_off_action, - }, - [VB_TO_DEV_LANGUAGE] = { - .text = "Language", - .action = enter_language_menu, - }, - }, - }, - [VB_MENU_LANGUAGES] = { - .name = "Language Selection", - .screen = VB_SCREEN_LANGUAGES_MENU, - /* Rest is filled out dynamically by vb2_init_menus() */ - }, - [VB_MENU_OPTIONS] = { - .name = "Options", - .size = VB_OPTIONS_COUNT, - .screen = VB_SCREEN_OPTIONS_MENU, - .items = (struct vb2_menu_item[]){ - [VB_OPTIONS_DBG_INFO] = { - .text = "Show Debug Info", - .action = debug_info_action, - }, - [VB_OPTIONS_CANCEL] = { - .text = "Cancel", - .action = enter_recovery_base_screen, - }, - [VB_OPTIONS_POWER_OFF] = { - .text = "Power Off", - .action = power_off_action, - }, - [VB_OPTIONS_LANGUAGE] = { - .text = "Language", - .action = enter_language_menu, - }, - }, - }, - [VB_MENU_RECOVERY_INSERT] = { - .name = "Recovery INSERT", - .size = 0, - .screen = VB_SCREEN_RECOVERY_INSERT, - .items = NULL, - }, - [VB_MENU_RECOVERY_NO_GOOD] = { - .name = "Recovery NO_GOOD", - .size = 0, - .screen = VB_SCREEN_RECOVERY_NO_GOOD, - .items = NULL, - }, - [VB_MENU_RECOVERY_BROKEN] = { - .name = "Non-manual Recovery (BROKEN)", - .size = 0, - .screen = VB_SCREEN_OS_BROKEN, - .items = NULL, - }, - [VB_MENU_TO_NORM_CONFIRMED] = { - .name = "TO_NORM Interstitial", - .size = 0, - .screen = VB_SCREEN_TO_NORM_CONFIRMED, - .items = NULL, - }, - [VB_MENU_ALT_FW] = { - .name = "Alternative Firmware Selection", - .screen = VB_SCREEN_ALT_FW_MENU, - .size = VB_ALTFW_COUNT + 1, - .items = (struct vb2_menu_item[]) {{ - .text = "Bootloader 1", - .action = altfw_action, - }, { - .text = "Bootloader 2", - .action = altfw_action, - }, { - .text = "Bootloader 3", - .action = altfw_action, - }, { - .text = "Bootloader 4", - .action = altfw_action, - }, { - .text = "Bootloader 5", - .action = altfw_action, - }, { - .text = "Bootloader 6", - .action = altfw_action, - }, { - .text = "Bootloader 7", - .action = altfw_action, - }, { - .text = "Bootloader 8", - .action = altfw_action, - }, { - .text = "Bootloader 9", - .action = altfw_action, - }, { - .text = "Cancel", - .action = enter_developer_menu, - }, - }, - }, -}; - -/* Initialize menu state. Must be called once before displaying any menus. */ -static vb2_error_t vb2_init_menus(struct vb2_context *ctx) -{ - struct vb2_menu_item *items; - uint32_t count; - int i; - - /* Initialize language menu with the correct amount of entries. */ - if (VB2_SUCCESS != VbExGetLocalizationCount(&count) || count == 0) - count = 1; /* Fall back to 1 language entry on failure */ - - items = malloc(count * sizeof(struct vb2_menu_item)); - if (!items) - return VB2_ERROR_UNKNOWN; - - for (i = 0; i < count; i++) { - /* The actual language is drawn by the bootloader */ - items[i].text = "Some Language"; - items[i].action = language_action; - } - menus[VB_MENU_LANGUAGES].size = count; - menus[VB_MENU_LANGUAGES].items = items; - - return VB2_SUCCESS; -} - -/** - * Main function that handles developer warning menu functionality - * - * @param ctx Vboot2 context - * @return VB2_SUCCESS, or non-zero error code if error. - */ -static vb2_error_t vb2_developer_menu(struct vb2_context *ctx) -{ - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - vb2_error_t ret; - - /* Check if the default is to boot using disk, usb, or legacy */ - default_boot = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT); - if (gbb->flags & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) - default_boot = VB2_DEV_DEFAULT_BOOT_LEGACY; - - /* Check if developer mode is disabled by FWMP */ - disable_dev_boot = 0; - if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_DISABLE_BOOT)) { - if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { - VB2_DEBUG("FWMP_DEV_DISABLE_BOOT rejected by" - "FORCE_DEV_SWITCH_ON\n"); - } else { - /* If dev mode is disabled, only allow TONORM */ - disable_dev_boot = 1; - VB2_DEBUG("dev_disable_boot is set.\n"); - } - } - - altfw_allowed = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY) || - (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY) || - vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY); - - /* Show appropriate initial menu */ - if (disable_dev_boot) - enter_to_norm_menu(ctx); - else - enter_dev_warning_menu(ctx); - - /* Get audio/delay context */ - vb2_audio_start(ctx); - - /* We'll loop until we finish the delay or are interrupted */ - do { - uint32_t key = VbExKeyboardRead(); - - switch (key) { - case VB_BUTTON_VOL_DOWN_LONG_PRESS: - case VB_KEY_CTRL('D'): - /* Ctrl+D = boot from internal disk */ - ret = boot_disk_action(ctx); - break; - case VB_KEY_CTRL('L'): - /* Ctrl+L = boot alternative bootloader */ - ret = enter_altfw_menu(ctx); - break; - case VB_BUTTON_VOL_UP_LONG_PRESS: - case VB_KEY_CTRL('U'): - /* Ctrl+U = boot from USB or SD card */ - ret = boot_usb_action(ctx); - break; - /* We allow selection of the default '0' bootloader here */ - case '0'...'9': - VB2_DEBUG("VbBootDeveloper() - " - "user pressed key '%c': Boot alternative " - "firmware\n", key); - vb2_try_altfw(ctx, altfw_allowed, key - '0'); - ret = VBERROR_KEEP_LOOPING; - break; - default: - ret = vb2_handle_menu_input(ctx, key, 0); - break; - } - - /* We may have loaded a kernel or decided to shut down now. */ - if (ret != VBERROR_KEEP_LOOPING) - return ret; - - /* Reset 30 second timer whenever we see a new key. */ - if (key != 0) - vb2_audio_start(ctx); - - VbExSleepMs(KEY_DELAY_MS); - - /* If dev mode was disabled, loop forever (never timeout) */ - } while (disable_dev_boot ? 1 : vb2_audio_looping()); - - if (default_boot == VB2_DEV_DEFAULT_BOOT_LEGACY) - boot_legacy_action(ctx); /* Doesn't return on success. */ - - if (default_boot == VB2_DEV_DEFAULT_BOOT_USB) - if (VB2_SUCCESS == boot_usb_action(ctx)) - return VB2_SUCCESS; - - return boot_disk_action(ctx); -} - -/* Developer mode entry point. */ -vb2_error_t VbBootDeveloperMenu(struct vb2_context *ctx) -{ - vb2_error_t retval = vb2_init_menus(ctx); - if (VB2_SUCCESS != retval) - return retval; - retval = vb2_developer_menu(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - return retval; -} - -/* Main function that handles non-manual recovery (BROKEN) menu functionality */ -static vb2_error_t broken_ui(struct vb2_context *ctx) -{ - VbSharedDataHeader *vbsd = vb2_get_sd(ctx)->vbsd; - - /* - * Temporarily stash recovery reason in subcode so we'll still know what - * to display if the user reboots into manual recovery from here. Commit - * immediately since the user may hard-reset out of here. - */ - VB2_DEBUG("saving recovery reason (%#x)\n", vbsd->recovery_reason); - vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, vbsd->recovery_reason); - - /* Ignore commit errors in recovery mode. */ - vb2_commit_data(ctx); - - enter_recovery_base_screen(ctx); - - /* Loop and wait for the user to reset or shut down. */ - VB2_DEBUG("waiting for manual recovery\n"); - while (1) { - uint32_t key = VbExKeyboardRead(); - vb2_error_t ret = vb2_handle_menu_input(ctx, key, 0); - if (ret != VBERROR_KEEP_LOOPING) - return ret; - } -} - -/** - * Main function that handles recovery menu functionality - * - * @param ctx Vboot2 context - * @return VB2_SUCCESS, or non-zero error code if error. - */ -static vb2_error_t recovery_ui(struct vb2_context *ctx) -{ - uint32_t key; - uint32_t key_flags; - vb2_error_t ret; - - /* Loop and wait for a recovery image */ - VB2_DEBUG("waiting for a recovery image\n"); - usb_nogood = -1; - while (1) { - ret = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE); - - if (VB2_SUCCESS == ret) - return ret; /* Found a recovery kernel */ - - if (usb_nogood != (ret != VB2_ERROR_LK_NO_DISK_FOUND)) { - /* USB state changed, force back to base screen */ - usb_nogood = ret != VB2_ERROR_LK_NO_DISK_FOUND; - enter_recovery_base_screen(ctx); - } - - key = VbExKeyboardReadWithFlags(&key_flags); - if (key == VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS) { - if (key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD) - enter_to_dev_menu(ctx); - else - VB2_DEBUG("ERROR: untrusted combo?!\n"); - } else { - ret = vb2_handle_menu_input(ctx, key, key_flags); - if (ret != VBERROR_KEEP_LOOPING) - return ret; - } - VbExSleepMs(KEY_DELAY_MS); - } -} - -/* Recovery mode entry point. */ -vb2_error_t VbBootRecoveryMenu(struct vb2_context *ctx) -{ - vb2_error_t retval = vb2_init_menus(ctx); - if (VB2_SUCCESS != retval) - return retval; - if (vb2_allow_recovery(ctx)) - retval = recovery_ui(ctx); - else - retval = broken_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - return retval; -} diff --git a/firmware/lib/vboot_ui_wilco.c b/firmware/lib/vboot_ui_wilco.c deleted file mode 100644 index ff4e229e..00000000 --- a/firmware/lib/vboot_ui_wilco.c +++ /dev/null @@ -1,350 +0,0 @@ -/* Copyright 2020 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. - * - * Common code used by both vboot_ui and Wilco-specific - * feature support for vboot_ui - */ - -#include "2common.h" -#include "2nvstorage.h" -#include "2sysincludes.h" -#include "vboot_api.h" -#include "vboot_display.h" -#include "vboot_ui_common.h" -#include "vboot_ui_wilco.h" - -static inline int is_vowel(uint32_t key) -{ - return key == 'A' || key == 'E' || key == 'I' || - key == 'O' || key == 'U'; -} - -static int vendor_data_length(char *data_value) -{ - for (int len = 0; len <= VENDOR_DATA_LENGTH; len++) { - if (data_value[len] == '\0') - return len; - } - - return VENDOR_DATA_LENGTH; -} - -/* - * Prompt the user to enter the serial number - */ -static vb2_error_t vb2_enter_vendor_data_ui(struct vb2_context *ctx, - char *data_value) -{ - int len = vendor_data_length(data_value); - VbScreenData data = {.vendor_data = {data_value, 1}}; - - VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, 1, &data); - - /* We'll loop until the user decides what to do */ - do { - uint32_t key = VbExKeyboardRead(); - - if (vb2_want_shutdown(ctx, key)) { - VB2_DEBUG("Vendor Data UI - shutdown requested!\n"); - return VBERROR_SHUTDOWN_REQUESTED; - } - switch (key) { - case 0: - /* Nothing pressed */ - break; - case VB_KEY_ESC: - /* Escape pressed - return to developer screen */ - VB2_DEBUG("Vendor Data UI - user pressed Esc: " - "exit to Developer screen\n"); - data_value[0] = '\0'; - return VB2_SUCCESS; - case 'a'...'z': - key = toupper(key); - __attribute__ ((fallthrough)); - case '0'...'9': - case 'A'...'Z': - if ((len > 0 && is_vowel(key)) || - len >= VENDOR_DATA_LENGTH) { - vb2_error_beep(VB_BEEP_NOT_ALLOWED); - } else { - data_value[len++] = key; - data_value[len] = '\0'; - VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, - 1, &data); - } - - VB2_DEBUG("Vendor Data UI - vendor_data: %s\n", - data_value); - break; - case VB_KEY_BACKSPACE: - if (len > 0) { - data_value[--len] = '\0'; - VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, - 1, &data); - } - - VB2_DEBUG("Vendor Data UI - vendor_data: %s\n", - data_value); - break; - case VB_KEY_ENTER: - if (len == VENDOR_DATA_LENGTH) { - /* Enter pressed - confirm input */ - VB2_DEBUG("Vendor Data UI - user pressed " - "Enter: confirm vendor data\n"); - return VB2_SUCCESS; - } else { - vb2_error_beep(VB_BEEP_NOT_ALLOWED); - } - break; - default: - VB2_DEBUG("Vendor Data UI - pressed key %#x\n", key); - VbCheckDisplayKey(ctx, key, &data); - break; - } - VbExSleepMs(KEY_DELAY_MS); - } while (1); - - return VB2_SUCCESS; -} - -/* - * Prompt the user to confirm the serial number and write to memory - */ -static vb2_error_t vb2_confirm_vendor_data_ui(struct vb2_context *ctx, - char* data_value, VbScreenData *data) -{ - VbDisplayScreen(ctx, VB_SCREEN_CONFIRM_VENDOR_DATA, 1, data); - /* We'll loop until the user decides what to do */ - do { - uint32_t key_confirm = VbExKeyboardRead(); - - if (vb2_want_shutdown(ctx, key_confirm)) { - VB2_DEBUG("Confirm Vendor Data UI " - "- shutdown requested!\n"); - return VBERROR_SHUTDOWN_REQUESTED; - } - switch (key_confirm) { - case 0: - /* Nothing pressed */ - break; - case VB_KEY_ESC: - /* Escape pressed - return to developer screen */ - VB2_DEBUG("Confirm Vendor Data UI - user " - "pressed Esc: exit to Developer screen\n"); - return VB2_SUCCESS; - case VB_KEY_RIGHT: - case VB_KEY_LEFT: - data->vendor_data.selected_index = - data->vendor_data.selected_index ^ 1; - VbDisplayScreen(ctx, VB_SCREEN_CONFIRM_VENDOR_DATA, - 1, data); - VB2_DEBUG("selected_index:%d\n", - data->vendor_data.selected_index); - break; - case VB_KEY_ENTER: - /* Enter pressed - write vendor data */ - if (data->vendor_data.selected_index == 0) { - VB2_DEBUG("Confirm Vendor Data UI - user " - "selected YES: " - "write vendor data (%s) to VPD\n", - data_value); - vb2_error_t ret = VbExSetVendorData(data_value); - - if (ret == VB2_SUCCESS) { - vb2_nv_set(ctx, - VB2_NV_DISABLE_DEV_REQUEST, - 1); - return VBERROR_REBOOT_REQUIRED; - } else { - vb2_error_notify( - "ERROR: Vendor data was not " - "set.\n" - "System will now shutdown\n", - NULL, VB_BEEP_FAILED); - VbExSleepMs(5000); - return VBERROR_SHUTDOWN_REQUESTED; - } - } else { - VB2_DEBUG("Confirm Vendor Data UI - user " - "selected NO: " - "Returning to set screen\n"); - return VB2_SUCCESS; - } - default: - VB2_DEBUG("Confirm Vendor Data UI - pressed " - "key %#x\n", key_confirm); - VbCheckDisplayKey(ctx, key_confirm, data); - break; - } - VbExSleepMs(KEY_DELAY_MS); - } while (1); - return VB2_SUCCESS; -} - -vb2_error_t vb2_vendor_data_ui(struct vb2_context *ctx) -{ - char data_value[VENDOR_DATA_LENGTH + 1]; - - VbScreenData data = {.vendor_data = {data_value, 0}}; - VbDisplayScreen(ctx, VB_COMPLETE_VENDOR_DATA, 0, NULL); - - do { - uint32_t key_set = VbExKeyboardRead(); - - if (vb2_want_shutdown(ctx, key_set)) { - VB2_DEBUG("Vendor Data UI - shutdown requested!\n"); - return VBERROR_SHUTDOWN_REQUESTED; - } - - switch (key_set) { - case 0: - /* Nothing pressed - do nothing. */ - break; - case VB_KEY_ESC: - /* ESC pressed - boot normally */ - VB2_DEBUG("Vendor Data UI - boot normally\n"); - return VB2_SUCCESS; - break; - case VB_KEY_ENTER: - data_value[0] = '\0'; - do { - /* ENTER pressed - - enter vendor data set screen */ - VB2_DEBUG("Vendor Data UI - Enter VD set " - "screen\n"); - vb2_error_t ret = vb2_enter_vendor_data_ui( - ctx, data_value); - - if (ret) - return ret; - - /* Vendor data was not entered just return */ - if (vendor_data_length(data_value) == 0) { - return VB2_SUCCESS; - } - - /* Reset confirmation answer to YES */ - data.vendor_data.selected_index = 0; - - ret = vb2_confirm_vendor_data_ui( - ctx, data_value, &data); - - if (ret) - return ret; - - /* Break if vendor data confirmed */ - if (data.vendor_data.selected_index == 0) - return VB2_SUCCESS; - } while (1); - break; - default: - break; - } - } while (1); - return VB2_SUCCESS; -} - -vb2_error_t vb2_check_diagnostic_key(struct vb2_context *ctx, - uint32_t key) { - if (DIAGNOSTIC_UI && (key == VB_KEY_CTRL('C') || key == VB_KEY_F(12))) { - VB2_DEBUG("Diagnostic mode requested, rebooting\n"); - vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); - - return VBERROR_REBOOT_REQUIRED; - } - - return VB2_SUCCESS; -} - -vb2_error_t vb2_diagnostics_ui(struct vb2_context *ctx) -{ - int active = 1; - int power_button_was_released = 0; - int power_button_was_pressed = 0; - vb2_error_t result = VBERROR_REBOOT_REQUIRED; - int action_confirmed = 0; - uint64_t start_time_us; - - VbDisplayScreen(ctx, VB_SCREEN_CONFIRM_DIAG, 0, NULL); - - start_time_us = VbExGetTimer(); - - /* We'll loop until the user decides what to do */ - do { - uint32_t key = VbExKeyboardRead(); - /* - * VbExIsShutdownRequested() is almost an adequate substitute - * for adding a new flag to VbExGetSwitches(). The main - * issue is that the former doesn't consult the power button - * on detachables, and this function wants to see for itself - * that the power button isn't currently pressed. - */ - if (VbExGetSwitches(VB_SWITCH_FLAG_PHYS_PRESENCE_PRESSED)) { - /* Wait for a release before registering a press. */ - if (power_button_was_released) - power_button_was_pressed = 1; - } else { - power_button_was_released = 1; - if (power_button_was_pressed) { - VB2_DEBUG("vb2_diagnostics_ui() - power released\n"); - action_confirmed = 1; - active = 0; - break; - } - } - - /* Check the lid and ignore the power button. */ - if (vb2_want_shutdown(ctx, 0) & ~VB_SHUTDOWN_REQUEST_POWER_BUTTON) { - VB2_DEBUG("vb2_diagnostics_ui() - shutdown request\n"); - result = VBERROR_SHUTDOWN_REQUESTED; - active = 0; - break; - } - - switch (key) { - case 0: - /* Nothing pressed */ - break; - case VB_KEY_ESC: - /* Escape pressed - reboot */ - VB2_DEBUG("vb2_diagnostics_ui() - user pressed Esc\n"); - active = 0; - break; - default: - VB2_DEBUG("vb2_diagnostics_ui() - pressed key %#x\n", - key); - VbCheckDisplayKey(ctx, key, NULL); - break; - } - if (VbExGetTimer() - start_time_us >= 30 * VB_USEC_PER_SEC) { - VB2_DEBUG("vb2_diagnostics_ui() - timeout\n"); - break; - } - if (active) { - VbExSleepMs(KEY_DELAY_MS); - } - } while (active); - - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - - if (action_confirmed) { - VB2_DEBUG("Diagnostic requested, running\n"); - - if (vb2ex_tpm_set_mode(VB2_TPM_MODE_DISABLED) != - VB2_SUCCESS) { - VB2_DEBUG("Failed to disable TPM\n"); - vb2api_fail(ctx, VB2_RECOVERY_TPM_DISABLE_FAILED, 0); - } else { - vb2_try_altfw(ctx, 1, VB_ALTFW_DIAGNOSTIC); - VB2_DEBUG("Diagnostic failed to run\n"); - /* - * Assuming failure was due to bad hash, though - * the rom could just be missing or invalid. - */ - vb2api_fail(ctx, VB2_RECOVERY_ALTFW_HASH_FAILED, 0); - } - } - - return result; -} -- cgit v1.2.1