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 +#include #include #include #include @@ -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 =