diff options
author | Furquan Shaikh <furquan@google.com> | 2021-10-07 00:08:59 -0700 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2021-10-15 18:15:14 +0000 |
commit | d2da8704992a9db90f430e69635e7f10e57cb15c (patch) | |
tree | 8227086ae74cf1af43b58d77640bb5d099cbf773 /src/soc | |
parent | a0f8dc3bd55d4706606e14173bb9afaa97049287 (diff) |
soc/intel/common/cse: Split CSE metadata into two CBFS files
This change splits CSE metadata structure (added to CBFS) into two
separate CBFS files (me_rw.hash and me_rw.version). Since `struct
cse_rw_metadata` is now used, it is dropped completely.
This change is being made in order to prepare for the upcoming changes
to stitch CSE binary at build time. Since the binary might not be
available pre-built, it complicates the order of operations for the
addition of CSE metadata structure and declaring hash and version as
CPPFLAGS_common. Instead rules can be enabled for individual CBFS file
targets for hash and version that ensure proper ordering as well.
BUG=b:184892226
TEST=Ensured that update works correctly on brya by forcing version
mismatch. In case of version match, no update is triggered.
Signed-off-by: Furquan Shaikh <furquan@google.com>
Change-Id: I7c9bb165e6a64415affcd0b3331628092195fa0d
Reviewed-on: https://review.coreboot.org/c/coreboot/+/58158
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Diffstat (limited to 'src/soc')
-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 */ |