summaryrefslogtreecommitdiff
path: root/firmware/2lib
diff options
context:
space:
mode:
authorJoel Kitching <kitching@google.com>2020-08-03 23:52:27 +0800
committerCommit Bot <commit-bot@chromium.org>2020-09-11 10:47:08 +0000
commitf573cf6669b5f2972f29f511efead068b8c3b38e (patch)
treea294e9fafe4ddf4692ac79820abaa6c4a67d0509 /firmware/2lib
parentade6151a678c59e270c89bcca37f61cfdd41700d (diff)
downloadvboot-f573cf6669b5f2972f29f511efead068b8c3b38e.tar.gz
vboot: Introduce alternate boot functionality
Introduce alternate boot functionality both via keyboard shortcut ("Ctrl+L") to directly boot into the default alternate bootloader, and via menu ("Alternate bootloader" on dev screen) to show a screen listing available bootloaders. BUG=b:146399181, b:161092974 TEST=make clean && make runtests BRANCH=puff, zork Cq-Depend: chromium:2339040 Signed-off-by: Joel Kitching <kitching@google.com> Change-Id: I28f157936017719dc95656db147967f5e61a1407 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2335017 Commit-Queue: Yu-Ping Wu <yupingso@chromium.org> Tested-by: Hsuan Ting Chen <roccochen@chromium.org> Reviewed-by: Yu-Ping Wu <yupingso@chromium.org> Reviewed-by: Joel Kitching <kitching@chromium.org>
Diffstat (limited to 'firmware/2lib')
-rw-r--r--firmware/2lib/2ui.c2
-rw-r--r--firmware/2lib/2ui_screens.c117
-rw-r--r--firmware/2lib/include/2api.h9
-rw-r--r--firmware/2lib/include/2ui.h5
4 files changed, 133 insertions, 0 deletions
diff --git a/firmware/2lib/2ui.c b/firmware/2lib/2ui.c
index d80002d5..4ddbcef0 100644
--- a/firmware/2lib/2ui.c
+++ b/firmware/2lib/2ui.c
@@ -410,6 +410,8 @@ vb2_error_t developer_action(struct vb2_ui_context *ui)
if (ui->key == VB_KEY_CTRL('D') ||
(DETACHABLE && ui->key == VB_BUTTON_VOL_DOWN_LONG_PRESS))
return vb2_ui_developer_mode_boot_internal_action(ui);
+ if (ui->key == VB_KEY_CTRL('L'))
+ return vb2_ui_developer_mode_boot_alternate_action(ui);
if (ui->key == '\t')
return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO);
diff --git a/firmware/2lib/2ui_screens.c b/firmware/2lib/2ui_screens.c
index 2e5dbfaf..e1b02d0a 100644
--- a/firmware/2lib/2ui_screens.c
+++ b/firmware/2lib/2ui_screens.c
@@ -642,6 +642,7 @@ static const struct vb2_screen_info recovery_disk_step3_screen = {
#define DEVELOPER_MODE_ITEM_RETURN_TO_SECURE 1
#define DEVELOPER_MODE_ITEM_BOOT_INTERNAL 2
#define DEVELOPER_MODE_ITEM_BOOT_EXTERNAL 3
+#define DEVELOPER_MODE_ITEM_SELECT_BOOTLOADER 4
vb2_error_t developer_mode_init(struct vb2_ui_context *ui)
{
@@ -662,11 +663,20 @@ vb2_error_t developer_mode_init(struct vb2_ui_context *ui)
ui->state->disabled_item_mask |=
1 << DEVELOPER_MODE_ITEM_BOOT_EXTERNAL;
+ /* Don't show "Select alternate bootloader" button if not allowed. */
+ if (!vb2_dev_boot_legacy_allowed(ui->ctx))
+ ui->state->disabled_item_mask |=
+ 1 << DEVELOPER_MODE_ITEM_SELECT_BOOTLOADER;
+
/* Choose the default selection. */
switch (default_boot) {
case VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL:
ui->state->selected_item = DEVELOPER_MODE_ITEM_BOOT_EXTERNAL;
break;
+ case VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY:
+ ui->state->selected_item =
+ DEVELOPER_MODE_ITEM_SELECT_BOOTLOADER;
+ break;
default:
ui->state->selected_item = DEVELOPER_MODE_ITEM_BOOT_INTERNAL;
break;
@@ -781,6 +791,10 @@ static const struct vb2_menu_item developer_mode_items[] = {
.text = "Boot from external disk",
.action = vb2_ui_developer_mode_boot_external_action,
},
+ [DEVELOPER_MODE_ITEM_SELECT_BOOTLOADER] = {
+ .text = "Select alternate bootloader",
+ .target = VB2_SCREEN_DEVELOPER_SELECT_BOOTLOADER,
+ },
ADVANCED_OPTIONS_ITEM,
POWER_OFF_ITEM,
};
@@ -860,6 +874,108 @@ static const struct vb2_screen_info developer_invalid_disk_screen = {
};
/******************************************************************************/
+/* VB2_SCREEN_DEVELOPER_SELECT_BOOTLOADER */
+
+const struct vb2_menu_item developer_select_bootloader_items_before[] = {
+ LANGUAGE_SELECT_ITEM,
+};
+
+const struct vb2_menu_item developer_select_bootloader_items_after[] = {
+ BACK_ITEM,
+ POWER_OFF_ITEM,
+};
+
+vb2_error_t vb2_ui_developer_mode_boot_alternate_action(
+ struct vb2_ui_context *ui)
+{
+ uint32_t altfw_num;
+ const size_t menu_before_len =
+ ARRAY_SIZE(developer_select_bootloader_items_before);
+
+ if (!(ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) ||
+ !vb2_dev_boot_allowed(ui->ctx) ||
+ !vb2_dev_boot_legacy_allowed(ui->ctx)) {
+ VB2_DEBUG("ERROR: Dev mode alternate bootloader not allowed\n");
+ ui->error_beep = 1;
+ return VB2_REQUEST_UI_CONTINUE;
+ }
+
+ if (vb2ex_get_bootloader_count() == 0) {
+ VB2_DEBUG("ERROR: No bootloader was found\n");
+ ui->error_beep = 1;
+ return VB2_REQUEST_UI_CONTINUE;
+ }
+
+ if (ui->key == VB_KEY_CTRL('L')) {
+ altfw_num = 0;
+ VB2_DEBUG("Try booting from default bootloader\n");
+ } else {
+ altfw_num = ui->state->selected_item - menu_before_len + 1;
+ VB2_DEBUG("Try booting from bootloader #%u\n", altfw_num);
+ }
+
+ /* VbExLegacy will not return if successful */
+ VbExLegacy(altfw_num);
+
+ VB2_DEBUG("ERROR: Alternate bootloader failed\n");
+ /* TODO(b/161092974): Leverage the error dialog on error. */
+ ui->error_beep = 1;
+ return VB2_REQUEST_UI_CONTINUE;
+}
+
+static const struct vb2_menu *get_bootloader_menu(struct vb2_ui_context *ui)
+{
+ int i;
+ uint32_t num_bootloaders, num_items;
+ struct vb2_menu_item *items;
+ const size_t menu_before_len =
+ ARRAY_SIZE(developer_select_bootloader_items_before);
+ const size_t menu_after_len =
+ ARRAY_SIZE(developer_select_bootloader_items_after);
+
+ if (ui->bootloader_menu.num_items > 0)
+ return &ui->bootloader_menu;
+
+ /* TODO(b/161092974): Show error dialog if no bootloader. */
+ num_bootloaders = vb2ex_get_bootloader_count();
+ VB2_DEBUG("num_bootloaders: %u\n", num_bootloaders);
+ num_items = num_bootloaders + menu_before_len + menu_after_len;
+ items = malloc(num_items * sizeof(struct vb2_menu_item));
+ if (!items) {
+ VB2_DEBUG("ERROR: malloc failed for bootloader items\n");
+ return NULL;
+ }
+
+ /* Copy prefix items to the begin. */
+ memcpy(&items[0],
+ developer_select_bootloader_items_before,
+ menu_before_len * sizeof(struct vb2_menu_item));
+
+ /* Copy bootloaders. */
+ for (i = 0; i < num_bootloaders; i++) {
+ items[i + menu_before_len].text = "Some bootloader";
+ items[i + menu_before_len].action =
+ vb2_ui_developer_mode_boot_alternate_action;
+ }
+
+ /* Copy postfix items to the end. */
+ memcpy(&items[num_items - menu_after_len],
+ developer_select_bootloader_items_after,
+ menu_after_len * sizeof(struct vb2_menu_item));
+
+ ui->bootloader_menu.num_items = num_items;
+ ui->bootloader_menu.items = items;
+
+ return &ui->bootloader_menu;
+}
+
+static const struct vb2_screen_info developer_select_bootloader_screen = {
+ .id = VB2_SCREEN_DEVELOPER_SELECT_BOOTLOADER,
+ .name = "Select alternate bootloader",
+ .get_menu = get_bootloader_menu,
+};
+
+/******************************************************************************/
/* VB2_SCREEN_DIAGNOSTICS */
static const struct vb2_menu_item diagnostics_items[] = {
@@ -1071,6 +1187,7 @@ static const struct vb2_screen_info *screens[] = {
&developer_to_norm_screen,
&developer_boot_external_screen,
&developer_invalid_disk_screen,
+ &developer_select_bootloader_screen,
&diagnostics_screen,
&diagnostics_storage_screen,
&diagnostics_memory_quick_screen,
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index ee3bb53e..56c0b80c 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -1316,6 +1316,8 @@ enum vb2_screen {
VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL = 0x320,
/* Invalid external disk inserted */
VB2_SCREEN_DEVELOPER_INVALID_DISK = 0x330,
+ /* Select alternate bootloader ("legacy boot") */
+ VB2_SCREEN_DEVELOPER_SELECT_BOOTLOADER = 0x340,
/* Diagnostic tools */
VB2_SCREEN_DIAGNOSTICS = 0x400,
/* Storage diagnostic screen */
@@ -1380,6 +1382,13 @@ int vb2ex_physical_presence_pressed(void);
uint32_t vb2ex_get_locale_count(void);
/**
+ * Return the number of available alternate bootloaders.
+ *
+ * @returns Number of alternate bootloaders. 0 if none or on error.
+ */
+uint32_t vb2ex_get_bootloader_count(void);
+
+/**
* Delay for at least the specified number of milliseconds.
*
* @param msec Duration in milliseconds.
diff --git a/firmware/2lib/include/2ui.h b/firmware/2lib/include/2ui.h
index cc21f580..2fefaf32 100644
--- a/firmware/2lib/include/2ui.h
+++ b/firmware/2lib/include/2ui.h
@@ -103,6 +103,9 @@ struct vb2_ui_context {
/* For language selection screen. */
struct vb2_menu language_menu;
+ /* For bootloader selection screen. */
+ struct vb2_menu bootloader_menu;
+
/* For error beep sound. */
int error_beep;
@@ -118,6 +121,8 @@ 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);
+vb2_error_t vb2_ui_developer_mode_boot_alternate_action(
+ struct vb2_ui_context *ui);
/**
* Get info struct of a screen.