diff options
author | Michał Żygowski <michal.zygowski@3mdeb.com> | 2022-10-04 10:55:38 +0200 |
---|---|---|
committer | Michał Żygowski <michal.zygowski@3mdeb.com> | 2023-01-27 16:25:37 +0000 |
commit | daa17107cbe68194a36f14911e420eee21310c00 (patch) | |
tree | a9a69aafbe2e08cd69c2e332429170209cdb3e44 /src/soc/intel/common | |
parent | 0b6954b8d538f0e7eb6b7aa852fb0e3a4a9ed352 (diff) |
intelblocks/cse: Add functions to check and change PTT state
Add functions that allow checking and changing PTT state at runtime.
Can be useful for platforms that want to use dTPM instead and have no
means to stitch ME firmware binary with disabled PTT.
The changing function also checks for the current feature states via
HECI to ensure that the feature state will not be changed if not
needed.
TEST=Successfully switch to dTPM on Comet Lake i5-10210U SoC.
Signed-off-by: Michał Żygowski <michal.zygowski@3mdeb.com>
Change-Id: I8426c46eada2d503d6ee72324c5d0025da3f2028
Reviewed-on: https://review.coreboot.org/c/coreboot/+/68919
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Krystian Hebel <krystian.hebel@3mdeb.com>
Diffstat (limited to 'src/soc/intel/common')
-rw-r--r-- | src/soc/intel/common/block/cse/cse.c | 157 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/cse.h | 20 |
2 files changed, 177 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/cse/cse.c b/src/soc/intel/common/block/cse/cse.c index d697c84a97..2928a4e6c6 100644 --- a/src/soc/intel/common/block/cse/cse.c +++ b/src/soc/intel/common/block/cse/cse.c @@ -247,6 +247,15 @@ static bool cse_check_hfs1_com(int mode) return hfs1.fields.operation_mode == mode; } +static bool cse_is_hfs1_fw_init_complete(void) +{ + union me_hfsts1 hfs1; + hfs1.data = me_read_config32(PCI_ME_HFSTS1); + if (hfs1.fields.fw_init_complete) + return true; + return false; +} + bool cse_is_hfs1_cws_normal(void) { union me_hfsts1 hfs1; @@ -1069,6 +1078,154 @@ void cse_control_global_reset_lock(void) pmc_global_reset_enable(false); } +enum cb_err cse_get_fw_feature_state(uint32_t *feature_state) +{ + struct fw_feature_state_msg { + struct mkhi_hdr hdr; + uint32_t rule_id; + } __packed; + + /* Get Firmware Feature State message */ + struct fw_feature_state_msg msg = { + .hdr = { + .group_id = MKHI_GROUP_ID_FWCAPS, + .command = MKHI_FWCAPS_GET_FW_FEATURE_STATE, + }, + .rule_id = ME_FEATURE_STATE_RULE_ID + }; + + /* Get Firmware Feature State response */ + struct fw_feature_state_resp { + struct mkhi_hdr hdr; + uint32_t rule_id; + uint8_t rule_len; + uint32_t fw_runtime_status; + } __packed; + + struct fw_feature_state_resp resp; + size_t resp_size = sizeof(struct fw_feature_state_resp); + + /* Ignore if CSE is disabled or input buffer is invalid */ + if (!is_cse_enabled() || !feature_state) + return CB_ERR; + + /* + * Prerequisites: + * 1) HFSTS1 Current Working State is Normal + * 2) HFSTS1 Current Operation Mode is Normal + * 3) It's after DRAM INIT DONE message (taken care of by calling it + * during ramstage) + */ + if (!cse_is_hfs1_cws_normal() || !cse_is_hfs1_com_normal() || !ENV_RAMSTAGE) + return CB_ERR; + + printk(BIOS_DEBUG, "HECI: Send GET FW FEATURE STATE Command\n"); + + if (heci_send_receive(&msg, sizeof(struct fw_feature_state_msg), + &resp, &resp_size, HECI_MKHI_ADDR)) + return CB_ERR; + + if (resp.hdr.result) { + printk(BIOS_ERR, "HECI: Resp Failed:%d\n", resp.hdr.result); + return CB_ERR; + } + + if (resp.rule_len != sizeof(resp.fw_runtime_status)) { + printk(BIOS_ERR, "HECI: GET FW FEATURE STATE has invalid rule data length\n"); + return CB_ERR; + } + + *feature_state = resp.fw_runtime_status; + + return CB_SUCCESS; +} + +void cse_enable_ptt(bool state) +{ + struct fw_feature_shipment_override_msg { + struct mkhi_hdr hdr; + uint32_t enable_mask; + uint32_t disable_mask; + } __packed; + + /* FW Feature Shipment Time State Override message */ + struct fw_feature_shipment_override_msg msg = { + .hdr = { + .group_id = MKHI_GROUP_ID_GEN, + .command = MKHI_GEN_FW_FEATURE_SHIPMENT_OVER, + }, + .enable_mask = 0, + .disable_mask = 0 + }; + + /* FW Feature Shipment Time State Override response */ + struct fw_feature_shipment_override_resp { + struct mkhi_hdr hdr; + uint32_t data; + } __packed; + + struct fw_feature_shipment_override_resp resp; + size_t resp_size = sizeof(struct fw_feature_shipment_override_resp); + uint32_t feature_status; + + /* Ignore if CSE is disabled */ + if (!is_cse_enabled()) + return; + + printk(BIOS_DEBUG, "Requested to change PTT state to %sabled\n", state ? "en" : "dis"); + + /* + * Prerequisites: + * 1) HFSTS1 Current Working State is Normal + * 2) HFSTS1 Current Operation Mode is Normal + * 3) It's after DRAM INIT DONE message (taken care of by calling it + * during ramstage + * 4) HFSTS1 FW Init Complete is set + * 5) Before EOP issued to CSE + */ + if (!cse_is_hfs1_cws_normal() || !cse_is_hfs1_com_normal() || + !cse_is_hfs1_fw_init_complete() || !ENV_RAMSTAGE) { + printk(BIOS_ERR, "HECI: Unmet prerequisites for" + "FW FEATURE SHIPMENT TIME STATE OVERRIDE\n"); + return; + } + + if (cse_get_fw_feature_state(&feature_status) != CB_SUCCESS) { + printk(BIOS_ERR, "HECI: Cannot determine current feature status\n"); + return; + } + + if (!!(feature_status & ME_FW_FEATURE_PTT) == state) { + printk(BIOS_DEBUG, "HECI: PTT is already in the requested state\n"); + return; + } + + printk(BIOS_DEBUG, "HECI: Send FW FEATURE SHIPMENT TIME STATE OVERRIDE Command\n"); + + if (state) + msg.enable_mask |= ME_FW_FEATURE_PTT; + else + msg.disable_mask |= ME_FW_FEATURE_PTT; + + if (heci_send_receive(&msg, sizeof(struct fw_feature_shipment_override_msg), + &resp, &resp_size, HECI_MKHI_ADDR)) + return; + + if (resp.hdr.result) { + printk(BIOS_ERR, "HECI: Resp Failed:%d\n", resp.hdr.result); + return; + } + + /* Global reset is required after acceptance of the command */ + if (resp.data == 0) { + printk(BIOS_DEBUG, "HECI: FW FEATURE SHIPMENT TIME STATE OVERRIDE success\n"); + do_global_reset(); + } else { + printk(BIOS_ERR, "HECI: FW FEATURE SHIPMENT TIME STATE OVERRIDE error (%x)\n", + resp.data); + } +} + #if ENV_RAMSTAGE /* diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h index b031aa3390..4634984756 100644 --- a/src/soc/intel/common/block/include/intelblocks/cse.h +++ b/src/soc/intel/common/block/include/intelblocks/cse.h @@ -30,6 +30,14 @@ /* Get Firmware Version Command Id */ #define MKHI_GEN_GET_FW_VERSION 0x2 +/* Firmware Feature Shipment Time State Override Command Id */ +#define MKHI_GEN_FW_FEATURE_SHIPMENT_OVER 0x14 +#define ME_FW_FEATURE_PTT BIT(29) + +/* Get Firmware Feature State Command Id */ +#define MKHI_FWCAPS_GET_FW_FEATURE_STATE 0x02 +#define ME_FEATURE_STATE_RULE_ID 0x20 + /* MEI bus disable command. Must be sent to MEI client endpoint, not MKHI */ #define MEI_BUS_DISABLE_COMMAND 0xc @@ -567,4 +575,16 @@ void cse_get_telemetry_data(void); /* Function to log the cse WP information like range, if WP etc. */ void cse_log_ro_write_protection_info(bool mfg_mode); +/* + * Changes Intel PTT feature state at runtime. Global reset is required after + * successful HECI command completion. + */ +void cse_enable_ptt(bool state); + +/* + * Queries CSE for runtime status of firmware features. + * Returns 0 on success and < 0 on failure. + */ +enum cb_err cse_get_fw_feature_state(uint32_t *feature_state); + #endif // SOC_INTEL_COMMON_CSE_H |