summaryrefslogtreecommitdiff
path: root/firmware/2lib/2ui_screens.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/2lib/2ui_screens.c')
-rw-r--r--firmware/2lib/2ui_screens.c117
1 files changed, 117 insertions, 0 deletions
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,