summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorJoel Kitching <kitching@google.com>2020-05-12 00:26:01 +0800
committerCommit Bot <commit-bot@chromium.org>2020-05-18 16:13:13 +0000
commit23f819197799d56824ed5b8fc92a23625fe65348 (patch)
tree5f2eac4c7ed11cc28f7c638006ef49b5ef3efa59 /firmware
parenta2f2c015cb545a0c1060bd30c59df567b856bc17 (diff)
downloadvboot-23f819197799d56824ed5b8fc92a23625fe65348.tar.gz
vboot/ui: add developer and to_norm screens
Developer mode can boot internal or external disk. Support for booting legacy firmware ("Ctrl+L") will be added in a subsequent CL. BUG=b:146399181 TEST=make clean && make runtests BRANCH=none Change-Id: I45590e20727bd84375d10ca5ef906206d0ecd805 Signed-off-by: Joel Kitching <kitching@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2192863 Tested-by: Joel Kitching <kitching@chromium.org> Reviewed-by: Yu-Ping Wu <yupingso@chromium.org> Commit-Queue: Joel Kitching <kitching@chromium.org>
Diffstat (limited to 'firmware')
-rw-r--r--firmware/2lib/2ui.c66
-rw-r--r--firmware/2lib/2ui_screens.c208
-rw-r--r--firmware/2lib/include/2ui.h11
-rw-r--r--firmware/2lib/include/2ui_private.h7
4 files changed, 248 insertions, 44 deletions
diff --git a/firmware/2lib/2ui.c b/firmware/2lib/2ui.c
index 6f90135b..a711bde8 100644
--- a/firmware/2lib/2ui.c
+++ b/firmware/2lib/2ui.c
@@ -120,7 +120,7 @@ vb2_error_t menu_down_action(struct vb2_ui_context *ui)
/**
* Navigate to the target screen of the current menu item selection.
*/
-vb2_error_t menu_select_action(struct vb2_ui_context *ui)
+vb2_error_t vb2_ui_menu_select_action(struct vb2_ui_context *ui)
{
const struct vb2_menu_item *menu_item;
@@ -138,7 +138,7 @@ vb2_error_t menu_select_action(struct vb2_ui_context *ui)
} else if (menu_item->target) {
VB2_DEBUG("Menu item <%s> to target screen %#x\n",
menu_item->text, menu_item->target);
- return change_screen(ui, menu_item->target);
+ return vb2_ui_change_screen(ui, menu_item->target);
}
VB2_DEBUG("Menu item <%s> no action or target screen\n",
@@ -152,19 +152,30 @@ vb2_error_t menu_select_action(struct vb2_ui_context *ui)
vb2_error_t vb2_ui_back_action(struct vb2_ui_context *ui)
{
/* TODO(kitching): Return to previous screen instead of root screen. */
- return change_screen(ui, ui->root_screen->id);
+ return vb2_ui_change_screen(ui, ui->root_screen->id);
}
/**
* Context-dependent keyboard shortcut Ctrl+D.
*
* - Manual recovery mode: Change to dev mode transition screen.
- * - Developer mode: Boot from internal disk (TODO).
+ * - Developer mode: Boot from internal disk.
*/
vb2_error_t ctrl_d_action(struct vb2_ui_context *ui)
{
if (vb2_allow_recovery(ui->ctx))
- return change_screen(ui, VB2_SCREEN_RECOVERY_TO_DEV);
+ return change_to_dev_screen_action(ui);
+ else if (ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)
+ return vb2_ui_developer_mode_boot_internal_action(ui);
+
+ return VB2_REQUEST_UI_CONTINUE;
+}
+
+vb2_error_t change_to_dev_screen_action(struct vb2_ui_context *ui)
+{
+ if (vb2_allow_recovery(ui->ctx))
+ return vb2_ui_change_screen(ui, VB2_SCREEN_RECOVERY_TO_DEV);
+
return VB2_REQUEST_UI_CONTINUE;
}
@@ -174,13 +185,20 @@ vb2_error_t ctrl_d_action(struct vb2_ui_context *ui)
static struct input_action action_table[] = {
{ VB_KEY_UP, menu_up_action },
{ VB_KEY_DOWN, menu_down_action },
- { VB_KEY_ENTER, menu_select_action },
+ { VB_KEY_ENTER, vb2_ui_menu_select_action },
{ VB_BUTTON_VOL_UP_SHORT_PRESS, menu_up_action },
{ VB_BUTTON_VOL_DOWN_SHORT_PRESS, menu_down_action },
- { VB_BUTTON_POWER_SHORT_PRESS, menu_select_action },
+ { VB_BUTTON_POWER_SHORT_PRESS, vb2_ui_menu_select_action },
{ VB_KEY_ESC, vb2_ui_back_action },
{ VB_KEY_CTRL('D'), ctrl_d_action },
- { ' ', vb2_ui_recovery_to_dev_action },
+ { VB_BUTTON_VOL_DOWN_LONG_PRESS,
+ vb2_ui_developer_mode_boot_internal_action },
+ { VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS, change_to_dev_screen_action },
+ { ' ', vb2_ui_recovery_to_dev_action },
+ { VB_KEY_CTRL('U'),
+ vb2_ui_developer_mode_boot_external_action },
+ { VB_BUTTON_VOL_UP_LONG_PRESS,
+ vb2_ui_developer_mode_boot_external_action },
};
vb2_error_t (*input_action_lookup(int key))(struct vb2_ui_context *ui)
@@ -195,7 +213,7 @@ vb2_error_t (*input_action_lookup(int key))(struct vb2_ui_context *ui)
/*****************************************************************************/
/* Core UI functions */
-vb2_error_t change_screen(struct vb2_ui_context *ui, enum vb2_screen id)
+vb2_error_t vb2_ui_change_screen(struct vb2_ui_context *ui, enum vb2_screen id)
{
const struct vb2_screen_info *new_screen_info = vb2_get_screen_info(id);
@@ -227,7 +245,7 @@ vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id,
ui.root_screen = vb2_get_screen_info(root_screen_id);
if (ui.root_screen == NULL)
VB2_DIE("Root screen not found.\n");
- rv = change_screen(&ui, ui.root_screen->id);
+ rv = vb2_ui_change_screen(&ui, ui.root_screen->id);
if (rv != VB2_REQUEST_UI_CONTINUE)
return rv;
memset(&prev_state, 0, sizeof(prev_state));
@@ -299,27 +317,7 @@ vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id,
vb2_error_t vb2_developer_menu(struct vb2_context *ctx)
{
- enum vb2_dev_default_boot default_boot;
-
- /* If dev mode was disabled, loop forever. */
- if (!vb2_dev_boot_allowed(ctx))
- while (1);
-
- /* Boot from the default option. */
- default_boot = vb2_get_dev_boot_target(ctx);
-
- /* Boot legacy does not return on success */
- if (default_boot == VB2_DEV_DEFAULT_BOOT_LEGACY &&
- vb2_dev_boot_legacy_allowed(ctx) &&
- VbExLegacy(VB_ALTFW_DEFAULT) == VB2_SUCCESS)
- return VB2_SUCCESS;
-
- if (default_boot == VB2_DEV_DEFAULT_BOOT_USB &&
- vb2_dev_boot_usb_allowed(ctx) &&
- VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE) == VB2_SUCCESS)
- return VB2_SUCCESS;
-
- return VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED);
+ return ui_loop(ctx, VB2_SCREEN_DEVELOPER_MODE, NULL);
}
/*****************************************************************************/
@@ -350,9 +348,9 @@ vb2_error_t try_recovery_action(struct vb2_ui_context *ui)
invalid_disk = rv != VB2_ERROR_LK_NO_DISK_FOUND;
if (invalid_disk_last != invalid_disk) {
invalid_disk_last = invalid_disk;
- return change_screen(ui, invalid_disk ?
- VB2_SCREEN_RECOVERY_INVALID :
- VB2_SCREEN_RECOVERY_SELECT);
+ return vb2_ui_change_screen(ui, invalid_disk ?
+ VB2_SCREEN_RECOVERY_INVALID :
+ VB2_SCREEN_RECOVERY_SELECT);
}
return VB2_REQUEST_UI_CONTINUE;
diff --git a/firmware/2lib/2ui_screens.c b/firmware/2lib/2ui_screens.c
index ca492039..356b3bfb 100644
--- a/firmware/2lib/2ui_screens.c
+++ b/firmware/2lib/2ui_screens.c
@@ -10,7 +10,8 @@
#include "2nvstorage.h"
#include "2ui.h"
#include "2ui_private.h"
-#include "vboot_api.h" /* for VB_KEY_ */
+#include "vboot_api.h"
+#include "vboot_kernel.h"
#define MENU_ITEMS(a) \
.num_items = ARRAY_SIZE(a), \
@@ -45,12 +46,26 @@ static const struct vb2_screen_info recovery_broken_screen = {
/******************************************************************************/
/* VB2_SCREEN_ADVANCED_OPTIONS */
+#define ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE 0
+#define ADVANCED_OPTIONS_ITEM_BACK 1
+
+vb2_error_t advanced_options_init(struct vb2_ui_context *ui)
+{
+ if (vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) {
+ ui->state.disabled_item_mask |=
+ 1 << ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE;
+ ui->state.selected_item = ADVANCED_OPTIONS_ITEM_BACK;
+ }
+
+ return VB2_REQUEST_UI_CONTINUE;
+}
+
static const struct vb2_menu_item advanced_options_items[] = {
- {
- .text = "Developer mode",
+ [ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE] = {
+ .text = "Enable developer mode",
.target = VB2_SCREEN_RECOVERY_TO_DEV,
},
- {
+ [ADVANCED_OPTIONS_ITEM_BACK] = {
.text = "Back",
.action = vb2_ui_back_action,
},
@@ -59,6 +74,7 @@ static const struct vb2_menu_item advanced_options_items[] = {
static const struct vb2_screen_info advanced_options_screen = {
.id = VB2_SCREEN_ADVANCED_OPTIONS,
.name = "Advanced options",
+ .init = advanced_options_init,
MENU_ITEMS(advanced_options_items),
};
@@ -95,6 +111,7 @@ static const struct vb2_screen_info recovery_invalid_screen = {
/* VB2_SCREEN_RECOVERY_TO_DEV */
#define RECOVERY_TO_DEV_ITEM_CONFIRM 0
+#define RECOVERY_TO_DEV_ITEM_CANCEL 1
vb2_error_t recovery_to_dev_init(struct vb2_ui_context *ui)
{
@@ -109,9 +126,11 @@ vb2_error_t recovery_to_dev_init(struct vb2_ui_context *ui)
}
/* Disable "Confirm" button for other physical presence types. */
- if (!PHYSICAL_PRESENCE_KEYBOARD)
- ui->state.disabled_item_mask =
+ if (!PHYSICAL_PRESENCE_KEYBOARD) {
+ ui->state.disabled_item_mask |=
1 << RECOVERY_TO_DEV_ITEM_CONFIRM;
+ ui->state.selected_item = RECOVERY_TO_DEV_ITEM_CANCEL;
+ }
return VB2_REQUEST_UI_CONTINUE;
}
@@ -158,7 +177,7 @@ vb2_error_t vb2_ui_recovery_to_dev_action(struct vb2_ui_context *ui)
/* Sanity check, should never happen. */
if ((vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) ||
!vb2_allow_recovery(ui->ctx)) {
- VB2_DEBUG("ERROR: dev transition sanity check failed\n");
+ VB2_DEBUG("ERROR: Dev transition sanity check failed\n");
return VB2_REQUEST_UI_CONTINUE;
}
@@ -172,7 +191,7 @@ static const struct vb2_menu_item recovery_to_dev_items[] = {
.text = "Confirm",
.action = vb2_ui_recovery_to_dev_action,
},
- {
+ [RECOVERY_TO_DEV_ITEM_CANCEL] = {
.text = "Cancel",
.action = vb2_ui_back_action,
},
@@ -203,6 +222,177 @@ static const struct vb2_screen_info recovery_disk_step1_screen = {
};
/******************************************************************************/
+/* VB2_SCREEN_DEVELOPER_MODE */
+
+#define DEVELOPER_MODE_ITEM_RETURN_TO_SECURE 0
+#define DEVELOPER_MODE_ITEM_BOOT_INTERNAL 1
+#define DEVELOPER_MODE_ITEM_BOOT_EXTERNAL 2
+
+vb2_error_t developer_mode_init(struct vb2_ui_context *ui)
+{
+ enum vb2_dev_default_boot default_boot =
+ vb2_get_dev_boot_target(ui->ctx);
+
+ /* Get me outta here! */
+ if (!vb2_dev_boot_allowed(ui->ctx))
+ vb2_ui_change_screen(ui, VB2_SCREEN_DEVELOPER_TO_NORM);
+
+ /* Don't show "Return to secure mode" button if GBB forces dev mode. */
+ if (vb2_get_gbb(ui->ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON)
+ ui->state.disabled_item_mask |=
+ 1 << DEVELOPER_MODE_ITEM_RETURN_TO_SECURE;
+
+ /* Don't show "Boot from external disk" button if not allowed. */
+ if (!vb2_dev_boot_usb_allowed(ui->ctx))
+ ui->state.disabled_item_mask |=
+ 1 << DEVELOPER_MODE_ITEM_BOOT_EXTERNAL;
+
+ /* Choose the default selection. */
+ switch (default_boot) {
+ case VB2_DEV_DEFAULT_BOOT_USB:
+ ui->state.selected_item = DEVELOPER_MODE_ITEM_BOOT_EXTERNAL;
+ break;
+ default:
+ ui->state.selected_item = DEVELOPER_MODE_ITEM_BOOT_INTERNAL;
+ break;
+ }
+
+ ui->start_time = VbExGetTimer();
+
+ return VB2_REQUEST_UI_CONTINUE;
+}
+
+vb2_error_t vb2_ui_developer_mode_boot_internal_action(
+ struct vb2_ui_context *ui)
+{
+ if (!(ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) ||
+ !vb2_dev_boot_allowed(ui->ctx)) {
+ VB2_DEBUG("ERROR: Dev mode internal boot not allowed\n");
+ return VB2_REQUEST_UI_CONTINUE;
+ }
+
+ if (VbTryLoadKernel(ui->ctx, VB_DISK_FLAG_FIXED)) {
+ VB2_DEBUG("ERROR: Dev mode internal boot failed\n");
+ return VB2_REQUEST_UI_CONTINUE;
+ }
+
+ return VB2_SUCCESS;
+}
+
+vb2_error_t vb2_ui_developer_mode_boot_external_action(
+ struct vb2_ui_context *ui)
+{
+ /* Sanity check, should never happen. */
+ if (!(ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) ||
+ !vb2_dev_boot_allowed(ui->ctx) ||
+ !vb2_dev_boot_usb_allowed(ui->ctx)) {
+ VB2_DEBUG("ERROR: Dev mode external boot not allowed\n");
+ return VB2_REQUEST_UI_CONTINUE;
+ }
+
+ if (VbTryLoadKernel(ui->ctx, VB_DISK_FLAG_REMOVABLE)) {
+ VB2_DEBUG("ERROR: Dev mode external boot failed\n");
+ return VB2_REQUEST_UI_CONTINUE;
+ }
+
+ return VB2_SUCCESS;
+}
+
+vb2_error_t developer_mode_action(struct vb2_ui_context *ui)
+{
+ struct vb2_gbb_header *gbb = vb2_get_gbb(ui->ctx);
+ const int use_short = gbb->flags & VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY;
+ uint64_t elapsed;
+
+ /* Once any user interaction occurs, stop the timer. */
+ if (ui->key)
+ ui->disable_timer = 1;
+ if (ui->disable_timer)
+ return VB2_REQUEST_UI_CONTINUE;
+
+ elapsed = VbExGetTimer() - ui->start_time;
+
+ /* If we're using short delay, wait 2 seconds and don't beep. */
+ if (use_short && elapsed > 2 * VB_USEC_PER_SEC) {
+ VB2_DEBUG("Booting default target after 2s\n");
+ ui->disable_timer = 1;
+ return vb2_ui_menu_select_action(ui);
+ }
+
+ /* Otherwise, beep at 20 and 20.5 seconds. */
+ if ((ui->beep_count == 0 && elapsed > 20 * VB_USEC_PER_SEC) ||
+ (ui->beep_count == 1 && elapsed > 20500 * VB_USEC_PER_MSEC)) {
+ VbExBeep(250, 400);
+ ui->beep_count++;
+ }
+
+ /* Stop after 30 seconds. */
+ if (elapsed > 30 * VB_USEC_PER_SEC) {
+ VB2_DEBUG("Booting default target after 30s\n");
+ ui->disable_timer = 1;
+ return vb2_ui_menu_select_action(ui);
+ }
+
+ return VB2_REQUEST_UI_CONTINUE;
+}
+
+static const struct vb2_menu_item developer_mode_items[] = {
+ [DEVELOPER_MODE_ITEM_RETURN_TO_SECURE] = {
+ .text = "Return to secure mode",
+ .target = VB2_SCREEN_DEVELOPER_TO_NORM,
+ },
+ [DEVELOPER_MODE_ITEM_BOOT_INTERNAL] = {
+ .text = "Boot from internal disk",
+ .action = vb2_ui_developer_mode_boot_internal_action,
+ },
+ [DEVELOPER_MODE_ITEM_BOOT_EXTERNAL] = {
+ .text = "Boot from external disk",
+ .action = vb2_ui_developer_mode_boot_external_action,
+ },
+ ADVANCED_OPTIONS_ITEM,
+};
+
+static const struct vb2_screen_info developer_mode_screen = {
+ .id = VB2_SCREEN_DEVELOPER_MODE,
+ .name = "Developer mode",
+ .init = developer_mode_init,
+ .action = developer_mode_action,
+ MENU_ITEMS(developer_mode_items),
+};
+
+/******************************************************************************/
+/* VB2_SCREEN_DEVELOPER_TO_NORM */
+
+vb2_error_t developer_to_norm_action(struct vb2_ui_context *ui)
+{
+ if (vb2_get_gbb(ui->ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) {
+ VB2_DEBUG("ERROR: dev mode forced by GBB flag\n");
+ return VB2_REQUEST_UI_CONTINUE;
+ }
+
+ VB2_DEBUG("Leaving dev mode\n");
+ vb2_nv_set(ui->ctx, VB2_NV_DISABLE_DEV_REQUEST, 1);
+ return VB2_REQUEST_REBOOT;
+}
+
+static const struct vb2_menu_item developer_to_norm_items[] = {
+ {
+ .text = "Confirm",
+ .action = developer_to_norm_action,
+ },
+ {
+ .text = "Cancel",
+ .action = vb2_ui_back_action,
+ },
+};
+
+static const struct vb2_screen_info developer_to_norm_screen = {
+ .id = VB2_SCREEN_DEVELOPER_TO_NORM,
+ .name = "Transition to normal mode",
+ MENU_ITEMS(developer_to_norm_items),
+};
+
+/******************************************************************************/
/*
* TODO(chromium:1035800): Refactor UI code across vboot and depthcharge.
* Currently vboot and depthcharge maintain their own copies of menus/screens.
@@ -219,6 +409,8 @@ static const struct vb2_screen_info *screens[] = {
&recovery_to_dev_screen,
&recovery_phone_step1_screen,
&recovery_disk_step1_screen,
+ &developer_mode_screen,
+ &developer_to_norm_screen,
};
const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen id)
diff --git a/firmware/2lib/include/2ui.h b/firmware/2lib/include/2ui.h
index b5754020..0043963a 100644
--- a/firmware/2lib/include/2ui.h
+++ b/firmware/2lib/include/2ui.h
@@ -53,11 +53,22 @@ struct vb2_ui_context {
uint32_t locale_id;
uint32_t key;
int key_trusted;
+
+ /* For developer mode screen. */
+ int disable_timer;
+ uint64_t start_time;
+ int beep_count;
};
vb2_error_t vb2_ui_change_screen(struct vb2_ui_context *ui, enum vb2_screen id);
+vb2_error_t vb2_ui_menu_select_action(struct vb2_ui_context *ui);
vb2_error_t vb2_ui_back_action(struct vb2_ui_context *ui);
+
vb2_error_t vb2_ui_recovery_to_dev_action(struct vb2_ui_context *ui);
+vb2_error_t vb2_ui_developer_mode_boot_internal_action(
+ struct vb2_ui_context *ui);
+vb2_error_t vb2_ui_developer_mode_boot_external_action(
+ struct vb2_ui_context *ui);
/**
* Get info struct of a screen.
diff --git a/firmware/2lib/include/2ui_private.h b/firmware/2lib/include/2ui_private.h
index f7c4e247..bfc0dd0b 100644
--- a/firmware/2lib/include/2ui_private.h
+++ b/firmware/2lib/include/2ui_private.h
@@ -27,17 +27,20 @@ struct input_action {
vb2_error_t menu_up_action(struct vb2_ui_context *ui);
vb2_error_t menu_down_action(struct vb2_ui_context *ui);
-vb2_error_t menu_select_action(struct vb2_ui_context *ui);
vb2_error_t ctrl_d_action(struct vb2_ui_context *ui);
+vb2_error_t change_to_dev_screen_action(struct vb2_ui_context *ui);
vb2_error_t (*input_action_lookup(int key))(struct vb2_ui_context *ui);
-vb2_error_t change_screen(struct vb2_ui_context *ui, enum vb2_screen id);
vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id,
vb2_error_t (*global_action)(struct vb2_ui_context *ui));
vb2_error_t try_recovery_action(struct vb2_ui_context *ui);
/* From 2ui_screens.c */
+vb2_error_t advanced_options_init(struct vb2_ui_context *ui);
vb2_error_t recovery_to_dev_init(struct vb2_ui_context *ui);
+vb2_error_t developer_mode_init(struct vb2_ui_context *ui);
+vb2_error_t developer_mode_action(struct vb2_ui_context *ui);
+vb2_error_t developer_to_norm_action(struct vb2_ui_context *ui);
#endif /* VBOOT_REFERENCE_2UI_PRIVATE_H_ */