Sridhar Siricilla has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/46552 )
Change subject: soc/intel/common: Add support for CSE Lite driver to handle CSE RW and metadata ......................................................................
soc/intel/common: Add support for CSE Lite driver to handle CSE RW and metadata
The patch modifies CSE Lite driver to support to have separate CBFS file for metadata of RW blobs. So, the driver expects separate CBFS files for CSE RW and it's metadata. Also, the driver initiates CSE Firmware update path if it finds the metadata's CBFS file. The change gives flexibility to modify RW blob's FMAP locations while maintaining uniform or little modified CSE Lite driver. Currently, CSE RW blob and it's metadata were unified into one RW blob.
TEST=Verified on hatch. BRANCH=Puff
Signed-off-by: Sridhar Siricilla sridhar.siricilla@intel.com Change-Id: I316344d23987d9907b64efafbe61f36ae7ade337 --- M src/soc/intel/common/block/cse/Kconfig M src/soc/intel/common/block/cse/Makefile.inc M src/soc/intel/common/block/cse/cse_lite.c 3 files changed, 128 insertions(+), 71 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/52/46552/1
diff --git a/src/soc/intel/common/block/cse/Kconfig b/src/soc/intel/common/block/cse/Kconfig index 1cb7d35..6512e3d 100644 --- a/src/soc/intel/common/block/cse/Kconfig +++ b/src/soc/intel/common/block/cse/Kconfig @@ -37,3 +37,15 @@ default "" help Intel CSE CBFS RW blob path and file name + +config SOC_INTEL_CSE_RW_METADATA_CBFS_NAME + string "CBFS entry name for CSE RW blob" + default "me_rw.metadata" + help + CBFS entry name for Intel CSE CBFS RW blob + +config SOC_INTEL_CSE_RW_METADATA_FILE + string "Intel CSE CBFS RW path and filename" + default "" + help + Intel CSE CBFS RW blob path and file name diff --git a/src/soc/intel/common/block/cse/Makefile.inc b/src/soc/intel/common/block/cse/Makefile.inc index 11cc3c2..59ba0cb 100644 --- a/src/soc/intel/common/block/cse/Makefile.inc +++ b/src/soc/intel/common/block/cse/Makefile.inc @@ -4,11 +4,20 @@ ramstage-$(CONFIG_SOC_INTEL_CSE_LITE_SKU) += cse_lite.c smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_HECI_DISABLE_IN_SMM) += disable_heci.c
+ifneq ($(CONFIG_SOC_INTEL_CSE_RW_METADATA_FILE),"") +CSE_LITE_RW_METADATA = $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_METADATA_CBFS_NAME)) +regions-for-file-$(CSE_LITE_RW_METADATA) = FW_MAIN_A,FW_MAIN_B +cbfs-files-y += $(CSE_LITE_RW_METADATA) +$(CSE_LITE_RW_METADATA)-file := $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_METADATA_FILE)) +$(CSE_LITE_RW_METADATA)-name := $(CSE_LITE_RW_METADATA) +$(CSE_LITE_RW_METADATA)-type := raw +endif + ifneq ($(CONFIG_SOC_INTEL_CSE_RW_FILE),"") -CSE_LITE_ME_RW = $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_CBFS_NAME)) -regions-for-file-$(CSE_LITE_ME_RW) = FW_MAIN_A,FW_MAIN_B -cbfs-files-y += $(CSE_LITE_ME_RW) -$(CSE_LITE_ME_RW)-file := $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_FILE)) -$(CSE_LITE_ME_RW)-name := $(CSE_LITE_ME_RW) -$(CSE_LITE_ME_RW)-type := raw +CSE_LITE_RW = $(call strip_quotes, $(CONFIG_SOC_INTEL_CSE_RW_CBFS_NAME)) +regions-for-file-$(CSE_LITE_RW) = FW_MAIN_A, FW_MAIN_B +cbfs-files-y += $(CSE_LITE_RW) +$(CSE_LITE_RW)-file := $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_FILE)) +$(CSE_LITE_RW)-name := $(CSE_LITE_RW) +$(CSE_LITE_RW)-type := raw endif diff --git a/src/soc/intel/common/block/cse/cse_lite.c b/src/soc/intel/common/block/cse/cse_lite.c index c9e4e1f..7218a92 100644 --- a/src/soc/intel/common/block/cse/cse_lite.c +++ b/src/soc/intel/common/block/cse/cse_lite.c @@ -12,9 +12,6 @@ #include <vb2_api.h> #include <soc/intel/common/reset.h>
-/* CSE RW version size reserved in the CSE CBFS RW binary */ -#define CSE_RW_VERSION_SZ 16 - /* Converts bp index to boot partition string */ #define GET_BP_STR(bp_index) (bp_index ? "RW" : "RO")
@@ -45,6 +42,9 @@
/* CSE recovery sub-error codes */ enum csme_failure_reason { + + /* No error */ + CSE_LITE_SKU_NO_ERROR = 0, /* Unspecified error */ CSE_LITE_SKU_UNSPECIFIED = 1,
@@ -64,7 +64,10 @@ CSE_LITE_SKU_COMMUNICATION_ERROR = 6,
/* Fails to wipe CSE runtime data */ - CSE_LITE_SKU_DATA_WIPE_ERROR = 7 + CSE_LITE_SKU_DATA_WIPE_ERROR = 7, + + /* CSE RW is not found */ + CSE_LITE_SKU_RW_BLOB_NOT_FOUND = 8, };
/* @@ -157,6 +160,13 @@ struct cse_bp_info bp_info; } __packed;
+/* CSE CBFS RW metadata */ +struct cse_cbfs_rw_info { + /* CSE CBFS RW version */ + struct fw_version fw_ver; + uint8_t reserved[8]; +}; + static void cse_log_status_registers(void) { printk(BIOS_DEBUG, "cse_lite: CSE status registers: HFSTS1: 0x%x, HFSTS2: 0x%x " @@ -423,7 +433,7 @@ { struct cbfsf file_desc;
- if (cbfs_boot_locate(&file_desc, CONFIG_SOC_INTEL_CSE_RW_CBFS_NAME, NULL) < 0) + if (cbfs_boot_locate(&file_desc, CONFIG_SOC_INTEL_CSE_RW_METADATA_CBFS_NAME, NULL) < 0) return false;
cbfs_file_data(source_rdev, &file_desc); @@ -503,15 +513,33 @@ return true; }
-static bool cse_get_cbfs_rw_version(const struct region_device *source_rdev, - void *cse_cbfs_rw_ver) +static bool cse_get_cbfs_rw(struct region_device *rdev) +{ + struct cbfsf file_desc; + + if (cbfs_boot_locate(&file_desc, CONFIG_SOC_INTEL_CSE_RW_CBFS_NAME, NULL) < 0) + return false; + + cbfs_file_data(rdev, &file_desc); + + return true; +} + +static bool cse_get_cbfs_rw_metadata(const struct region_device *source_info_rdev, + struct cse_cbfs_rw_info *source_info) {
- if (rdev_readat(source_rdev, (void *) cse_cbfs_rw_ver, 0, sizeof(struct fw_version)) - != sizeof(struct fw_version)) { - printk(BIOS_ERR, "cse_lite: Failed to read CSE CBFW RW version\n"); + if (rdev_readat(source_info_rdev, (void *) source_info, 0, + sizeof(struct cse_cbfs_rw_info)) != sizeof(struct cse_cbfs_rw_info)) { + printk(BIOS_ERR, "cse_lite: Failed to read CSE CBFS RW metadata\n"); return false; } + + printk(BIOS_SPEW, "cse_lite: CSE CBFS RW version : %d.%d.%d.%d\n", + source_info->fw_ver.major, + source_info->fw_ver.minor, + source_info->fw_ver.hotfix, + source_info->fw_ver.build); return true; }
@@ -522,30 +550,26 @@ * If ver_cmp_status > 0, coreboot upgrades CSE RW region */ static int cse_check_version_mismatch(const struct cse_bp_info *cse_bp_info, - const struct region_device *source_rdev) + const struct cse_cbfs_rw_info *source_info) { - struct fw_version cse_cbfs_rw_ver; const struct fw_version *cse_rw_ver;
- if (!cse_get_cbfs_rw_version(source_rdev, &cse_cbfs_rw_ver)) - return false; - printk(BIOS_DEBUG, "cse_lite: CSE CBFS RW version : %d.%d.%d.%d\n", - cse_cbfs_rw_ver.major, - cse_cbfs_rw_ver.minor, - cse_cbfs_rw_ver.hotfix, - cse_cbfs_rw_ver.build); + source_info->fw_ver.major, + source_info->fw_ver.minor, + source_info->fw_ver.hotfix, + source_info->fw_ver.build);
cse_rw_ver = cse_get_rw_version(cse_bp_info);
- if (cse_cbfs_rw_ver.major != cse_rw_ver->major) - return cse_cbfs_rw_ver.major - cse_rw_ver->major; - else if (cse_cbfs_rw_ver.minor != cse_rw_ver->minor) - return cse_cbfs_rw_ver.minor - cse_rw_ver->minor; - else if (cse_cbfs_rw_ver.hotfix != cse_rw_ver->hotfix) - return cse_cbfs_rw_ver.hotfix - cse_rw_ver->hotfix; + if (source_info->fw_ver.major != cse_rw_ver->major) + return source_info->fw_ver.major - cse_rw_ver->major; + else if (source_info->fw_ver.minor != cse_rw_ver->minor) + return source_info->fw_ver.minor - cse_rw_ver->minor; + else if (source_info->fw_ver.hotfix != cse_rw_ver->hotfix) + return source_info->fw_ver.hotfix - cse_rw_ver->hotfix; else - return cse_cbfs_rw_ver.build - cse_rw_ver->build; + return source_info->fw_ver.build - cse_rw_ver->build; }
/* Check if CSE RW data partition is valid or not */ @@ -587,8 +611,8 @@ return true; }
-static bool cse_copy_rw(const struct region_device *target_rdev, const void *buf, size_t offset, - size_t size) +static bool cse_copy_rw(const struct region_device *target_rdev, const void *buf, + size_t offset, size_t size) { if (rdev_writeat(target_rdev, buf, offset, size) < 0) { printk(BIOS_ERR, "cse_lite: Failed to update CSE firmware\n"); @@ -599,36 +623,35 @@ }
static bool cse_is_rw_version_latest(const struct cse_bp_info *cse_bp_info, - const struct region_device *source_rdev) + const struct cse_cbfs_rw_info *source_info) { - return !cse_check_version_mismatch(cse_bp_info, source_rdev); + return !cse_check_version_mismatch(cse_bp_info, source_info); }
static bool cse_is_downgrade_instance(const struct cse_bp_info *cse_bp_info, - const struct region_device *source_rdev) + const struct cse_cbfs_rw_info *source_info) { - return cse_check_version_mismatch(cse_bp_info, source_rdev) < 0; + return cse_check_version_mismatch(cse_bp_info, source_info) < 0; }
static bool cse_is_update_required(const struct cse_bp_info *cse_bp_info, - const struct region_device *source_rdev, struct region_device *target_rdev) + const struct cse_cbfs_rw_info *source_info, struct region_device *target_rdev) { return (!cse_is_rw_bp_sign_valid(target_rdev) || - !cse_is_rw_version_latest(cse_bp_info, source_rdev)); + !cse_is_rw_version_latest(cse_bp_info, source_info)); }
static bool cse_write_rw_region(const struct region_device *target_rdev, const struct region_device *source_rdev) { - void *cse_cbfs_rw = rdev_mmap(source_rdev, CSE_RW_VERSION_SZ, - region_device_sz(source_rdev) - CSE_RW_VERSION_SZ); + + void *cse_cbfs_rw = rdev_mmap(source_rdev, 0, region_device_sz(source_rdev));
/* Points to CSE CBFS RW image after boot partition signature */ uint8_t *cse_cbfs_rw_wo_sign = (uint8_t *)cse_cbfs_rw + CSE_RW_SIGN_SIZE;
/* Size of CSE CBFS RW image without boot partition signature */ - uint32_t cse_cbfs_rw_wo_sign_sz = region_device_sz(source_rdev) - - (CSE_RW_VERSION_SZ + CSE_RW_SIGN_SIZE); + uint32_t cse_cbfs_rw_wo_sign_sz = region_device_sz(source_rdev) - CSE_RW_SIGN_SIZE;
/* Update except CSE RW signature */ if (!cse_copy_rw(target_rdev, cse_cbfs_rw_wo_sign, CSE_RW_SIGN_SIZE, @@ -639,29 +662,32 @@ if (!cse_copy_rw(target_rdev, (void *)cse_cbfs_rw, 0, CSE_RW_SIGN_SIZE)) goto exit_rw_update;
- rdev_munmap(source_rdev, cse_cbfs_rw_wo_sign); - return true; + printk(BIOS_INFO, "cse_lite: CSE RW Update Successful\n"); + rdev_munmap(source_rdev, cse_cbfs_rw); + return CSE_LITE_SKU_NO_ERROR;
exit_rw_update: - rdev_munmap(source_rdev, cse_cbfs_rw_wo_sign); - return false; + rdev_munmap(source_rdev, cse_cbfs_rw); + return CSE_LITE_SKU_FW_UPDATE_ERROR; }
static bool cse_update_rw(const struct cse_bp_info *cse_bp_info, - const struct region_device *source_rdev, struct region_device *target_rdev) + struct region_device *target_rdev) { + + struct region_device source_rdev; + + if (!cse_get_cbfs_rw(&source_rdev)) + return CSE_LITE_SKU_RW_BLOB_NOT_FOUND; + if (!cse_erase_rw_region(target_rdev)) - return false; + return CSE_LITE_SKU_FW_UPDATE_ERROR;
- if (!cse_write_rw_region(target_rdev, source_rdev)) - return false; - - printk(BIOS_INFO, "cse_lite: CSE RW Update Successful\n"); - return true; + return cse_write_rw_region(target_rdev, &source_rdev); }
static bool cse_prep_for_rw_update(const struct cse_bp_info *cse_bp_info, - const struct region_device *source_rdev) + const struct cse_cbfs_rw_info *source_info) { /* * To set CSE's operation mode to HMRFPO mode: @@ -671,7 +697,7 @@ if (!cse_boot_to_ro(cse_bp_info)) return false;
- if (cse_is_downgrade_instance(cse_bp_info, source_rdev) && + 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"); return false; @@ -680,20 +706,18 @@ return cse_hmrfpo_enable(); }
-static uint8_t cse_trigger_fw_update(const struct cse_bp_info *cse_bp_info, - const struct region_device *source_rdev, struct region_device *target_rdev) +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) { - if (!cse_prep_for_rw_update(cse_bp_info, source_rdev)) + + if (!cse_prep_for_rw_update(cse_bp_info, source_info)) return CSE_LITE_SKU_COMMUNICATION_ERROR;
- if (!cse_update_rw(cse_bp_info, source_rdev, target_rdev)) - return CSE_LITE_SKU_FW_UPDATE_ERROR; - - return 0; + return cse_update_rw(cse_bp_info, target_rdev); }
static uint8_t cse_fw_update(const struct cse_bp_info *cse_bp_info, - const struct region_device *source_rdev) + const struct region_device *source_info_rdev) { struct region_device target_rdev;
@@ -702,9 +726,17 @@ return CSE_LITE_SKU_RW_ACCESS_ERROR; }
- if (cse_is_update_required(cse_bp_info, source_rdev, &target_rdev)) { + struct cse_cbfs_rw_info source_info; + + /* Read CSE CBFS RW metadata */ + if (!cse_get_cbfs_rw_metadata(source_info_rdev, &source_info)) { + printk(BIOS_ERR, "cse_lite: Failed to get CSE RW blob metadata\n"); + return CSE_LITE_SKU_UNSPECIFIED; + } + + 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_rdev, &target_rdev); + return cse_trigger_fw_update(cse_bp_info, &source_info, &target_rdev); }
if (!cse_is_rw_bp_status_valid(cse_bp_info)) @@ -736,11 +768,15 @@ if (!cse_fix_data_failure_err(&cse_bp_info.bp_info)) cse_trigger_recovery(CSE_LITE_SKU_DATA_WIPE_ERROR);
- /* If RW blob is present in CBFS, then trigger CSE firmware update */ + /* + * 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 + * CBFS RW blob is not available. + */ uint8_t rv; - struct region_device source_rdev; - if (cse_get_cbfs_rdev(&source_rdev)) { - rv = cse_fw_update(&cse_bp_info.bp_info, &source_rdev); + 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); if (rv) cse_trigger_recovery(rv); }