diff options
-rw-r--r-- | firmware/include/vboot_api.h | 19 | ||||
-rw-r--r-- | firmware/lib/include/vboot_ui_common.h | 17 | ||||
-rw-r--r-- | firmware/lib/include/vboot_ui_menu_private.h | 1 | ||||
-rw-r--r-- | firmware/lib/vboot_display.c | 5 | ||||
-rw-r--r-- | firmware/lib/vboot_ui.c | 97 | ||||
-rw-r--r-- | firmware/lib/vboot_ui_common.c | 17 | ||||
-rw-r--r-- | firmware/lib/vboot_ui_menu.c | 100 | ||||
-rw-r--r-- | tests/vboot_api_kernel2_tests.c | 24 | ||||
-rw-r--r-- | tests/vboot_detach_menu_tests.c | 97 | ||||
-rw-r--r-- | tests/vboot_display_tests.c | 6 |
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)); |