diff options
-rw-r--r-- | src/soc/intel/common/block/cse/Kconfig | 14 | ||||
-rw-r--r-- | src/soc/intel/common/block/cse/cse_lite.c | 224 |
2 files changed, 124 insertions, 114 deletions
diff --git a/src/soc/intel/common/block/cse/Kconfig b/src/soc/intel/common/block/cse/Kconfig index 5b52bfd9c3..a2c8928cf0 100644 --- a/src/soc/intel/common/block/cse/Kconfig +++ b/src/soc/intel/common/block/cse/Kconfig @@ -20,32 +20,38 @@ config SOC_INTEL_CSE_LITE_SKU help Enables CSE Lite SKU +config SOC_INTEL_CSE_RW_UPDATE + bool "Enable the CSE RW Update Feature" + default n + depends on SOC_INTEL_CSE_LITE_SKU + help + This config will enable CSE RW firmware update feature and also will be used ensure + all the required configs are provided by mainboard. + +if SOC_INTEL_CSE_RW_UPDATE config SOC_INTEL_CSE_FMAP_NAME string "Name of CSE Region in FMAP" - depends on SOC_INTEL_CSE_LITE_SKU default "SI_ME" help Name of CSE region in FMAP config SOC_INTEL_CSE_RW_CBFS_NAME string "CBFS entry name for CSE RW blob" - depends on SOC_INTEL_CSE_LITE_SKU default "me_rw" help CBFS entry name for Intel CSE CBFS RW blob config SOC_INTEL_CSE_RW_FILE string "Intel CSE CBFS RW path and filename" - depends on SOC_INTEL_CSE_LITE_SKU default "" help Intel CSE CBFS RW blob path and file name config SOC_INTEL_CSE_RW_VERSION string "Intel CSE RW firmware version" - depends on SOC_INTEL_CSE_LITE_SKU default "" help This config contains the Intel CSE RW version of the blob that is provided by SOC_INTEL_CSE_RW_FILE config and the version must be set in the format major.minor.hotfix.build (ex: 14.0.40.1209). +endif diff --git a/src/soc/intel/common/block/cse/cse_lite.c b/src/soc/intel/common/block/cse/cse_lite.c index c9e4e1f470..edb35c4353 100644 --- a/src/soc/intel/common/block/cse/cse_lite.c +++ b/src/soc/intel/common/block/cse/cse_lite.c @@ -191,49 +191,6 @@ static const struct cse_bp_entry *cse_get_bp_entry(enum boot_partition_id bp, return &cse_bp_info->bp_entries[bp]; } -static void cse_get_bp_entry_range(const struct cse_bp_info *cse_bp_info, - enum boot_partition_id bp, uint32_t *start_offset, uint32_t *end_offset) -{ - const struct cse_bp_entry *cse_bp; - - cse_bp = cse_get_bp_entry(bp, cse_bp_info); - - if (start_offset) - *start_offset = cse_bp->start_offset; - - if (end_offset) - *end_offset = cse_bp->end_offset; - -} - -static const struct fw_version *cse_get_bp_entry_version(enum boot_partition_id bp, - const struct cse_bp_info *bp_info) -{ - const struct cse_bp_entry *cse_bp; - - cse_bp = cse_get_bp_entry(bp, bp_info); - return &cse_bp->fw_ver; -} - -static const struct fw_version *cse_get_rw_version(const struct cse_bp_info *cse_bp_info) -{ - return cse_get_bp_entry_version(RW, cse_bp_info); -} - -static bool cse_is_rw_bp_status_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); - - if (rw_bp->status == BP_STATUS_PARTITION_NOT_PRESENT || - rw_bp->status == BP_STATUS_GENERAL_FAILURE) { - printk(BIOS_ERR, "cse_lite: RW BP (status:%u) is not valid\n", rw_bp->status); - return false; - } - return true; -} - static void cse_print_boot_partition_info(const struct cse_bp_info *cse_bp_info) { const struct cse_bp_entry *cse_bp; @@ -369,6 +326,43 @@ static bool cse_set_next_boot_partition(enum boot_partition_id bp) 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; +} __weak void cse_board_reset(void) { /* Default weak implementation, does nothing. */ @@ -400,6 +394,80 @@ static bool cse_boot_to_rw(const struct cse_bp_info *cse_bp_info) return cse_set_and_boot_from_next_bp(RW); } +/* 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); +} + +#if CONFIG(SOC_INTEL_CSE_RW_UPDATE) +static const struct fw_version *cse_get_bp_entry_version(enum boot_partition_id bp, + const struct cse_bp_info *bp_info) +{ + const struct cse_bp_entry *cse_bp; + + cse_bp = cse_get_bp_entry(bp, bp_info); + return &cse_bp->fw_ver; +} + +static const struct fw_version *cse_get_rw_version(const struct cse_bp_info *cse_bp_info) +{ + return cse_get_bp_entry_version(RW, cse_bp_info); +} + +static void cse_get_bp_entry_range(const struct cse_bp_info *cse_bp_info, + enum boot_partition_id bp, uint32_t *start_offset, uint32_t *end_offset) +{ + const struct cse_bp_entry *cse_bp; + + cse_bp = cse_get_bp_entry(bp, cse_bp_info); + + if (start_offset) + *start_offset = cse_bp->start_offset; + + if (end_offset) + *end_offset = cse_bp->end_offset; + +} + +static bool cse_is_rw_bp_status_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); + + if (rw_bp->status == BP_STATUS_PARTITION_NOT_PRESENT || + rw_bp->status == BP_STATUS_GENERAL_FAILURE) { + printk(BIOS_ERR, "cse_lite: RW BP (status:%u) is not valid\n", rw_bp->status); + return false; + } + return true; +} + static bool cse_boot_to_ro(const struct cse_bp_info *cse_bp_info) { if (cse_get_current_bp(cse_bp_info) == RO) @@ -465,43 +533,6 @@ static bool cse_get_target_rdev(const struct cse_bp_info *cse_bp_info, 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) @@ -548,36 +579,6 @@ static int cse_check_version_mismatch(const struct cse_bp_info *cse_bp_info, 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) { @@ -712,6 +713,7 @@ static uint8_t cse_fw_update(const struct cse_bp_info *cse_bp_info, return 0; } +#endif void cse_fw_sync(void *unused) { @@ -737,6 +739,7 @@ void cse_fw_sync(void *unused) cse_trigger_recovery(CSE_LITE_SKU_DATA_WIPE_ERROR); /* If RW blob is present in CBFS, then trigger CSE firmware update */ +#if CONFIG(SOC_INTEL_CSE_RW_UPDATE) uint8_t rv; struct region_device source_rdev; if (cse_get_cbfs_rdev(&source_rdev)) { @@ -744,6 +747,7 @@ void cse_fw_sync(void *unused) if (rv) cse_trigger_recovery(rv); } +#endif if (!cse_boot_to_rw(&cse_bp_info.bp_info)) { printk(BIOS_ERR, "cse_lite: Failed to switch to RW\n"); |