summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/vendorcode/google/chromeos/vboot2/Kconfig9
-rw-r--r--src/vendorcode/google/chromeos/vboot2/misc.h2
-rw-r--r--src/vendorcode/google/chromeos/vboot2/recovery.c34
-rw-r--r--src/vendorcode/google/chromeos/vboot2/vboot_loader.c1
4 files changed, 46 insertions, 0 deletions
diff --git a/src/vendorcode/google/chromeos/vboot2/Kconfig b/src/vendorcode/google/chromeos/vboot2/Kconfig
index 7580d8d50c..5aaf932042 100644
--- a/src/vendorcode/google/chromeos/vboot2/Kconfig
+++ b/src/vendorcode/google/chromeos/vboot2/Kconfig
@@ -78,3 +78,12 @@ config VBOOT_DYNAMIC_WORK_BUFFER
ram to allocate the vboot work buffer. That means vboot verification
is after memory init and requires main memory to back the work
buffer.
+
+config VBOOT_SAVE_RECOVERY_REASON_ON_REBOOT
+ bool
+ default n
+ depends on VBOOT_VERIFY_FIRMWARE
+ help
+ This option ensures that the recovery request is not lost because of
+ reboots caused after vboot verification is run. e.g. reboots caused by
+ FSP components on Intel platforms.
diff --git a/src/vendorcode/google/chromeos/vboot2/misc.h b/src/vendorcode/google/chromeos/vboot2/misc.h
index ca64b378df..9b771a24e3 100644
--- a/src/vendorcode/google/chromeos/vboot2/misc.h
+++ b/src/vendorcode/google/chromeos/vboot2/misc.h
@@ -35,4 +35,6 @@ int vb2_logic_executed(void);
/* Store the selected region in cbmem for later use. */
void vb2_store_selected_region(void);
+void vb2_save_recovery_reason_vbnv(void);
+
#endif /* __CHROMEOS_VBOOT2_MISC_H__ */
diff --git a/src/vendorcode/google/chromeos/vboot2/recovery.c b/src/vendorcode/google/chromeos/vboot2/recovery.c
index 2cd5e806ea..94a8cc3f37 100644
--- a/src/vendorcode/google/chromeos/vboot2/recovery.c
+++ b/src/vendorcode/google/chromeos/vboot2/recovery.c
@@ -14,6 +14,7 @@
*/
#include <assert.h>
+#include <bootstate.h>
#include <rules.h>
#include <string.h>
#include <vb2_api.h>
@@ -32,6 +33,39 @@ static int vb2_get_recovery_reason_shared_data(void)
return sd->recovery_reason;
}
+void vb2_save_recovery_reason_vbnv(void)
+{
+ if (!IS_ENABLED(CONFIG_VBOOT_SAVE_RECOVERY_REASON_ON_REBOOT))
+ return;
+
+ int reason = vb2_get_recovery_reason_shared_data();
+ if (!reason)
+ return;
+
+ set_recovery_mode_into_vbnv(reason);
+}
+
+static void vb2_clear_recovery_reason_vbnv(void *unused)
+{
+ if (!IS_ENABLED(CONFIG_VBOOT_SAVE_RECOVERY_REASON_ON_REBOOT))
+ return;
+
+ set_recovery_mode_into_vbnv(0);
+}
+
+/*
+ * Recovery reason stored in VBNV needs to be cleared before the state of VBNV
+ * is backed-up anywhere or jumping to the payload (whichever occurs
+ * first). Currently, vbnv_cmos.c backs up VBNV on POST_DEVICE. Thus, we need to
+ * make sure that the stored recovery reason is cleared off before that
+ * happens.
+ * IMPORTANT: Any reboot occurring after BS_DEV_INIT state will cause loss of
+ * recovery reason on reboot. Until now, we have seen reboots occuring on x86
+ * only in FSP stages which run before BS_DEV_INIT.
+ */
+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT,
+ vb2_clear_recovery_reason_vbnv, NULL);
+
/*
* Returns 0 for the stages where we know that cbmem does not come online.
* Even if this function returns 1 for romstage, depending upon the point in
diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_loader.c b/src/vendorcode/google/chromeos/vboot2/vboot_loader.c
index 7541518f13..b76d20bebe 100644
--- a/src/vendorcode/google/chromeos/vboot2/vboot_loader.c
+++ b/src/vendorcode/google/chromeos/vboot2/vboot_loader.c
@@ -91,6 +91,7 @@ static void vboot_prepare(void)
if (verification_should_run()) {
verstage_main();
car_set_var(vboot_executed, 1);
+ vb2_save_recovery_reason_vbnv();
} else if (verstage_should_load()) {
struct cbfsf file;
struct prog verstage =