summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2018-10-16 19:36:48 -0600
committerMartin Roth <martinroth@chromium.org>2018-11-27 23:18:28 +0000
commitc15147f0b5a819dbc58bf9771a400b02c85df4fb (patch)
tree964dd7ff9c1868f78b8a0f483f42cba2a7eb7c3c
parent4a9b54b2fbe0f0cbb7982f0b7430984c5e2c94ab (diff)
downloadvboot-c15147f0b5a819dbc58bf9771a400b02c85df4fb.tar.gz
Add a screen showing a menu for alternative firmware
At present we allow the user to press a keypad number to boot into another bootloader but there is no indication which one is which. Add a new screen for this. It is entered via Ctrl-L and shows the available bootloaders, along with the number to press for each. The contents of the screen is rendered by the bootloader, as usual. This is supported by two new screens, one for the keyboard UI and one for the menu UI. Also a new function, VbExGetAltFwIdxMask(), is added to find out what bootloaders are available. Note: This CL combines changes for both UIs. The changes may be easier to review separately. CQ-DEPEND=CL:1273269 BUG=chromium:837018 BRANCH=none TEST=FEATURES=test emerge-grunt --nodeps vboot_reference Change-Id: Ib3227545dc677c8f9587944753e32f3b49647360 Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1273268 Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/1351848 Reviewed-by: Martin Roth <martinroth@chromium.org> Tested-by: Martin Roth <martinroth@chromium.org>
-rw-r--r--firmware/include/vboot_api.h19
-rw-r--r--firmware/lib/include/vboot_ui_common.h17
-rw-r--r--firmware/lib/include/vboot_ui_menu_private.h1
-rw-r--r--firmware/lib/vboot_display.c5
-rw-r--r--firmware/lib/vboot_ui.c97
-rw-r--r--firmware/lib/vboot_ui_common.c17
-rw-r--r--firmware/lib/vboot_ui_menu.c100
-rw-r--r--tests/vboot_api_kernel2_tests.c24
-rw-r--r--tests/vboot_detach_menu_tests.c97
-rw-r--r--tests/vboot_display_tests.c6
10 files changed, 320 insertions, 63 deletions
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index 9d0ec3f3..5eedcaab 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -667,6 +667,10 @@ enum VbScreenType_t {
VB_SCREEN_OPTIONS_MENU = 0x210,
/* Alt OS picker screen */
VB_SCREEN_ALT_OS = 0x211,
+ /* Alt firmware picker screen (for keyboard UI) */
+ VB_SCREEN_ALT_FW_PICK = 0x212,
+ /* Alt firmware menu screen (for detachable UI ) */
+ VB_SCREEN_ALT_FW_MENU = 0x213,
};
/**
@@ -994,6 +998,21 @@ uint8_t VbExOverrideGptEntryPriority(const GptEntry *e);
*/
VbError_t VbExGetLocalizationCount(uint32_t *count);
+enum vb_altfw {
+ VB_ALTFW_COUNT = 9, /* We allow 9 bootloaders, numbered 1-9 */
+};
+
+/**
+ * Get a mask of available alternative firmware options
+ *
+ * There are up to 9 bootloaders, numbered 1 to 9, using bits 1 to 9 of this
+ * mask. Bit 0 is unused.
+ *
+ * @return Bit mask indicating which bootloaders are present (bit n indicates
+ * bootloader n is present)
+ */
+uint32_t VbExGetAltFwIdxMask(void);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/firmware/lib/include/vboot_ui_common.h b/firmware/lib/include/vboot_ui_common.h
index 19c3809d..30ade5a6 100644
--- a/firmware/lib/include/vboot_ui_common.h
+++ b/firmware/lib/include/vboot_ui_common.h
@@ -28,4 +28,21 @@ void vb2_error_beep(enum vb2_beep_type beep);
*/
void vb2_run_altfw(int altfw_num);
+/** 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.
+ *
+ * If the operation is not permitted, or it is permitted but the bootloader
+ * cannot be found, it beeps and returns.
+ *
+ * @allowed 1 if allowed, 0 if not allowed
+ * @altfw_num Number of bootloader to start (0=any, 1=first, etc.)
+ */
+void vb2_try_alt_fw(int allowed, int altfw_num);
+
#endif /* VBOOT_REFERENCE_VBOOT_UI_COMMON_H_ */
diff --git a/firmware/lib/include/vboot_ui_menu_private.h b/firmware/lib/include/vboot_ui_menu_private.h
index e07ece07..828a4a0f 100644
--- a/firmware/lib/include/vboot_ui_menu_private.h
+++ b/firmware/lib/include/vboot_ui_menu_private.h
@@ -33,6 +33,7 @@ typedef enum _VB_MENU {
VB_MENU_RECOVERY_NO_GOOD,
VB_MENU_RECOVERY_BROKEN,
VB_MENU_TO_NORM_CONFIRMED,
+ VB_MENU_ALT_FW,
VB_MENU_COUNT,
} VB_MENU;
diff --git a/firmware/lib/vboot_display.c b/firmware/lib/vboot_display.c
index b34976d1..c7607726 100644
--- a/firmware/lib/vboot_display.c
+++ b/firmware/lib/vboot_display.c
@@ -30,6 +30,11 @@ VbError_t VbExGetLocalizationCount(uint32_t *count) {
return VBERROR_UNKNOWN;
}
+__attribute__((weak))
+VbError_t VbExGetAltFwIdxMask(void) {
+ return 0;
+}
+
VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force)
{
uint32_t locale;
diff --git a/firmware/lib/vboot_ui.c b/firmware/lib/vboot_ui.c
index 63ae9cc5..71a7ceb3 100644
--- a/firmware/lib/vboot_ui.c
+++ b/firmware/lib/vboot_ui.c
@@ -73,31 +73,6 @@ static int VbWantShutdown(struct vb2_context *ctx, uint32_t key)
return !!shutdown_request;
}
-/**
- * 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.
- *
- * If the operation is not permitted, or it is permitted but the bootloader
- * cannot be found, it beeps and returns.
- *
- * @allowed 1 if allowed, 0 if not allowed
- * @altfw_num Number of bootloader to start (0=any, 1=first, etc.)
- */
-static void vb2_try_alt_fw(int allowed, int altfw_num)
-{
- if (allowed) {
- vb2_run_altfw(altfw_num); /* will not return if found */
- } else {
- VB2_DEBUG("VbBootDeveloper() - Legacy boot is disabled\n");
- VbExDisplayDebugInfo("WARNING: Booting legacy BIOS has not "
- "been enabled. Refer to the developer"
- "-mode documentation for details.\n");
- vb2_error_beep(VB_BEEP_NOT_ALLOWED);
- }
-}
-
uint32_t VbTryUsb(struct vb2_context *ctx)
{
uint32_t retval = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE);
@@ -186,6 +161,62 @@ int VbUserConfirms(struct vb2_context *ctx, uint32_t confirm_flags)
/* Delay in developer ui */
#define DEV_KEY_DELAY 20 /* Check keys every 20ms */
+/*
+ * 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.
+ */
+VbError_t vb2_altfw_ui(struct vb2_context *ctx)
+{
+ int active = 1;
+
+ VbDisplayScreen(ctx, VB_SCREEN_ALT_FW_PICK, 0);
+
+ /* We'll loop until the user decides what to do */
+ do {
+ uint32_t key = VbExKeyboardRead();
+
+ if (VbWantShutdown(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_run_altfw(key - '0');
+ active = 0;
+ break;
+ default:
+ VB2_DEBUG("VbBootDeveloper() - pressed key %d\n", key);
+ VbCheckDisplayKey(ctx, key);
+ break;
+ }
+ VbExSleepMs(DEV_KEY_DELAY);
+ } while (active);
+
+ /* Back to developer screen */
+ VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0);
+
+ 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"
@@ -349,10 +380,17 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx)
break;
case 0x0c:
VB2_DEBUG("VbBootDeveloper() - "
- "user pressed Ctrl+L; Try legacy boot\n");
- vb2_try_alt_fw(allow_legacy, 0);
- break;
+ "user pressed Ctrl+L; Try alt firmware\n");
+ if (allow_legacy) {
+ int 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;
@@ -386,7 +424,8 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx)
}
}
break;
- case '1'...'9':
+ /* We allow selection of the default '0' bootloader here */
+ case '0'...'9':
VB2_DEBUG("VbBootDeveloper() - "
"user pressed key '%c': Boot alternative "
"firmware\n", key);
diff --git a/firmware/lib/vboot_ui_common.c b/firmware/lib/vboot_ui_common.c
index 727ed779..df1615d1 100644
--- a/firmware/lib/vboot_ui_common.c
+++ b/firmware/lib/vboot_ui_common.c
@@ -38,3 +38,20 @@ void vb2_run_altfw(int altfw_num)
VbExLegacy(altfw_num); /* will not return if found */
vb2_error_beep(VB_BEEP_FAILED);
}
+
+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");
+ vb2_error_beep(VB_BEEP_NOT_ALLOWED);
+}
+
+void vb2_try_alt_fw(int allowed, int altfw_num)
+{
+ if (allowed)
+ vb2_run_altfw(altfw_num); /* will not return if found */
+ else
+ vb2_error_no_altfw();
+}
diff --git a/firmware/lib/vboot_ui_menu.c b/firmware/lib/vboot_ui_menu.c
index 9bbc2c70..e547f38a 100644
--- a/firmware/lib/vboot_ui_menu.c
+++ b/firmware/lib/vboot_ui_menu.c
@@ -36,6 +36,7 @@ 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
@@ -86,7 +87,6 @@ static void vb2_change_menu(VB_MENU new_current_menu,
{
prev_menu = current_menu;
current_menu = new_current_menu;
- current_menu_idx = new_current_menu_idx;
/* Reconfigure disabled_idx_mask for the new menu */
disabled_idx_mask = 0;
@@ -97,6 +97,19 @@ static void vb2_change_menu(VB_MENU new_current_menu,
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;
}
/************************
@@ -118,8 +131,6 @@ static VbError_t boot_disk_action(struct vb2_context *ctx)
/* Boot legacy BIOS if allowed and available. */
static VbError_t boot_legacy_action(struct vb2_context *ctx)
{
- const char no_legacy[] = "Legacy boot failed. Missing BIOS?\n";
-
if (disable_dev_boot) {
vb2_flash_screen(ctx);
vb2_error_beep(VB_BEEP_NOT_ALLOWED);
@@ -258,6 +269,26 @@ static VbError_t enter_to_norm_menu(struct vb2_context *ctx)
return VBERROR_KEEP_LOOPING;
}
+/* Boot alternative bootloader if allowed and available. */
+static VbError_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 VbError_t debug_info_action(struct vb2_context *ctx)
{
VbDisplayDebugInfo(ctx);
@@ -298,6 +329,17 @@ static VbError_t language_action(struct vb2_context *ctx)
}
}
+/* Action when selecting a bootloader in the alternative firmware menu. */
+static VbError_t altfw_action(struct vb2_context *ctx)
+{
+ vb2_run_altfw(current_menu_idx + 1);
+ vb2_flash_screen(ctx);
+ VB2_DEBUG(no_legacy);
+ VbExDisplayDebugInfo(no_legacy);
+
+ return VBERROR_KEEP_LOOPING;
+}
+
/* Action that enables developer mode and reboots. */
static VbError_t to_dev_action(struct vb2_context *ctx)
{
@@ -481,7 +523,7 @@ static struct vb2_menu menus[VB_MENU_COUNT] = {
},
[VB_DEV_LEGACY] = {
.text = "Boot Legacy BIOS",
- .action = boot_legacy_action,
+ .action = enter_altfw_menu,
},
[VB_DEV_USB] = {
.text = "Boot From USB or SD Card",
@@ -595,6 +637,42 @@ static struct vb2_menu menus[VB_MENU_COUNT] = {
.screen = VB_SCREEN_TO_NORM_CONFIRMED,
.items = NULL,
},
+ [VB_MENU_ALT_FW] = {
+ .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. */
@@ -614,6 +692,7 @@ static VbError_t vb2_init_menus(struct vb2_context *ctx)
return VBERROR_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;
}
@@ -679,14 +758,21 @@ static VbError_t vb2_developer_menu(struct vb2_context *ctx)
ret = boot_disk_action(ctx);
break;
case 'L' & 0x1f:
- /* Ctrl+L = boot legacy BIOS */
- ret = boot_legacy_action(ctx);
+ /* Ctrl+L = boot alternative bootloader */
+ ret = enter_altfw_menu(ctx);
break;
case VB_BUTTON_VOL_UP_LONG_PRESS:
case 'U' & 0x1f:
/* 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_alt_fw(altfw_allowed, key - '0');
+ break;
default:
ret = vb2_handle_menu_input(ctx, key, 0);
break;
@@ -703,7 +789,7 @@ static VbError_t vb2_developer_menu(struct vb2_context *ctx)
VbExSleepMs(DEV_KEY_DELAY);
/* If dev mode was disabled, loop forever (never timeout) */
- } while(disable_dev_boot ? 1 : vb2_audio_looping());
+ } 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. */
diff --git a/tests/vboot_api_kernel2_tests.c b/tests/vboot_api_kernel2_tests.c
index 2f76490a..2f1dee90 100644
--- a/tests/vboot_api_kernel2_tests.c
+++ b/tests/vboot_api_kernel2_tests.c
@@ -484,25 +484,49 @@ static void VbBootDevTest(void)
TEST_EQ(VbBootDeveloper(&ctx), 1002, "Ctrl+L normal");
TEST_EQ(vbexlegacy_called, 0, " not legacy");
+ /* Enter altfw menu and time out */
ResetMocks();
+ shutdown_request_calls_left = 1000;
sd->gbb_flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
mock_keypress[0] = 0x0c;
+ TEST_EQ(VbBootDeveloper(&ctx), VBERROR_SHUTDOWN_REQUESTED,
+ "Ctrl+L force legacy");
+ TEST_EQ(vbexlegacy_called, 0, " try legacy");
+
+ /* Enter altfw menu and select firmware 0 */
+ ResetMocks();
+ sd->gbb_flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
+ mock_keypress[0] = 0x0c;
+ mock_keypress[1] = '0';
TEST_EQ(VbBootDeveloper(&ctx), 1002,
"Ctrl+L force legacy");
TEST_EQ(vbexlegacy_called, 1, " try legacy");
TEST_EQ(altfw_num, 0, " check altfw_num");
+ /* Enter altfw menu and then exit it */
+ ResetMocks();
+ vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
+ mock_keypress[0] = 0x0c;
+ mock_keypress[1] = VB_KEY_ESC;
+ TEST_EQ(VbBootDeveloper(&ctx), 1002,
+ "Ctrl+L nv legacy");
+ TEST_EQ(vbexlegacy_called, 0, " try legacy");
+
+ /* Enter altfw menu and select firmware 0 */
ResetMocks();
vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
mock_keypress[0] = 0x0c;
+ mock_keypress[1] = '0';
TEST_EQ(VbBootDeveloper(&ctx), 1002,
"Ctrl+L nv legacy");
TEST_EQ(vbexlegacy_called, 1, " try legacy");
TEST_EQ(altfw_num, 0, " check altfw_num");
+ /* Enter altfw menu and select firmware 0 */
ResetMocks();
VbApiKernelGetFwmp()->flags |= FWMP_DEV_ENABLE_LEGACY;
mock_keypress[0] = 0x0c;
+ mock_keypress[1] = '0';
TEST_EQ(VbBootDeveloper(&ctx), 1002,
"Ctrl+L fwmp legacy");
TEST_EQ(vbexlegacy_called, 1, " fwmp legacy");
diff --git a/tests/vboot_detach_menu_tests.c b/tests/vboot_detach_menu_tests.c
index 6ec9f334..a9034b33 100644
--- a/tests/vboot_detach_menu_tests.c
+++ b/tests/vboot_detach_menu_tests.c
@@ -56,6 +56,8 @@ static uint32_t screens_displayed[64];
static uint32_t screens_count = 0;
static uint32_t beeps_played[64];
static uint32_t beeps_count = 0;
+static uint32_t mock_altfw_mask;
+static int vbexaltfwmask_called;
extern enum VbEcBootMode_t VbGetMode(void);
extern struct RollbackSpaceFwmp *VbApiKernelGetFwmp(void);
@@ -107,6 +109,9 @@ static void ResetMocks(void)
memset(mock_switches, 0, sizeof(mock_switches));
mock_switches_count = 0;
mock_switches_are_stuck = 0;
+
+ mock_altfw_mask = 3 << 1; /* This mask selects 1 and 2 */
+ vbexaltfwmask_called = 0;
}
static void ResetMocksForDeveloper(void)
@@ -127,6 +132,13 @@ static void ResetMocksForManualRecovery(void)
/* Mock functions */
+uint32_t VbExGetAltFwIdxMask() {
+
+ vbexaltfwmask_called++;
+
+ return mock_altfw_mask;
+}
+
uint32_t VbExIsShutdownRequested(void)
{
if (shutdown_request_calls_left == 0)
@@ -614,17 +626,18 @@ static void VbBootDevTest(void)
ResetMocksForDeveloper();
sd->gbb_flags |= GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
mock_keypress[0] = 'L' & 0x1f;
+ mock_keypress[1] = VB_BUTTON_POWER_SHORT_PRESS;
TEST_EQ(VbBootDeveloperMenu(&ctx), vbtlk_retval_fixed,
"Ctrl+L force legacy");
TEST_EQ(vbexlegacy_called, 1, " try legacy");
- TEST_EQ(altfw_num, 0, " check altfw_num");
+ TEST_EQ(altfw_num, 1, " check altfw_num");
TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU,
" warning screen");
- TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)");
- TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU,
- " warning screen");
- TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen");
- TEST_EQ(screens_count, 4, " no extra screens");
+ TEST_EQ(screens_displayed[1], VB_SCREEN_ALT_FW_MENU, " altfw");
+ TEST_EQ(screens_displayed[2], VB_SCREEN_BLANK, " blank (error flash)");
+ TEST_EQ(screens_displayed[3], VB_SCREEN_ALT_FW_MENU, " altfw");
+ TEST_EQ(screens_displayed[4], VB_SCREEN_BLANK, " blank (error flash)");
+ TEST_EQ(screens_count, 5, " no extra screens");
TEST_EQ(beeps_count, 1, " error beep: legacy BIOS not found");
TEST_EQ(beeps_played[0], 200, " low-frequency error beep");
@@ -632,17 +645,18 @@ static void VbBootDevTest(void)
ResetMocksForDeveloper();
vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
mock_keypress[0] = 'L' & 0x1f;
+ mock_keypress[1] = VB_BUTTON_POWER_SHORT_PRESS;
TEST_EQ(VbBootDeveloperMenu(&ctx), vbtlk_retval_fixed,
"Ctrl+L nv legacy");
TEST_EQ(vbexlegacy_called, 1, " try legacy");
TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery");
TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU,
" warning screen");
- TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)");
- TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU,
- " warning screen");
- TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen");
- TEST_EQ(screens_count, 4, " no extra screens");
+ TEST_EQ(screens_displayed[1], VB_SCREEN_ALT_FW_MENU, " altfw");
+ TEST_EQ(screens_displayed[2], VB_SCREEN_BLANK, " blank (error flash)");
+ TEST_EQ(screens_displayed[3], VB_SCREEN_ALT_FW_MENU, " altfw");
+ TEST_EQ(screens_displayed[4], VB_SCREEN_BLANK, " blank (error flash)");
+ TEST_EQ(screens_count, 5, " no extra screens");
TEST_EQ(beeps_count, 1, " error beep: legacy BIOS not found");
TEST_EQ(beeps_played[0], 200, " low-frequency error beep");
@@ -650,20 +664,23 @@ static void VbBootDevTest(void)
ResetMocksForDeveloper();
VbApiKernelGetFwmp()->flags |= FWMP_DEV_ENABLE_LEGACY;
mock_keypress[0] = 'L' & 0x1f;
+ mock_keypress[1] = VB_BUTTON_POWER_SHORT_PRESS;
TEST_EQ(VbBootDeveloperMenu(&ctx), vbtlk_retval_fixed,
"Ctrl+L fwmp legacy");
TEST_EQ(vbexlegacy_called, 1, " fwmp legacy");
- TEST_EQ(altfw_num, 0, " check altfw_num");
+ TEST_EQ(altfw_num, 1, " check altfw_num");
TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU,
" warning screen");
- TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)");
- TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU,
- " warning screen");
- TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen");
- TEST_EQ(screens_count, 4, " no extra screens");
+ TEST_EQ(screens_displayed[1], VB_SCREEN_ALT_FW_MENU, " altfw");
+ TEST_EQ(screens_displayed[2], VB_SCREEN_BLANK, " blank (error flash)");
+ TEST_EQ(screens_displayed[3], VB_SCREEN_ALT_FW_MENU, " altfw");
+ TEST_EQ(screens_displayed[4], VB_SCREEN_BLANK, " final blank screen");
+ TEST_EQ(screens_count, 5, " no extra screens");
TEST_EQ(beeps_count, 1, " error beep: legacy BIOS not found");
TEST_EQ(beeps_played[0], 200, " low-frequency error beep");
+ /* TODO(sjg@chromium.org): Add a test for there being no bootloaders */
+
/* Ctrl+U boots USB only if enabled */
ResetMocksForDeveloper();
mock_keypress[0] = 'U' & 0x1f;
@@ -908,8 +925,9 @@ static void VbBootDevTest(void)
mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS Verif
mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info
mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options
- mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS;
- mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS;
+ mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Enter altfw menu
+ mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Select first option
+ mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // and again
vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT, VB2_DEV_DEFAULT_BOOT_LEGACY);
TEST_EQ(VbBootDeveloperMenu(&ctx), vbtlk_retval_fixed,
@@ -930,13 +948,12 @@ static void VbBootDevTest(void)
" dev warning menu: developer options");
TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU,
" dev menu: legacy boot");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw");
TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)");
- TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU,
- " dev menu: legacy boot");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw");
TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)");
- TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU,
- " dev menu: legacy boot");
- TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen");
TEST_EQ(screens_count, i, " no extra screens");
TEST_EQ(beeps_count, 2, " two error beeps: legacy BIOS not found");
TEST_EQ(beeps_played[0], 200, " low-frequency error beep");
@@ -1282,6 +1299,7 @@ static void VbBootRecTest(void)
TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen");
TEST_EQ(screens_count, 2, " no extra screens");
TEST_EQ(beeps_count, 0, " no beep on shutdown");
+ TEST_EQ(vbexaltfwmask_called, 0, " VbExGetAltFwIdxMask not called");
/* BROKEN screen with disks inserted */
ResetMocks();
@@ -2192,13 +2210,23 @@ static void VbNavigationTest(void)
mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From USB
mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot Legacy
mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // (end of menu)
- mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS;
+ mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Select altfw menu
+ mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Second altfw
+ mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Cancel
+ mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // (end of menu)
+ mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Back to dev options
+ mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From Disk
+ mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From USB
+ mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot Legacy
+ mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Select altfw menu
+ mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Second altfw
+ mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Select 2nd altfw
vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
TEST_EQ(VbBootDeveloperMenu(&ctx), vbtlk_retval_fixed,
"developer mode long navigation");
TEST_EQ(debug_info_displayed, 1, " showed debug info");
TEST_EQ(vbexlegacy_called, 1, " tried legacy");
- TEST_EQ(altfw_num, 0, " check altfw_num");
+ TEST_EQ(altfw_num, 2, " check altfw_num");
TEST_EQ(audio_looping_calls_left, 0, " audio timeout");
TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery");
i = 0;
@@ -2280,9 +2308,24 @@ static void VbNavigationTest(void)
" dev menu: boot legacy");
TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU,
" dev menu: boot legacy");
- TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw 1");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw 2");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU,
+ " altfw cancel");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU,
+ " altfw end");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU,
+ " dev menu: cancel");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU,
+ " dev menu: boot from disk");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU,
+ " dev menu: boot from USB");
TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU,
" dev menu: boot legacy");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)");
+ TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw");
TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen");
TEST_EQ(screens_count, i, " no extra screens");
TEST_EQ(beeps_count, 1, " error beep: legacy BIOS not found");
diff --git a/tests/vboot_display_tests.c b/tests/vboot_display_tests.c
index 71b66aeb..ef9d1466 100644
--- a/tests/vboot_display_tests.c
+++ b/tests/vboot_display_tests.c
@@ -33,6 +33,7 @@ static struct vb2_context ctx;
struct vb2_shared_data *sd;
static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE];
static uint32_t mock_localization_count;
+static uint32_t mock_altfw_mask;
/* Reset mock data (for use before each test) */
static void ResetMocks(void)
@@ -51,6 +52,7 @@ static void ResetMocks(void)
gbb_used = (gbb_used + gbb->hwid_size + 7) & ~7;
mock_localization_count = 3;
+ mock_altfw_mask = 3 << 1; /* This mask selects 1 and 2 */
gbb->header_size = sizeof(*gbb);
gbb->rootkey_offset = gbb_used;
@@ -88,6 +90,10 @@ VbError_t VbExGetLocalizationCount(uint32_t *count) {
return VBERROR_SUCCESS;
}
+uint32_t VbExGetAltFwIdxMask() {
+ return mock_altfw_mask;
+}
+
VbError_t VbExDisplayDebugInfo(const char *info_str)
{
strncpy(debug_info, info_str, sizeof(debug_info));