summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2015-10-20 18:31:10 -0700
committerchrome-bot <chrome-bot@chromium.org>2015-10-26 11:24:18 -0700
commit3a631486bddaeab1e8cc2abe0fb725721f2a0be0 (patch)
treebb6ae76d4965913377ec526fa1e7a9f813f22462
parentbe5eca9126a048d7187d5c96de46d27df3b1359c (diff)
downloadvboot-3a631486bddaeab1e8cc2abe0fb725721f2a0be0.tar.gz
Save recovery reason before user three-finger-salutes
When a user hits esc+refresh+power to start recovery, the true recovery reason will be lost after reboot. (It would always look like VB2_RECOVERY_RO_MANUAL.) This patch makes VbBootRecovery save the reason in the subcode area before entering the new 'broken' loop. BUG=chromium:501060 BRANCH=tot TEST=test_that -b veyron_jerry suite:faft_bios Change-Id: Ib536daa0633721bfc975381782d348f122b3d337 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/307586 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--firmware/2lib/2misc.c35
-rw-r--r--firmware/lib/vboot_api_kernel.c35
2 files changed, 48 insertions, 22 deletions
diff --git a/firmware/2lib/2misc.c b/firmware/2lib/2misc.c
index a8567758..a955f536 100644
--- a/firmware/2lib/2misc.c
+++ b/firmware/2lib/2misc.c
@@ -139,29 +139,34 @@ int vb2_init_context(struct vb2_context *ctx)
void vb2_check_recovery(struct vb2_context *ctx)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
+ uint32_t reason = vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST);
+ uint32_t subcode = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE);
+
+ VB2_DEBUG("Recovery reason from previous boot: %#x / %#x\n",
+ reason, subcode);
/*
- * Read the current recovery request, unless there's already been a
+ * Sets the current recovery request, unless there's already been a
* failure earlier in the boot process.
*/
if (!sd->recovery_reason)
- sd->recovery_reason = vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST);
+ sd->recovery_reason = reason;
- /* Clear the recovery request so we don't get stuck in recovery mode */
- if (sd->recovery_reason) {
- vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST,
- VB2_RECOVERY_NOT_REQUESTED);
- /*
- * Note that we ignore failures clearing the request. We only
- * hit this code path if recovery mode has already been
- * requested, so what more can we do? Don't want to obscure
- * the original reason for going into recovery mode.
- */
- }
+ /* Clear request and subcode so we don't get stuck in recovery mode */
+ vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, VB2_RECOVERY_NOT_REQUESTED);
+ vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, VB2_RECOVERY_NOT_REQUESTED);
- /* If forcing recovery, override recovery reason */
if (ctx->flags & VB2_CONTEXT_FORCE_RECOVERY_MODE) {
- sd->recovery_reason = VB2_RECOVERY_RO_MANUAL;
+ VB2_DEBUG("Recovery was requested manually\n");
+ if (subcode && !sd->recovery_reason)
+ /*
+ * Recovery was requested at 'broken' screen.
+ * Promote subcode to reason.
+ */
+ sd->recovery_reason = subcode;
+ else
+ /* Recovery was forced. Override recovery reason */
+ sd->recovery_reason = VB2_RECOVERY_RO_MANUAL;
sd->flags |= VB2_SD_FLAG_MANUAL_RECOVERY;
}
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 7b47dc69..fcec4cb7 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -41,6 +41,19 @@ static void VbSetRecoveryRequest(uint32_t recovery_request)
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, recovery_request);
}
+static void VbSetRecoverySubcode(uint32_t recovery_request)
+{
+ VBDEBUG(("VbSetRecoverySubcode(%d)\n", (int)recovery_request));
+ VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE, recovery_request);
+}
+
+static void VbNvCommit(void)
+{
+ VbNvTeardown(&vnc);
+ if (vnc.raw_changed)
+ VbExNvStorageWrite(vnc.raw);
+}
+
static void VbAllowUsbBoot(void)
{
VBDEBUG(("%s\n", __func__));
@@ -500,8 +513,20 @@ VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p)
*/
if (!(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
!(shared->flags & VBSD_BOOT_REC_SWITCH_ON)) {
- VBDEBUG(("VbBootRecovery() waiting for manual recovery\n"));
+ /*
+ * We have to save the reason here so that it will survive
+ * coming up three-finger-salute. We're saving it in
+ * VBNV_RECOVERY_SUBCODE to avoid a recovery loop.
+ * If we save the reason in VBNV_RECOVERY_REQUEST, we will come
+ * back here, thus, we won't be able to give a user a chance to
+ * reboot to workaround boot hicups.
+ */
+ VBDEBUG(("VbBootRecovery() saving recovery reason (%#x)\n",
+ shared->recovery_reason));
+ VbSetRecoverySubcode(shared->recovery_reason);
+ VbNvCommit();
VbDisplayScreen(cparams, VB_SCREEN_OS_BROKEN, 0, &vnc);
+ VBDEBUG(("VbBootRecovery() waiting for manual recovery\n"));
while (1) {
VbCheckDisplayKey(cparams, VbExKeyboardRead(), &vnc);
if (VbWantShutdown(cparams->gbb->flags))
@@ -1171,9 +1196,7 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams,
VbApiKernelFree(cparams);
- VbNvTeardown(&vnc);
- if (vnc.raw_changed)
- VbExNvStorageWrite(vnc.raw);
+ VbNvCommit();
/* Stop timer */
shared->timer_vb_select_and_load_kernel_exit = VbExGetTimer();
@@ -1343,9 +1366,7 @@ VbError_t VbLockDevice(void)
VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST,
1);
- VbNvTeardown(&vnc);
- if (vnc.raw_changed)
- VbExNvStorageWrite(vnc.raw);
+ VbNvCommit();
VBDEBUG(("%s() Mode change will take effect on next reboot.\n",
__func__));