summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/2lib/2misc.c4
-rw-r--r--firmware/lib/vboot_api_kernel.c31
-rw-r--r--tests/vb2_api_tests.c12
-rw-r--r--tests/vb2_misc_tests.c4
-rw-r--r--tests/vboot_api_kernel4_tests.c10
5 files changed, 40 insertions, 21 deletions
diff --git a/firmware/2lib/2misc.c b/firmware/2lib/2misc.c
index bab4b211..43d39f8b 100644
--- a/firmware/2lib/2misc.c
+++ b/firmware/2lib/2misc.c
@@ -146,10 +146,6 @@ void vb2_check_recovery(struct vb2_context *ctx)
if (!sd->recovery_reason)
sd->recovery_reason = reason;
- /* 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 (ctx->flags & VB2_CONTEXT_FORCE_RECOVERY_MODE) {
VB2_DEBUG("Recovery was requested manually\n");
if (subcode && !sd->recovery_reason)
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 5139ba33..d6fab619 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -262,15 +262,6 @@ static vb2_error_t vb2_kernel_setup(struct vb2_context *ctx,
*/
sd->vbsd = shared;
- /*
- * If we're in recovery mode just to do memory retraining, all we
- * need to do is reboot.
- */
- if (sd->recovery_reason == VB2_RECOVERY_TRAIN_AND_REBOOT) {
- VB2_DEBUG("Reboot after retraining in recovery.\n");
- return VBERROR_REBOOT_REQUIRED;
- }
-
/* Fill in params for calls to LoadKernel() */
memset(&lkp, 0, sizeof(lkp));
lkp.kernel_buffer = kparams->kernel_buffer;
@@ -373,6 +364,7 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
VbSharedDataHeader *shared,
VbSelectAndLoadKernelParams *kparams)
{
+ struct vb2_shared_data *sd = vb2_get_sd(ctx);
vb2_error_t rv, call_rv;
rv = vb2_kernel_setup(ctx, shared, kparams);
@@ -401,6 +393,27 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
/* Select boot path */
if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
+ /*
+ * Clear recovery request and subcode from nvdata, so that we
+ * don't get stuck in recovery mode after reboot. Should be
+ * called at some point after we are certain the system does
+ * not require any reboots for non-vboot-related reasons (e.g.
+ * FSP initialization), and before triggering a reboot to exit
+ * transient recovery mode (e.g. memory retraining request).
+ */
+ 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 we're in recovery mode just to do memory retraining, all
+ we need to do is reboot. */
+ if (sd->recovery_reason == VB2_RECOVERY_TRAIN_AND_REBOOT) {
+ VB2_DEBUG("Reboot after retraining in recovery.\n");
+ rv = VBERROR_REBOOT_REQUIRED;
+ goto VbSelectAndLoadKernel_exit;
+ }
+
/* Recovery boot. This has UI. */
if (LEGACY_MENU_UI)
rv = VbBootRecoveryMenu(ctx);
diff --git a/tests/vb2_api_tests.c b/tests/vb2_api_tests.c
index c2a52dbb..9cb2f195 100644
--- a/tests/vb2_api_tests.c
+++ b/tests/vb2_api_tests.c
@@ -393,7 +393,7 @@ static void phase1_tests(void)
TEST_EQ(vb2_nv_get(ctx, VB2_NV_TPM_REQUESTED_REBOOT),
1, " tpm reboot request");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
- 0, " recovery request");
+ VB2_RECOVERY_RO_TPM_REBOOT, " recovery request");
reset_common_data(FOR_MISC);
ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT;
@@ -405,7 +405,7 @@ static void phase1_tests(void)
TEST_EQ(vb2_nv_get(ctx, VB2_NV_TPM_REQUESTED_REBOOT),
1, " tpm reboot request");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
- VB2_RECOVERY_RO_UNSPECIFIED, " recovery request not cleared");
+ VB2_RECOVERY_RO_UNSPECIFIED, " recovery request");
reset_common_data(FOR_MISC);
vb2_nv_set(ctx, VB2_NV_TPM_REQUESTED_REBOOT, 1);
@@ -416,8 +416,8 @@ static void phase1_tests(void)
" recovery reason");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_TPM_REQUESTED_REBOOT),
0, " tpm reboot request");
- TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0,
- " recovery request cleared");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
+ VB2_RECOVERY_RO_UNSPECIFIED, " recovery request");
reset_common_data(FOR_MISC);
ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT;
@@ -429,8 +429,8 @@ static void phase1_tests(void)
" recovery reason");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_TPM_REQUESTED_REBOOT),
1, " tpm reboot request");
- TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0,
- " recovery request cleared");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
+ VB2_RECOVERY_RO_UNSPECIFIED, " recovery request");
/* Cases for checking DISPLAY_INIT and DISPLAY_AVAILABLE. */
reset_common_data(FOR_MISC);
diff --git a/tests/vb2_misc_tests.c b/tests/vb2_misc_tests.c
index 22de3ae2..2a3f88dc 100644
--- a/tests/vb2_misc_tests.c
+++ b/tests/vb2_misc_tests.c
@@ -414,7 +414,7 @@ static void recovery_tests(void)
vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, 3);
vb2_check_recovery(ctx);
TEST_EQ(sd->recovery_reason, 3, "Recovery reason from request");
- TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, "NV cleared");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 3, "NV not cleared");
TEST_EQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY,
0, "Not manual recovery");
TEST_NEQ(ctx->flags & VB2_CONTEXT_RECOVERY_MODE,
@@ -427,7 +427,7 @@ static void recovery_tests(void)
vb2_check_recovery(ctx);
TEST_EQ(sd->recovery_reason, 5, "Recovery reason already failed");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
- 0, "NV still cleared");
+ 4, "NV not cleared");
/* Override */
reset_common_data();
diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c
index cbae595c..97a6b1d2 100644
--- a/tests/vboot_api_kernel4_tests.c
+++ b/tests/vboot_api_kernel4_tests.c
@@ -301,6 +301,16 @@ static void VbSlkTest(void)
commit_data_retval = VB2_ERROR_UNKNOWN;
test_slk(0, 0, "Recovery return unknown write error");
+ /* Boot recovery - nvstorage cleared */
+ ResetMocks();
+ sd->recovery_reason = 123;
+ vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, 5);
+ vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, 13);
+ test_slk(0, 0, "Recovery with nvstorage");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE),
+ 0, " recovery subcode cleared");
+
+ /* Boot recovery - memory retraining */
ResetMocks();
sd->recovery_reason = VB2_RECOVERY_TRAIN_AND_REBOOT;
test_slk(VBERROR_REBOOT_REQUIRED, 0, "Recovery train and reboot");