summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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));