diff --git a/src/soc/intel/common/block/cse/cse_lite.c b/src/soc/intel/common/block/cse/cse_lite.c index 140a56d06f..9ea6c78225 100644 --- a/src/soc/intel/common/block/cse/cse_lite.c +++ b/src/soc/intel/common/block/cse/cse_lite.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -420,6 +421,38 @@ static bool cse_is_bp_cmd_info_possible(void) return false; } +static struct get_bp_info_rsp *sync_cse_bp_info_to_cbmem(void) +{ + struct get_bp_info_rsp *cse_bp_info_in_cbmem = cbmem_find(CBMEM_ID_CSE_BP_INFO); + + if (cse_bp_info_in_cbmem != NULL) + return cse_bp_info_in_cbmem; + + cse_bp_info_in_cbmem = cbmem_add(CBMEM_ID_CSE_BP_INFO, + sizeof(struct get_bp_info_rsp)); + + if (!cse_bp_info_in_cbmem) { + printk(BIOS_ERR, "Unable to store Boot Parition Info in cbmem\n"); + return NULL; + } + + /* Copy the CSE Boot Partition Info command response to cbmem */ + memcpy(cse_bp_info_in_cbmem, &cse_bp_info_rsp, sizeof(struct get_bp_info_rsp)); + + return cse_bp_info_in_cbmem; +} + +static bool is_cse_bp_info_valid(struct get_bp_info_rsp *bp_info_rsp) +{ + /* + * In case the cse_bp_info_rsp header group ID, command is incorrect or is_resp is 0, + * then return false to indicate cse_bp_info is not valid. + */ + return (bp_info_rsp->hdr.group_id != MKHI_GROUP_ID_BUP_COMMON || + bp_info_rsp->hdr.command != MKHI_BUP_COMMON_GET_BOOT_PARTITION_INFO || + !bp_info_rsp->hdr.is_resp) ? false : true; +} + static enum cb_err cse_get_bp_info(void) { struct get_bp_info_req { @@ -433,6 +466,33 @@ static enum cb_err cse_get_bp_info(void) .reserved = {0}, }; + /* + * If SOC_INTEL_CSE_LITE_SYNC_IN_RAMSTAGE config is selected and memory has been + * initialized, check if there is cse bp info response stored in cbmem. Once the data + * is validated, copy it to the global cse_bp_info_rsp so that it can be used by other + * functions. In case, data is not available in cbmem or invalid, continue to send the + * GET_BOOT_PARTITION_INFO command, else return. + */ + if (CONFIG(SOC_INTEL_CSE_LITE_SYNC_IN_RAMSTAGE) && cbmem_online()) { + struct get_bp_info_rsp *cse_bp_info_in_cbmem = sync_cse_bp_info_to_cbmem(); + if (cse_bp_info_in_cbmem) { + if (is_cse_bp_info_valid(cse_bp_info_in_cbmem)) { + memcpy(&cse_bp_info_rsp, cse_bp_info_in_cbmem, + sizeof(struct get_bp_info_rsp)); + return CB_SUCCESS; + } + } + } else { + /* + * If SOC_INTEL_CSE_LITE_SYNC_IN_ROMSTAGE config is selected, check if the + * global cse bp info response stored in global cse_bp_info_rsp is valid. + * In case, it is not valid, continue to send the GET_BOOT_PARTITION_INFO + * command, else return. + */ + if (is_cse_bp_info_valid(&cse_bp_info_rsp)) + return CB_SUCCESS; + } + if (!cse_is_bp_cmd_info_possible()) { printk(BIOS_ERR, "cse_lite: CSE does not meet prerequisites\n"); return CB_ERR; @@ -453,9 +513,29 @@ static enum cb_err cse_get_bp_info(void) } cse_print_boot_partition_info(); - return CB_SUCCESS; } + +void cse_fill_bp_info(void) +{ + if (vboot_recovery_mode_enabled()) + return; + + if (cse_get_bp_info() != CB_SUCCESS) + cse_trigger_vboot_recovery(CSE_COMMUNICATION_ERROR); +} + +/* Function to copy PRERAM CSE BP info to pertinent CBMEM. */ +static void preram_cse_bp_info_sync_to_cbmem(int is_recovery) +{ + if (vboot_recovery_mode_enabled()) + return; + + sync_cse_bp_info_to_cbmem(); +} + +CBMEM_CREATION_HOOK(preram_cse_bp_info_sync_to_cbmem); + /* * It sends HECI command to notify CSE about its next boot partition. When coreboot wants * CSE to boot from certain partition (BP1 or BP2 ), then this command can be used. diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h index ae9fe941c6..0f7356854d 100644 --- a/src/soc/intel/common/block/include/intelblocks/cse.h +++ b/src/soc/intel/common/block/include/intelblocks/cse.h @@ -572,4 +572,7 @@ void cse_enable_ptt(bool state); */ enum cb_err cse_get_fw_feature_state(uint32_t *feature_state); +/* Fills the CSE Boot Partition Info response */ +void cse_fill_bp_info(void); + #endif // SOC_INTEL_COMMON_CSE_H