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>
This commit is contained in:
parent
a0f8dc3bd5
commit
d2da870499
|
@ -51,11 +51,17 @@ config SOC_INTEL_CSE_RW_CBFS_NAME
|
||||||
help
|
help
|
||||||
CBFS entry name for Intel CSE CBFS RW blob
|
CBFS entry name for Intel CSE CBFS RW blob
|
||||||
|
|
||||||
config SOC_INTEL_CSE_RW_METADATA_CBFS_NAME
|
config SOC_INTEL_CSE_RW_HASH_CBFS_NAME
|
||||||
string "CBFS name for CSE RW metadata file" if SOC_INTEL_CSE_RW_UPDATE
|
string "CBFS name for CSE RW hash file" if SOC_INTEL_CSE_RW_UPDATE
|
||||||
default "me_rw.metadata"
|
default "me_rw.hash"
|
||||||
help
|
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
|
config SOC_INTEL_CSE_RW_FILE
|
||||||
string "Intel CSE CBFS RW path and filename" if SOC_INTEL_CSE_RW_UPDATE
|
string "Intel CSE CBFS RW path and filename" if SOC_INTEL_CSE_RW_UPDATE
|
||||||
|
|
|
@ -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
|
ramstage-$(CONFIG_SOC_INTEL_CSE_SET_EOP) += cse_eop.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_SOC_INTEL_CSE_RW_UPDATE),y)
|
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))
|
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)), \
|
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))
|
$(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_B_FMAP_NAME))
|
||||||
cbfs-files-y += $(CSE_LITE_ME_RW)
|
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)-name := $(CSE_LITE_ME_RW)
|
||||||
$(CSE_LITE_ME_RW)-type := raw
|
$(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
|
$(obj)/cse_rw.version:
|
||||||
ifneq ($(CONFIG_SOC_INTEL_CSE_RW_VERSION),"")
|
@echo '$(call strip_quotes,$(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
|
|
||||||
|
|
||||||
# Compute the hash of the CSE RW binary and update the cse_rw_metadata structure
|
CSE_RW_VERSION = $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_VERSION_CBFS_NAME))
|
||||||
CSE_RW_PATH := $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_FILE))
|
regions-for-file-$(CSE_RW_VERSION) = FW_MAIN_A,FW_MAIN_B
|
||||||
HASH := $(shell openssl dgst -sha256 -hex $(CSE_RW_PATH) | cut -d " " -f2 | fold -w2 | paste -sd',' -)
|
cbfs-files-y += $(CSE_RW_VERSION)
|
||||||
CPPFLAGS_common += -DCSE_RW_SHA256=$(HASH)
|
$(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
|
||||||
|
|
||||||
# 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
|
endif
|
||||||
|
|
|
@ -565,29 +565,53 @@ enum cse_update_status {
|
||||||
CSE_UPDATE_METADATA_ERROR,
|
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,
|
static enum cse_update_status cse_check_update_status(const struct cse_bp_info *cse_bp_info,
|
||||||
struct region_device *target_rdev)
|
struct region_device *target_rdev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
struct fw_version cbfs_rw_version;
|
||||||
|
char *version_str, *ptr;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
if (!cse_is_rw_bp_sign_valid(target_rdev))
|
if (!cse_is_rw_bp_sign_valid(target_rdev))
|
||||||
return CSE_UPDATE_CORRUPTED;
|
return CSE_UPDATE_CORRUPTED;
|
||||||
|
|
||||||
if (cbfs_load(CONFIG_SOC_INTEL_CSE_RW_METADATA_CBFS_NAME, &source_metadata,
|
ptr = version_str = cbfs_map(CONFIG_SOC_INTEL_CSE_RW_VERSION_CBFS_NAME, &size);
|
||||||
sizeof(source_metadata)) != sizeof(source_metadata)) {
|
if (!version_str) {
|
||||||
printk(BIOS_ERR, "cse_lite: Failed to get CSE CBFS RW metadata\n");
|
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;
|
return CSE_UPDATE_METADATA_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "cse_lite: CSE CBFS RW version : %d.%d.%d.%d\n",
|
printk(BIOS_DEBUG, "cse_lite: CSE CBFS RW version : %d.%d.%d.%d\n",
|
||||||
source_metadata.version.major,
|
cbfs_rw_version.major,
|
||||||
source_metadata.version.minor,
|
cbfs_rw_version.minor,
|
||||||
source_metadata.version.hotfix,
|
cbfs_rw_version.hotfix,
|
||||||
source_metadata.version.build);
|
cbfs_rw_version.build);
|
||||||
|
|
||||||
ret = compare_cse_version(&source_metadata.version, cse_get_rw_version(cse_bp_info));
|
cbfs_unmap(version_str);
|
||||||
|
|
||||||
|
ret = compare_cse_version(&cbfs_rw_version, cse_get_rw_version(cse_bp_info));
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return CSE_UPDATE_NOT_REQUIRED;
|
return CSE_UPDATE_NOT_REQUIRED;
|
||||||
else if (ret < 0)
|
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;
|
struct region_device source_rdev;
|
||||||
enum csme_failure_reason rv;
|
enum csme_failure_reason rv;
|
||||||
|
uint8_t *cbfs_rw_hash;
|
||||||
|
|
||||||
if (!cse_get_source_rdev(&source_rdev))
|
if (!cse_get_source_rdev(&source_rdev))
|
||||||
return CSE_LITE_SKU_RW_BLOB_NOT_FOUND;
|
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;
|
return CSE_LITE_SKU_RW_BLOB_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cse_verify_cbfs_rw_sha256(source_metadata.sha256, cse_cbfs_rw,
|
cbfs_rw_hash = cbfs_map(CONFIG_SOC_INTEL_CSE_RW_HASH_CBFS_NAME, NULL);
|
||||||
region_device_sz(&source_rdev))) {
|
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;
|
rv = CSE_LITE_SKU_RW_BLOB_SHA256_MISMATCH;
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
@ -690,6 +723,7 @@ static enum csme_failure_reason cse_trigger_fw_update(const struct cse_bp_info *
|
||||||
target_rdev);
|
target_rdev);
|
||||||
|
|
||||||
error_exit:
|
error_exit:
|
||||||
|
cbfs_unmap(cbfs_rw_hash);
|
||||||
rdev_munmap(&source_rdev, cse_cbfs_rw);
|
rdev_munmap(&source_rdev, cse_cbfs_rw);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,16 +76,6 @@ struct fw_version {
|
||||||
uint16_t build;
|
uint16_t build;
|
||||||
} __packed;
|
} __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 */
|
/* CSE recovery sub-error codes */
|
||||||
enum csme_failure_reason {
|
enum csme_failure_reason {
|
||||||
/* No error */
|
/* No error */
|
||||||
|
|
Loading…
Reference in New Issue