diff options
author | Joel Kitching <kitching@google.com> | 2020-05-12 00:26:01 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-05-18 16:13:13 +0000 |
commit | 23f819197799d56824ed5b8fc92a23625fe65348 (patch) | |
tree | 5f2eac4c7ed11cc28f7c638006ef49b5ef3efa59 /firmware | |
parent | a2f2c015cb545a0c1060bd30c59df567b856bc17 (diff) | |
download | vboot-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.c | 66 | ||||
-rw-r--r-- | firmware/2lib/2ui_screens.c | 208 | ||||
-rw-r--r-- | firmware/2lib/include/2ui.h | 11 | ||||
-rw-r--r-- | firmware/2lib/include/2ui_private.h | 7 |
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_ */ |