diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/soc/intel/common/block/cse/Kconfig | 14 | ||||
-rw-r--r-- | src/soc/intel/common/block/cse/Makefile.inc | 59 | ||||
-rw-r--r-- | src/soc/intel/common/block/cse/cse_lite.c | 56 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/cse.h | 10 |
4 files changed, 86 insertions, 53 deletions
diff --git a/src/soc/intel/common/block/cse/Kconfig b/src/soc/intel/common/block/cse/Kconfig index 94f8cd5ebc..e06895080e 100644 --- a/src/soc/intel/common/block/cse/Kconfig +++ b/src/soc/intel/common/block/cse/Kconfig @@ -51,11 +51,17 @@ config SOC_INTEL_CSE_RW_CBFS_NAME help CBFS entry name for Intel CSE CBFS RW blob -config SOC_INTEL_CSE_RW_METADATA_CBFS_NAME - string "CBFS name for CSE RW metadata file" if SOC_INTEL_CSE_RW_UPDATE - default "me_rw.metadata" +config SOC_INTEL_CSE_RW_HASH_CBFS_NAME + string "CBFS name for CSE RW hash file" if SOC_INTEL_CSE_RW_UPDATE + default "me_rw.hash" help - CBFS name for Intel CSE CBFS RW metadata file + CBFS name for Intel CSE CBFS RW hash file + +config SOC_INTEL_CSE_RW_VERSION_CBFS_NAME + string "CBFS name for CSE RW version file" if SOC_INTEL_CSE_RW_UPDATE + default "me_rw.version" + help + CBFS name for Intel CSE CBFS RW version file config SOC_INTEL_CSE_RW_FILE string "Intel CSE CBFS RW path and filename" if SOC_INTEL_CSE_RW_UPDATE diff --git a/src/soc/intel/common/block/cse/Makefile.inc b/src/soc/intel/common/block/cse/Makefile.inc index e21efc6144..9b50704a57 100644 --- a/src/soc/intel/common/block/cse/Makefile.inc +++ b/src/soc/intel/common/block/cse/Makefile.inc @@ -7,40 +7,43 @@ smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_HECI_DISABLE_IN_SMM) += disable_heci.c ramstage-$(CONFIG_SOC_INTEL_CSE_SET_EOP) += cse_eop.c ifeq ($(CONFIG_SOC_INTEL_CSE_RW_UPDATE),y) -ifneq ($(CONFIG_SOC_INTEL_CSE_RW_FILE),"") + +ifeq ($(CONFIG_SOC_INTEL_CSE_RW_FILE),"") +$(error "CSE RW file path is missing and need to be set by mainboard config") +endif + +ifeq ($(CONFIG_SOC_INTEL_CSE_RW_VERSION),"") +$(error "CSE RW version is missing and need to be set by mainboard config") +endif + +CSE_RW_FILE=$(call strip_quotes,$(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) = $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_A_FMAP_NAME)), \ $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_B_FMAP_NAME)) 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)-file := $(CSE_RW_FILE) $(CSE_LITE_ME_RW)-name := $(CSE_LITE_ME_RW) $(CSE_LITE_ME_RW)-type := raw -else -$(error "CSE RW file path is missing and need to be set by mainboard config") -endif -# Extract the CSE RW firmware version and update the cse_rw_metadata structure -ifneq ($(CONFIG_SOC_INTEL_CSE_RW_VERSION),"") -CSE_RW_VERSION:=$(subst ., ,$(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_VERSION))) -MAJOR := $(word 1, $(CSE_RW_VERSION)) -MINOR := $(word 2, $(CSE_RW_VERSION)) -HOTFIX := $(word 3, $(CSE_RW_VERSION)) -BUILD := $(word 4, $(CSE_RW_VERSION)) -CPPFLAGS_common += -DCSE_RW_MAJOR=$(MAJOR) -DCSE_RW_MINOR=$(MINOR) -DCSE_RW_HOTFIX=$(HOTFIX) -DCSE_RW_BUILD=$(BUILD) -else -$(error "CSE RW version is missing and need to be set by mainboard config") -endif +$(obj)/cse_rw.version: + @echo '$(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_VERSION))' > $@ + +CSE_RW_VERSION = $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_VERSION_CBFS_NAME)) +regions-for-file-$(CSE_RW_VERSION) = FW_MAIN_A,FW_MAIN_B +cbfs-files-y += $(CSE_RW_VERSION) +$(CSE_RW_VERSION)-file := $(obj)/cse_rw.version +$(CSE_RW_VERSION)-name := $(CSE_RW_VERSION) +$(CSE_RW_VERSION)-type := raw + +$(obj)/cse_rw.hash: $(CSE_RW_FILE) + openssl dgst -sha256 -binary $< > $@ + +CSE_RW_HASH = $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_HASH_CBFS_NAME)) +regions-for-file-$(CSE_RW_HASH) = FW_MAIN_A,FW_MAIN_B +cbfs-files-y += $(CSE_RW_HASH) +$(CSE_RW_HASH)-file := $(obj)/cse_rw.hash +$(CSE_RW_HASH)-name := $(CSE_RW_HASH) +$(CSE_RW_HASH)-type := raw -# Compute the hash of the CSE RW binary and update the cse_rw_metadata structure -CSE_RW_PATH := $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_FILE)) -HASH := $(shell openssl dgst -sha256 -hex $(CSE_RW_PATH) | cut -d " " -f2 | fold -w2 | paste -sd',' -) -CPPFLAGS_common += -DCSE_RW_SHA256=$(HASH) - -# Add the CSE RW metadata file to FW_MAIN_A/B -CSE_RW_METADATA = $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_METADATA_CBFS_NAME)) -regions-for-file-$(CSE_RW_METADATA) = FW_MAIN_A,FW_MAIN_B -cbfs-files-y += $(CSE_RW_METADATA) -$(CSE_RW_METADATA)-file := cse_rw_metadata.c:struct -$(CSE_RW_METADATA)-name := $(CSE_RW_METADATA) -$(CSE_RW_METADATA)-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 b381c48103..281d381736 100644 --- a/src/soc/intel/common/block/cse/cse_lite.c +++ b/src/soc/intel/common/block/cse/cse_lite.c @@ -565,29 +565,53 @@ enum cse_update_status { CSE_UPDATE_METADATA_ERROR, }; -static struct cse_rw_metadata source_metadata; +static bool read_ver_field(const char *start, char **curr, size_t size, uint16_t *ver_field) +{ + if ((*curr - start) >= size) { + printk(BIOS_ERR, "cse_lite: Version string read overflow!\n"); + return false; + } + + *ver_field = skip_atoi(curr); + (*curr)++; + return true; +} static enum cse_update_status cse_check_update_status(const struct cse_bp_info *cse_bp_info, struct region_device *target_rdev) { int ret; + struct fw_version cbfs_rw_version; + char *version_str, *ptr; + size_t size; if (!cse_is_rw_bp_sign_valid(target_rdev)) return CSE_UPDATE_CORRUPTED; - if (cbfs_load(CONFIG_SOC_INTEL_CSE_RW_METADATA_CBFS_NAME, &source_metadata, - sizeof(source_metadata)) != sizeof(source_metadata)) { - printk(BIOS_ERR, "cse_lite: Failed to get CSE CBFS RW metadata\n"); + ptr = version_str = cbfs_map(CONFIG_SOC_INTEL_CSE_RW_VERSION_CBFS_NAME, &size); + if (!version_str) { + printk(BIOS_ERR, "cse_lite: Failed to get %s\n", + CONFIG_SOC_INTEL_CSE_RW_VERSION_CBFS_NAME); + return CSE_UPDATE_METADATA_ERROR; + } + + if (!read_ver_field(version_str, &ptr, size, &cbfs_rw_version.major) || + !read_ver_field(version_str, &ptr, size, &cbfs_rw_version.minor) || + !read_ver_field(version_str, &ptr, size, &cbfs_rw_version.hotfix) || + !read_ver_field(version_str, &ptr, size, &cbfs_rw_version.build)) { + cbfs_unmap(version_str); return CSE_UPDATE_METADATA_ERROR; } printk(BIOS_DEBUG, "cse_lite: CSE CBFS RW version : %d.%d.%d.%d\n", - source_metadata.version.major, - source_metadata.version.minor, - source_metadata.version.hotfix, - source_metadata.version.build); + cbfs_rw_version.major, + cbfs_rw_version.minor, + cbfs_rw_version.hotfix, + cbfs_rw_version.build); + + cbfs_unmap(version_str); - ret = compare_cse_version(&source_metadata.version, cse_get_rw_version(cse_bp_info)); + ret = compare_cse_version(&cbfs_rw_version, cse_get_rw_version(cse_bp_info)); if (ret == 0) return CSE_UPDATE_NOT_REQUIRED; else if (ret < 0) @@ -664,6 +688,7 @@ static enum csme_failure_reason cse_trigger_fw_update(const struct cse_bp_info * { struct region_device source_rdev; enum csme_failure_reason rv; + uint8_t *cbfs_rw_hash; if (!cse_get_source_rdev(&source_rdev)) return CSE_LITE_SKU_RW_BLOB_NOT_FOUND; @@ -675,8 +700,16 @@ static enum csme_failure_reason cse_trigger_fw_update(const struct cse_bp_info * return CSE_LITE_SKU_RW_BLOB_NOT_FOUND; } - if (!cse_verify_cbfs_rw_sha256(source_metadata.sha256, cse_cbfs_rw, - region_device_sz(&source_rdev))) { + cbfs_rw_hash = cbfs_map(CONFIG_SOC_INTEL_CSE_RW_HASH_CBFS_NAME, NULL); + if (!cbfs_rw_hash) { + printk(BIOS_ERR, "cse_lite: Failed to get %s\n", + CONFIG_SOC_INTEL_CSE_RW_HASH_CBFS_NAME); + rv = CSE_LITE_SKU_RW_METADATA_NOT_FOUND; + goto error_exit; + } + + if (!cse_verify_cbfs_rw_sha256(cbfs_rw_hash, cse_cbfs_rw, + region_device_sz(&source_rdev))) { rv = CSE_LITE_SKU_RW_BLOB_SHA256_MISMATCH; goto error_exit; } @@ -690,6 +723,7 @@ static enum csme_failure_reason cse_trigger_fw_update(const struct cse_bp_info * target_rdev); error_exit: + cbfs_unmap(cbfs_rw_hash); rdev_munmap(&source_rdev, cse_cbfs_rw); return rv; } diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h index f162d485fd..80e28d5e75 100644 --- a/src/soc/intel/common/block/include/intelblocks/cse.h +++ b/src/soc/intel/common/block/include/intelblocks/cse.h @@ -76,16 +76,6 @@ struct fw_version { uint16_t build; } __packed; -/* - * CSE RW metadata structure - * fw_version - CSE RW firmware version - * sha256 - Hash of the CSE RW binary. - */ -struct cse_rw_metadata { - struct fw_version version; - uint8_t sha256[VB2_SHA256_DIGEST_SIZE]; -}; - /* CSE recovery sub-error codes */ enum csme_failure_reason { /* No error */ |