Patrick Georgi submitted this change.

View Change

Approvals: build bot (Jenkins): Verified V Sowmya: Looks good to me, approved Tim Wawrzynczak: Looks good to me, but someone else must approve Jamie Ryu: Looks good to me, but someone else must approve
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 compatibility issues.
To avoid such issues, coreboot sends DATA CLEAR HECI command to CSE to
clear CSE run time data on proactive basis during a downgrade and
when CSE indicates a 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
Reviewed-on: https://review.coreboot.org/c/coreboot/+/40561
Reviewed-by: V Sowmya <v.sowmya@intel.com>
Reviewed-by: Jamie Ryu <jamie.m.ryu@intel.com>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
---
M src/soc/intel/common/block/cse/cse_lite.c
M src/soc/intel/common/block/include/intelblocks/cse.h
2 files changed, 92 insertions(+), 3 deletions(-)

diff --git a/src/soc/intel/common/block/cse/cse_lite.c b/src/soc/intel/common/block/cse/cse_lite.c
index a8948be..edb08da 100644
--- a/src/soc/intel/common/block/cse/cse_lite.c
+++ b/src/soc/intel/common/block/cse/cse_lite.c
@@ -84,6 +84,11 @@
/* This value is returned when a partition is not present per initial image layout */
BP_STATUS_PARTITION_NOT_PRESENT = 2,

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

/*
@@ -459,6 +464,44 @@
return true;
}

+static bool cse_data_clear_request(const 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_lite: CSE doesn't meet DATA CLEAR cmd prerequisites\n");
+ return false;
+ }
+
+ printk(BIOS_DEBUG, "cse_lite: 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_lite: CSE DATA CLEAR command response failed: %d\n",
+ data_clr_rsp.result);
+ return false;
+ }
+
+ return true;
+}
+
static bool cse_get_cbfs_rw_version(const struct region_device *source_rdev,
void *cse_cbfs_rw_ver)
{
@@ -504,9 +547,38 @@
return cse_cbfs_rw_ver.build - cse_rw_ver->build;
}

+/* Check if CSE RW data partition is valid or not */
+static bool cse_is_rw_dp_valid(const struct cse_bp_info *cse_bp_info)
+{
+ const struct cse_bp_entry *rw_bp;
+
+ rw_bp = cse_get_bp_entry(RW, cse_bp_info);
+ return rw_bp->status != BP_STATUS_DATA_FAILURE;
+}
+
+/*
+ * It returns true if RW partition doesn't indicate BP_STATUS_DATA_FAILURE
+ * otherwise false if any operation fails.
+ */
+static bool cse_fix_data_failure_err(const struct cse_bp_info *cse_bp_info)
+{
+ /*
+ * If RW partition status indicates BP_STATUS_DATA_FAILURE,
+ * - Send DATA CLEAR HECI command to CSE
+ * - Send SET BOOT PARTITION INFO(RW) command to set CSE's next partition
+ * - Issue GLOBAL RESET HECI command.
+ */
+ if (cse_is_rw_dp_valid(cse_bp_info))
+ return true;
+
+ if (!cse_data_clear_request(cse_bp_info))
+ return false;
+
+ return cse_boot_to_rw(cse_bp_info);
+}
+
static bool cse_erase_rw_region(const struct region_device *target_rdev)
{
-
if (rdev_eraseat(target_rdev, 0, region_device_sz(target_rdev)) < 0) {
printk(BIOS_ERR, "cse_lite: CSE RW partition could not be erased\n");
return false;
@@ -531,6 +603,12 @@
return !cse_check_version_mismatch(cse_bp_info, source_rdev);
}

+static bool cse_is_downgrade_instance(const struct cse_bp_info *cse_bp_info,
+ const struct region_device *source_rdev)
+{
+ return cse_check_version_mismatch(cse_bp_info, source_rdev) < 0;
+}
+
static bool cse_is_update_required(const struct cse_bp_info *cse_bp_info,
const struct region_device *source_rdev, struct region_device *target_rdev)
{
@@ -581,7 +659,8 @@
return true;
}

-static bool cse_prep_for_rw_update(const struct cse_bp_info *cse_bp_info)
+static bool cse_prep_for_rw_update(const struct cse_bp_info *cse_bp_info,
+ const struct region_device *source_rdev)
{
/*
* To set CSE's operation mode to HMRFPO mode:
@@ -591,13 +670,19 @@
if (!cse_boot_to_ro(cse_bp_info))
return false;

+ if (cse_is_downgrade_instance(cse_bp_info, source_rdev) &&
+ !cse_data_clear_request(cse_bp_info)) {
+ printk(BIOS_ERR, "cse_lite: CSE FW downgrade is aborted\n");
+ return false;
+ }
+
return cse_hmrfpo_enable();
}

static uint8_t cse_trigger_fw_update(const struct cse_bp_info *cse_bp_info,
const struct region_device *source_rdev, struct region_device *target_rdev)
{
- if (!cse_prep_for_rw_update(cse_bp_info))
+ if (!cse_prep_for_rw_update(cse_bp_info, source_rdev))
return CSE_LITE_SKU_COMMUNICATION_ERROR;

if (!cse_update_rw(cse_bp_info, source_rdev, target_rdev))
@@ -647,6 +732,9 @@
cse_trigger_recovery(CSE_LITE_SKU_COMMUNICATION_ERROR);
}

+ if (!cse_fix_data_failure_err(&cse_bp_info.bp_info))
+ cse_trigger_recovery(CSE_LITE_SKU_DATA_WIPE_ERROR);
+
/* If RW blob is present in CBFS, then trigger CSE firmware update */
uint8_t rv;
struct region_device source_rdev;
diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h
index 5466ba6..a67010c 100644
--- a/src/soc/intel/common/block/include/intelblocks/cse.h
+++ b/src/soc/intel/common/block/include/intelblocks/cse.h
@@ -27,6 +27,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: 37
Gerrit-Owner: Sridhar Siricilla <sridhar.siricilla@intel.com>
Gerrit-Reviewer: Angel Pons <th3fanbus@gmail.com>
Gerrit-Reviewer: Balaji Manigandan <balaji.manigandan@intel.com>
Gerrit-Reviewer: Furquan Shaikh <furquan@google.com>
Gerrit-Reviewer: Jamie Ryu <jamie.m.ryu@intel.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-Reviewer: Patrick Rudolph <siro@das-labor.org>
Gerrit-Reviewer: Rizwan Qureshi <rizwan.qureshi@intel.com>
Gerrit-Reviewer: Sridhar Siricilla <sridhar.siricilla@intel.corp-partner.google.com>
Gerrit-Reviewer: Subrata Banik <subrata.banik@intel.com>
Gerrit-Reviewer: Tim Wawrzynczak <twawrzynczak@chromium.org>
Gerrit-Reviewer: V Sowmya <v.sowmya@intel.com>
Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org>
Gerrit-CC: Paul Menzel <paulepanter@users.sourceforge.net>
Gerrit-MessageType: merged