firmware: Add recovery menu support for detachables

Adding in basic menu support (using arrow keys) for
detachables.  This is specifically for the recovery menu.

BUG=chrome-os-partner:61275
BRANCH=None
TEST=reboot into recovery and try booting into developer mode.

Change-Id: I9596cde62f2748928b4b796bde0a0226dc981235
Signed-off-by: Shelley Chen <shchen@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/424354
This commit is contained in:
Shelley Chen
2016-12-27 14:10:26 -08:00
committed by chrome-bot
parent 71c6c033f9
commit 755bf33ad1

View File

@@ -162,6 +162,8 @@ typedef enum _VB_MENU {
VB_MENU_DEV_WARNING,
VB_MENU_DEV,
VB_MENU_TO_NORM,
VB_MENU_RECOVERY,
VB_MENU_TO_DEV,
VB_MENU_COUNT,
} VB_MENU;
@@ -193,6 +195,22 @@ typedef enum _VB_TO_NORM_MENU {
VB_TO_NORM_COUNT,
} VB_TO_NORM_MENU;
typedef enum _VB_RECOVERY_MENU {
VB_RECOVERY_TO_DEV,
VB_RECOVERY_DBG_INFO,
VB_RECOVERY_POWER_OFF,
VB_RECOVERY_LANGUAGE,
VB_RECOVERY_COUNT,
} VB_RECOVERY_MENU;
typedef enum _VB_TO_DEV_MENU {
VB_TO_DEV_CONFIRM,
VB_TO_DEV_CANCEL,
VB_TO_DEV_POWER_OFF,
VB_TO_DEV_LANGUAGE,
VB_TO_DEV_COUNT,
} VB_TO_DEV_MENU;
static VB_MENU current_menu = VB_MENU_DEV_WARNING;
static int current_menu_idx = 0;
static int selected = 0;
@@ -223,6 +241,20 @@ static char *to_normal_menu[] = {
"Language\n"
};
static char *recovery_menu[] = {
"Enable developer mode\n",
"Show Debug Info\n",
"Power Off\n",
"Language\n"
};
static char *to_dev_menu[] = {
"Confirm enabling developer mode\n",
"Cancel\n",
"Power Off\n",
"Language\n"
};
// function that gets the current menu string array and size.
// can set menu_array to NULL and only return string size.
VbError_t vb2_get_current_menu_size(VB_MENU menu, char ***menu_array, int *size)
@@ -242,6 +274,14 @@ VbError_t vb2_get_current_menu_size(VB_MENU menu, char ***menu_array, int *size)
*size = VB_TO_NORM_COUNT;
temp_menu = to_normal_menu;
break;
case VB_MENU_RECOVERY:
*size = VB_RECOVERY_COUNT;
temp_menu = recovery_menu;
break;
case VB_MENU_TO_DEV:
*size = VB_TO_DEV_COUNT;
temp_menu = to_dev_menu;
break;
default:
*size = 0;
return VBERROR_UNKNOWN;
@@ -286,7 +326,7 @@ VbError_t vb2_print_current_menu()
}
VB2_DEBUG("%s", m_str);
return VbExDisplayText(0,0,m_str);
return VbExDisplayText(0,50,m_str);
}
// This updates current_menu and current_menu_idx,
@@ -381,6 +421,46 @@ VbError_t vb2_update_menu()
break;
}
break;
case VB_MENU_RECOVERY:
switch(current_menu_idx) {
case VB_RECOVERY_TO_DEV:
// switch to TO_DEV menu
current_menu = VB_MENU_TO_DEV;
current_menu_idx = 0;
selected = 0;
break;
case VB_RECOVERY_DBG_INFO:
break;
case VB_RECOVERY_POWER_OFF:
ret = VBERROR_SHUTDOWN_REQUESTED;
break;
case VB_RECOVERY_LANGUAGE:
break;
default:
// invalid menu item. don't update anything
break;
}
break;
case VB_MENU_TO_DEV:
switch(current_menu_idx) {
case VB_TO_DEV_CONFIRM:
// confirm enabling dev mode
break;
case VB_TO_DEV_CANCEL:
current_menu = VB_MENU_RECOVERY;
current_menu_idx = 0;
selected = 0;
break;
case VB_TO_DEV_POWER_OFF:
ret = VBERROR_SHUTDOWN_REQUESTED;
break;
case VB_TO_DEV_LANGUAGE:
break;
default:
// invalid menu item. don't update anything.
break;
}
break;
default:
VB2_DEBUG("Current Menu Invalid!");
}
@@ -662,8 +742,10 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams)
uint32_t retval;
uint32_t key;
int i;
VbError_t ret;
int menu_size;
VBDEBUG(("VbBootRecoveryMenu() start\n"));
VB2_DEBUG("VbBootRecoveryMenu() start\n");
/*
* If the dev-mode switch is off and the user didn't press the recovery
@@ -681,8 +763,8 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams)
* back here, thus, we won't be able to give a user a chance to
* reboot to workaround boot hicups.
*/
VBDEBUG(("VbBootRecoveryMenu() saving recovery reason (%#x)\n",
shared->recovery_reason));
VB2_DEBUG("VbBootRecoveryMenu() saving recovery reason (%#x)\n",
shared->recovery_reason);
vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE,
shared->recovery_reason);
/*
@@ -692,7 +774,7 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams)
vb2_nv_commit(ctx);
VbDisplayScreen(ctx, cparams, VB_SCREEN_OS_BROKEN, 0);
VBDEBUG(("VbBootRecoveryMenu() waiting for manual recovery\n"));
VB2_DEBUG("VbBootRecoveryMenu() waiting for manual recovery\n");
while (1) {
VbCheckDisplayKey(ctx, cparams, VbExKeyboardRead());
if (VbWantShutdownMenu(cparams->gbb->flags))
@@ -702,9 +784,13 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams)
}
/* Loop and wait for a recovery image */
VBDEBUG(("VbBootRecoveryMenu() waiting for a recovery image\n"));
VB2_DEBUG("VbBootRecoveryMenu() waiting for a recovery image\n");
// initialize menu to recovery menu.
current_menu = VB_MENU_RECOVERY;
current_menu_idx = 0;
while (1) {
VBDEBUG(("VbBootRecoveryMenu() attempting to load kernel2\n"));
VB2_DEBUG("VbBootRecoveryMenu() attempting to load kernel2\n");
retval = VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_REMOVABLE);
/*
@@ -723,6 +809,10 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams)
VB_SCREEN_RECOVERY_INSERT :
VB_SCREEN_RECOVERY_NO_GOOD,
0);
if (current_menu != VB_MENU_RECOVERY ||
current_menu_idx != VB_RECOVERY_DBG_INFO) {
vb2_print_current_menu();
}
/*
* Scan keyboard more frequently than media, since x86
@@ -730,72 +820,94 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams)
*/
for (i = 0; i < REC_DISK_DELAY; i += REC_KEY_DELAY) {
key = VbExKeyboardRead();
/*
* We might want to enter dev-mode from the Insert
* screen if all of the following are true:
* - user pressed Ctrl-D
* - we can honor the virtual dev switch
* - not already in dev mode
* - user forced recovery mode
* - EC isn't pwned
*/
if (key == 0x04 &&
shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
!(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
(shared->flags & VBSD_BOOT_REC_SWITCH_ON) &&
VbExTrustEC(0)) {
if (!(shared->flags &
VBSD_BOOT_REC_SWITCH_VIRTUAL) &&
VbExGetSwitches(
VB_INIT_FLAG_REC_BUTTON_PRESSED)) {
/*
* Is the recovery button stuck? In
* any case we don't like this. Beep
* and ignore.
*/
VBDEBUG(("%s() - ^D but rec switch "
"is pressed\n", __func__));
VbExBeep(120, 400);
continue;
switch (key) {
case 0:
/* nothing pressed */
break;
case VB_KEY_UP:
VB2_DEBUG("VbBootRecoveryMenu() - pressed key VB_KEY_UP\n");
vb2_get_current_menu_size(current_menu, NULL, &menu_size);
current_menu_idx = (current_menu_idx+menu_size-1) % menu_size;
vb2_print_current_menu();
break;
case VB_KEY_DOWN:
VB2_DEBUG("VbBootRecoveryMenu() - pressed key VB_KEY_DOWN\n");
vb2_get_current_menu_size(current_menu, NULL, &menu_size);
current_menu_idx = (current_menu_idx+1) % menu_size;
vb2_print_current_menu();
break;
case VB_KEY_RIGHT:
// temporarily using this as a stand in for
// power button until get power button bypassed
VB2_DEBUG("VbBootRecoveryMenu() - pressed key VB_KEY_RIGHT (SELECT)\n");
selected = 1;
ret = vb2_update_menu();
if (current_menu != VB_MENU_RECOVERY ||
current_menu_idx != VB_RECOVERY_DBG_INFO) {
vb2_print_current_menu();
}
/* Ask the user to confirm entering dev-mode */
VbDisplayScreen(ctx, cparams,
VB_SCREEN_RECOVERY_TO_DEV,
0);
/* SPACE means no... */
uint32_t vbc_flags =
VB_CONFIRM_SPACE_MEANS_NO |
VB_CONFIRM_MUST_TRUST_KEYBOARD;
switch (VbUserConfirmsMenu(ctx, cparams,
vbc_flags)) {
case 1:
VBDEBUG(("%s() Enabling dev-mode...\n",
__func__));
// probably shutting down
if (ret != VBERROR_SUCCESS) {
VB2_DEBUG("VbBootRecoveryMenu() - update_menu - shutting down!\n");
return ret;
}
// nothing selected, skip everything else.
if (selected == 0)
break;
/* Display debug information */
if (current_menu == VB_MENU_RECOVERY &&
current_menu_idx == VB_RECOVERY_DBG_INFO) {
VbDisplayDebugInfo(ctx, cparams);
}
/* Confirm going into developer mode */
/*
* We might want to enter dev-mode from the Insert
* screen if all of the following are true:
* - user pressed Ctrl-D
* - we can honor the virtual dev switch
* - not already in dev mode
* - user forced recovery mode
* - EC isn't pwned
*/
// TODO: let's put an error here if we're
// already in dev mode.
if (current_menu == VB_MENU_TO_DEV &&
current_menu_idx == 0 &&
shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
!(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
(shared->flags & VBSD_BOOT_REC_SWITCH_ON) &&
VbExTrustEC(0)) {
if (!(shared->flags &
VBSD_BOOT_REC_SWITCH_VIRTUAL) &&
VbExGetSwitches(
VB_INIT_FLAG_REC_BUTTON_PRESSED)) {
/*
* Is the recovery button stuck? In
* any case we don't like this. Beep
* and ignore.
*/
VB2_DEBUG("%s() - ^D but rec switch "
"is pressed\n", __func__);
VbExBeep(120, 400);
continue;
}
VB2_DEBUG("%s() Enabling dev-mode...\n",
__func__);
if (TPM_SUCCESS != SetVirtualDevMode(1))
return VBERROR_TPM_SET_BOOT_MODE_STATE;
VBDEBUG(("%s() Reboot so it will take "
"effect\n", __func__));
VB2_DEBUG("%s() Reboot so it will take "
"effect\n", __func__);
if (VbExGetSwitches
(VB_INIT_FLAG_ALLOW_USB_BOOT))
VbAllowUsbBootMenu(ctx);
return VBERROR_REBOOT_REQUIRED;
case -1:
VBDEBUG(("%s() - Shutdown requested\n",
__func__));
return VBERROR_SHUTDOWN_REQUESTED;
default: /* zero, actually */
VBDEBUG(("%s() - Not enabling "
"dev-mode\n", __func__));
/*
* Jump out of the outer loop to
* refresh the display quickly.
*/
i = 4;
break;
}
} else {
VbCheckDisplayKey(ctx, cparams, key);
}
if (VbWantShutdownMenu(cparams->gbb->flags))
return VBERROR_SHUTDOWN_REQUESTED;