summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFurquan Shaikh <furquan@google.com>2021-10-07 00:08:59 -0700
committerFelix Held <felix-coreboot@felixheld.de>2021-10-15 18:15:14 +0000
commitd2da8704992a9db90f430e69635e7f10e57cb15c (patch)
tree8227086ae74cf1af43b58d77640bb5d099cbf773 /src
parenta0f8dc3bd55d4706606e14173bb9afaa97049287 (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')
-rw-r--r--src/soc/intel/common/block/cse/Kconfig14
-rw-r--r--src/soc/intel/common/block/cse/Makefile.inc59
-rw-r--r--src/soc/intel/common/block/cse/cse_lite.c56
-rw-r--r--src/soc/intel/common/block/include/intelblocks/cse.h10
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 */