Sridhar Siricilla has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/46819 )
Change subject: soc/intel/common: Move reset request into intel_fw_update ......................................................................
soc/intel/common: Move reset request into intel_fw_update
The patch implements below functionalities: 1. Move reset request from CSE FW Update 2. Implement intel_fw_sync(), which triggers UCODE and CSE Lite FW update and trigger global reset if one of the FW update requests reset.
This patch prevents triggering global reset having separate reset request in UCODE update or CSE Lite FW Update.
Signed-off-by: Sridhar Siricilla sridhar.siricilla@intel.com Change-Id: I50da4206de05e552de68af7fa0afaef2dac33004 --- A src/soc/intel/common/basecode/fw_update/fw_update.c M src/soc/intel/common/block/cse/cse_lite.c M src/soc/intel/common/block/include/intelblocks/cse.h 3 files changed, 105 insertions(+), 52 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/19/46819/1
diff --git a/src/soc/intel/common/basecode/fw_update/fw_update.c b/src/soc/intel/common/basecode/fw_update/fw_update.c new file mode 100644 index 0000000..45d2d968 --- /dev/null +++ b/src/soc/intel/common/basecode/fw_update/fw_update.c @@ -0,0 +1,63 @@ +#include <bootstate.h> +#include <console/console.h> +#include <halt.h> +#include <intelbasecode/ucode_update.h> +#include <reset.h> +#include <security/vboot/misc.h> +#include <security/vboot/vboot_common.h> +#include <soc/intel/common/reset.h> +#include <vb2_api.h> +#include <intelblocks/cse.h> + +__weak void cse_board_reset(void) +{ + /* Default weak implementation, does nothing. */ +} + +void trigger_global_reset() { + + cse_board_reset(); + + /* If board does not perform the reset, then perform global_reset */ + do_global_reset(); + + die("cse_lite: Failed to reset the system\n"); +} + +static uint8_t update_ucode(void) +{ + if (CONFIG(INTEL_TOP_SWAP_MULTI_FIT_UCODE_UPDATE)) { + uint8_t reset_req = 0; + if (update_ucode_and_topswap_state(&reset_req)) { + /* Update failed */ + if (CONFIG(VBOOT)) { + printk(BIOS_DEBUG, "ucode: Failed to update microcode\n"); + struct vb2_context *ctx = vboot_get_context(); + if (ctx == NULL) + die("ucode: Failed to trigger recovery mode\n"); + vb2api_fail(ctx, 0x36, 0x0); + vboot_save_data(ctx); + vboot_reboot(); + } + } + return reset_req; + } +} + +static void intel_fw_update(void *unused) +{ + if (update_ucode() || cse_fw_sync()) + trigger_global_reset(); +} + + +#if CONFIG(SOC_INTEL_TIGERLAKE) || CONFIG(SOC_INTEL_JASPERLAKE) + +/* + * This needs to happen after the MRC cache write to avoid a 2nd + * memory training sequence. + */ +BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, intel_fw_update, NULL); +#else +BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, intel_fw_update, NULL); +#endif diff --git a/src/soc/intel/common/block/cse/cse_lite.c b/src/soc/intel/common/block/cse/cse_lite.c index 77a8d5f..6006e13 100644 --- a/src/soc/intel/common/block/cse/cse_lite.c +++ b/src/soc/intel/common/block/cse/cse_lite.c @@ -414,43 +414,28 @@ return true; }
-__weak void cse_board_reset(void) -{ - /* Default weak implementation, does nothing. */ -} - -/* Set the CSE's next boot partition and issues system reset */ -static bool cse_set_and_boot_from_next_bp(enum boot_partition_id bp) -{ - if (!cse_set_next_boot_partition(bp)) - return false; - - /* Allow the board to perform a reset for CSE RO<->RW jump */ - cse_board_reset(); - - /* If board does not perform the reset, then perform global_reset */ - do_global_reset(); - - die("cse_lite: Failed to reset the system\n"); - - /* Control never reaches here */ - return false; -} - -static bool cse_boot_to_rw(const struct cse_bp_info *cse_bp_info) +static bool cse_set_next_bp_to_rw(const struct cse_bp_info *cse_bp_info, uint8_t *reset_req) { if (cse_get_current_bp(cse_bp_info) == RW) return true;
- return cse_set_and_boot_from_next_bp(RW); + if (!cse_set_next_boot_partition(RW)) + return false; + + *reset_req = 1; + return true; }
-static bool cse_boot_to_ro(const struct cse_bp_info *cse_bp_info) +static bool cse_set_next_bp_to_ro(const struct cse_bp_info *cse_bp_info, uint8_t *reset_req) { if (cse_get_current_bp(cse_bp_info) == RO) return true;
- return cse_set_and_boot_from_next_bp(RO); + if (!cse_set_next_boot_partition(RO)) + return false; + + *reset_req = 1; + return truel }
static bool cse_get_rw_rdev(struct region_device *rdev) @@ -701,7 +686,7 @@ * It returns true if RW partition doesn't indicate BP_STATUS_DATA_FAILURE * otherwise false if any operation fails. */ -static bool cse_fix_data_failure_err(const struct cse_bp_info *cse_bp_info) +static bool cse_fix_data_failure_err(const struct cse_bp_info *cse_bp_info, uint8_t *reset_req) { /* * If RW partition status indicates BP_STATUS_DATA_FAILURE, @@ -715,7 +700,7 @@ if (!cse_data_clear_request(cse_bp_info)) return false;
- return cse_boot_to_rw(cse_bp_info); + return cse_set_next_bp_to_rw(cse_bp_info, reset_req); }
static bool cse_erase_rw_region(const struct region_device *target_rdev) @@ -798,16 +783,19 @@ }
static bool cse_prep_for_rw_update(const struct cse_bp_info *cse_bp_info, - const struct cse_cbfs_rw_info *source_info) + const struct cse_cbfs_rw_info *source_info, uint8_t *reset_req) { /* * To set CSE's operation mode to HMRFPO mode: * 1. Ensure CSE to boot from RO(BP1) * 2. Send HMRFPO_ENABLE command to CSE */ - if (!cse_boot_to_ro(cse_bp_info)) + if (!cse_set_boot_to_ro(cse_bp_info, reset_req)) return false;
+ if (*reset_req) + return true; + if (cse_is_downgrade_instance(cse_bp_info, source_info) && !cse_data_clear_request(cse_bp_info)) { printk(BIOS_ERR, "cse_lite: CSE FW downgrade is aborted\n"); @@ -818,7 +806,8 @@ }
static enum csme_failure_reason cse_trigger_fw_update(const struct cse_bp_info *cse_bp_info, - const struct cse_cbfs_rw_info *source_info, struct region_device *target_rdev) + const struct cse_cbfs_rw_info *source_info, struct region_device *target_rdev, + uint8_t *reset_req) { struct region_device source_rdev;
@@ -836,7 +825,7 @@ } }
- if (!cse_prep_for_rw_update(cse_bp_info, source_info)) { + if (!cse_prep_for_rw_update(cse_bp_info, source_info, reset_req)) { rv = CSE_LITE_SKU_COMMUNICATION_ERROR; goto error_exit; } @@ -850,7 +839,7 @@ }
static uint8_t cse_fw_update(const struct cse_bp_info *cse_bp_info, - const struct region_device *source_info_rdev) + const struct region_device *source_info_rdev, uint8_t *reset_req) { struct region_device target_rdev;
@@ -869,7 +858,7 @@
if (cse_is_update_required(cse_bp_info, &source_info, &target_rdev)) { printk(BIOS_DEBUG, "cse_lite: CSE RW update is initiated\n"); - return cse_trigger_fw_update(cse_bp_info, &source_info, &target_rdev); + return cse_trigger_fw_update(cse_bp_info, &source_info, &target_rdev, reset_req); }
if (!cse_is_rw_bp_status_valid(cse_bp_info)) @@ -878,19 +867,19 @@ return 0; }
-void cse_fw_sync(void *unused) +uint8_t cse_fw_sync(void) { static struct get_bp_info_rsp cse_bp_info;
if (vboot_recovery_mode_enabled()) { printk(BIOS_DEBUG, "cse_lite: Skip switching to RW in the recovery path\n"); - return; + return 0; }
/* If CSE SKU type is not Lite, skip enabling CSE Lite SKU */ if (!cse_is_hfs3_fw_sku_lite()) { printk(BIOS_ERR, "cse_lite: Not a CSE Lite SKU\n"); - return; + return 0; }
if (!cse_get_bp_info(&cse_bp_info)) { @@ -898,9 +887,15 @@ cse_trigger_recovery(CSE_LITE_SKU_COMMUNICATION_ERROR); }
- if (!cse_fix_data_failure_err(&cse_bp_info.bp_info)) + uint8_t reset_req = 0; + + if (!cse_fix_data_failure_err(&cse_bp_info.bp_info, &reset_req)) cse_trigger_recovery(CSE_LITE_SKU_DATA_WIPE_ERROR);
+ if(reset_req) + return reset_req; + + /* * If CSE CBFS RW blob metadata is present in CBFS, then trigger CSE firmware update. * The driver triggers recovery if CSE CBFS RW metadata is present in the CBFS and CSE @@ -909,23 +904,17 @@ uint8_t rv; struct region_device source_info_rdev; if (cse_get_cbfs_rdev(&source_info_rdev)) { - rv = cse_fw_update(&cse_bp_info.bp_info, &source_info_rdev); + rv = cse_fw_update(&cse_bp_info.bp_info, &source_info_rdev, &reset_req); if (rv) cse_trigger_recovery(rv); }
- if (!cse_boot_to_rw(&cse_bp_info.bp_info)) { + if(reset_req) + return reset_req; + + if (!cse_set_next_bp_to_rw(&cse_bp_info.bp_info, &reset_req)) { printk(BIOS_ERR, "cse_lite: Failed to switch to RW\n"); cse_trigger_recovery(CSE_LITE_SKU_RW_SWITCH_ERROR); } + return reset_req; } - -#if CONFIG(SOC_INTEL_TIGERLAKE) || CONFIG(SOC_INTEL_JASPERLAKE) -/* - * This needs to happen after the MRC cache write to avoid a 2nd - * memory training sequence. - */ -BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, cse_fw_sync, NULL); -#else -BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, cse_fw_sync, NULL); -#endif diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h index f554933..0ac5d74 100644 --- a/src/soc/intel/common/block/include/intelblocks/cse.h +++ b/src/soc/intel/common/block/include/intelblocks/cse.h @@ -216,8 +216,9 @@ * boot from RW and triggers recovery mode if CSE fails to jump to RW. * In software triggered recovery mode, the function allows CSE to boot from whatever is * currently selected partition. + * Returns 1 if reset is required otherwise 0. */ -void cse_fw_sync(void *unused); +uint8_t cse_fw_sync(void);
/* Perform a board-specific reset sequence for CSE RO<->RW jump */ void cse_board_reset(void);