Sridhar Siricilla has uploaded this change for review.

View Change

soc/intel/common: Add downgrade support for CSE Firmware

Add downgrade support for CSE RW firmware.
When CSE FW is downgraded, CSE may get into data compatible issues.
To avoid the data compatible issues, coreboot sends DATA CLEAR HECI
command to CSE to clear CSE run time data on preventive basis during
adowngrade and when CSE indicate the data mismatch error through
GET_BOOT_PARTITION_INFO.

BUG=b:144894771
TEST=Verified on hatch

Signed-off-by: Sridhar Siricilla <sridhar.siricilla@intel.com
Change-Id: I0a3a3036e448e5a743398f6b27e8e62965dbff3c
---
M src/soc/intel/common/block/cse/custom_bp.c
M src/soc/intel/common/block/include/intelblocks/cse.h
2 files changed, 89 insertions(+), 6 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/61/40561/1
diff --git a/src/soc/intel/common/block/cse/custom_bp.c b/src/soc/intel/common/block/cse/custom_bp.c
index 9aea0ee..379eb03 100644
--- a/src/soc/intel/common/block/cse/custom_bp.c
+++ b/src/soc/intel/common/block/cse/custom_bp.c
@@ -80,6 +80,11 @@
*/
BP_STATUS_PARTITION_NOT_PRESENT = 2,

+ /*
+ * This value is returned when unexpected issues detected in CSE Data area
+ * and CSE TCB-SVN downgrade scenario.
+ */
+ BP_STATUS_DATA_MISMATCH_ERROR = 3,
};

/*
@@ -449,7 +454,45 @@
cse_bp->end_offset);
}

-static bool cse_prep_for_rw_update(struct cse_bp_info *cse_bp_info)
+static bool cse_data_clear_request(struct cse_bp_info *cse_bp_info)
+{
+ struct data_clr_request {
+ struct mkhi_hdr hdr;
+ uint8_t reserved[4];
+ } __packed;
+
+ struct data_clr_request data_clr_rq = {
+ .hdr.group_id = MKHI_GROUP_ID_BUP_COMMON,
+ .hdr.command = MKHI_BUP_COMMON_DATA_CLEAR,
+ .reserved = {0},
+ };
+
+ if (!cse_is_hfs1_cws_normal() || !cse_is_hfs1_com_soft_temp_disable() ||
+ cse_get_current_bp(cse_bp_info) != RO) {
+ printk(BIOS_ERR, "cse_bp: CSE doesnn't meet DATA CLEAR cmd prerequisites\n");
+ return false;
+ }
+
+ printk(BIOS_DEBUG, "cse_bp: Sending DATA CLEAR HECI command\n");
+
+ struct mkhi_hdr data_clr_rsp;
+ size_t data_clr_rsp_sz = sizeof(data_clr_rsp);
+
+ if (!heci_send_receive(&data_clr_rq, sizeof(data_clr_rq), &data_clr_rsp,
+ &data_clr_rsp_sz)) {
+ return false;
+ }
+
+ if (data_clr_rsp.result) {
+ printk(BIOS_ERR, "cse_bp: CSE DATA CLEAR command response failed: %d\n",
+ data_clr_rsp.result);
+ return false;
+ }
+
+ return true;
+}
+
+static bool cse_prep_for_rw_update(struct cse_bp_info *cse_bp_info, uint32_t fw_downgrade)
{
/*
* To set CSE's operation mode to HMRFPO mode:
@@ -459,6 +502,11 @@
if (!cse_boot_to_ro(cse_bp_info))
return false;

+ if (fw_downgrade) {
+ if (!cse_data_clear_request(cse_bp_info))
+ return false;
+ }
+
if (!cse_hmrfpo_enable())
return false;

@@ -514,9 +562,42 @@
return cse_cbfs_rw_ver->build - cse_rw_ver->build;
}

+/* Checks RW Data partition is valid or not */
+static bool cse_is_rw_dp_valid(struct cse_bp_info *cse_bp_info)
+{
+ struct cse_bp_entry *rw_bp;
+
+ rw_bp = cse_get_bp_entry(RW, cse_bp_info);
+ if (rw_bp->status == BP_STATUS_DATA_MISMATCH_ERROR) {
+ printk(BIOS_ERR, "cse_bp: RW data partition is not valid\n");
+ return false;
+ }
+ return true;
+}
+
+static bool cse_is_fw_downgrade(struct cse_bp_info *cse_bp_info, void *cse_cbfs_rw_n_ver)
+{
+ return cse_check_version_mismatch(cse_bp_info, cse_cbfs_rw_n_ver) < 0;
+}
+
+/* Issues DATA_CLEAR HECI command and reset if RW boot partition indicates DATA_ERROR */
+static bool cse_fix_data_mismatch_err(struct cse_bp_info *cse_bp_info)
+{
+ if (cse_is_rw_dp_valid(cse_bp_info))
+ return true;
+
+ if (!cse_data_clear_request(cse_bp_info))
+ return false;
+
+ /* no return is exepected */
+ cse_boot_to_rw(cse_bp_info, 1);
+
+ /* Control never reaches here */
+ return false;
+}
+
static bool cse_erase_rw_region(struct region_device *target_rdev)
{
-
if (rdev_eraseat(target_rdev, 0, region_device_sz(target_rdev)) < 0) {
printk(BIOS_ERR, "cse_bp: CSE RW partition could not be erased\n");
return false;
@@ -589,8 +670,9 @@
static bool cse_write_to_rw(struct cse_bp_info *cse_bp_info, struct region_device *target_rdev,
void *cse_cbfs_rw_n_ver, size_t cse_cbfs_rw_n_ver_sz)
{
+ uint32_t fw_downgrade = cse_is_fw_downgrade(cse_bp_info, cse_cbfs_rw_n_ver);

- if (!cse_prep_for_rw_update(cse_bp_info))
+ if (!cse_prep_for_rw_update(cse_bp_info, fw_downgrade))
return false;

if (!cse_erase_rw_region(target_rdev))
@@ -638,8 +720,6 @@
return false;
}

- rdev_munmap(source_rw_n_ver_rdev, cse_cbfs_rw_n_ver);
-
/* Global Reset is required as CSE firmware update is successful */
*rst_req = 1;
return true;
@@ -674,6 +754,9 @@
return;
}

+ if (!cse_fix_data_mismatch_err(&cse_bp_info.bp_info))
+ goto failed;
+
struct region_device target_rdev;
struct region_device source_rw_n_ver_rdev;

diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h
index 6b91a4d..2367b68 100644
--- a/src/soc/intel/common/block/include/intelblocks/cse.h
+++ b/src/soc/intel/common/block/include/intelblocks/cse.h
@@ -41,7 +41,7 @@
/* Boot partition info and set boot partition info command ids */
#define MKHI_BUP_COMMON_GET_BOOT_PARTITION_INFO 0x1c
#define MKHI_BUP_COMMON_SET_BOOT_PARTITION_INFO 0x1d
-
+#define MKHI_BUP_COMMON_DATA_CLEAR 0x20
/* ME Current Working States */
#define ME_HFS1_CWS_NORMAL 0x5


To view, visit change 40561. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I0a3a3036e448e5a743398f6b27e8e62965dbff3c
Gerrit-Change-Number: 40561
Gerrit-PatchSet: 1
Gerrit-Owner: Sridhar Siricilla <sridhar.siricilla@intel.com>
Gerrit-Reviewer: Patrick Rudolph <siro@das-labor.org>
Gerrit-MessageType: newchange