From 386654ac73a55be89f0d2b64b347b2bd50b3cb03 Mon Sep 17 00:00:00 2001 From: Tim Crawford Date: Thu, 9 Sep 2021 16:51:36 -0600 Subject: [PATCH] soc/intel/common/cse: Add option to set IME mode Add function to have CSME firmware enter Soft Temporary Disable mode, and a corresponding function to put it back into Normal mode. A global reset is required for the CSME to change modes. Control changing modes by a new option "ime_mode". Possible values are - Enable (0): Set the current operation mode to Normal - Disable (1): Set the current operation mode to Soft Temporary Disable Reference: - Intel doc #612229 (CSME 15.0 BIOS Specification) Change-Id: I38d320fbb157a628c5decc90e6ced78efbf85e0d Signed-off-by: Tim Crawford --- src/soc/intel/common/block/cse/cse.c | 124 ++++++++++++++++++ .../common/block/include/intelblocks/cse.h | 11 ++ 2 files changed, 135 insertions(+) diff --git a/src/soc/intel/common/block/cse/cse.c b/src/soc/intel/common/block/cse/cse.c index f37ff9589e..8f1911cef0 100644 --- a/src/soc/intel/common/block/cse/cse.c +++ b/src/soc/intel/common/block/cse/cse.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -961,12 +962,135 @@ bool set_cse_device_state(unsigned int devfn, enum cse_device_state requested_st #if ENV_RAMSTAGE +/* + * Sets the ME firmware to "Soft Temporary Disable" mode. + * + * Sends FWCAPS_SET_RULE command with SET_ME_DISABLE rule to CSE. + * Returns 0 on failure and 1 on success. + */ +static int cse_soft_disable(void) +{ + struct disable_msg { + struct mkhi_hdr hdr; + uint32_t rule_id; + uint8_t rule_len; + uint32_t rule_data; + } __packed msg = { + .hdr = { + .group_id = MKHI_GROUP_ID_FWCAPS, + .command = MKHI_FWCAPS_SET_RULE, + }, + .rule_id = MKHI_FWCAPS_RULE_SET_ME_DISABLE, + .rule_len = 4, + .rule_data = 0, + }; + + struct disable_resp { + struct mkhi_hdr hdr; + uint32_t rule_id; + } __packed; + + struct disable_resp resp; + size_t resp_size = sizeof(resp); + + printk(BIOS_DEBUG, "HECI: Send Set ME Disable message\n"); + + /* + * Allow sending Set ME Disable message only if: + * - CSE's current working state is Normal and current operation mode is Normal + * - Intel AMT is not opened in SoL, SRoU, or KVM session (TODO) + */ + if (!cse_is_hfs1_cws_normal() || !cse_is_hfs1_com_normal()) + return 0; + + if (!heci_send_receive(&msg, sizeof(msg), &resp, &resp_size, HECI_MKHI_ADDR)) + return 0; + + if (resp.hdr.result) { + printk(BIOS_ERR, "HECI: Set ME Disable failed: %d\n", resp.hdr.result); + return 0; + } + + /* Global reset is required after issuing this message */ + cse_request_global_reset(); + + return 1; +} + +/* + * Takes the ME firmware out of "Soft Temporary Disable" mode. + * + * Sends SET_ME_ENABLE command to CSE. + * Returns 0 on failure and 1 on success. + */ +static int cse_soft_enable(void) +{ + struct enable_msg { + struct mkhi_hdr hdr; + } __packed; + + struct enable_msg msg = { + .hdr = { + .group_id = MKHI_GROUP_ID_BUP_COMMON, + .command = MKHI_BUP_COMMON_SET_ME_ENABLE, + }, + }; + + struct enable_resp { + struct mkhi_hdr hdr; + } __packed; + + struct enable_resp resp; + size_t resp_size = sizeof(resp); + + printk(BIOS_DEBUG, "HECI: Send Set ME Enable message\n"); + + /* + * Allow sending Set ME Enable message only if: + * - CSE's current operation mode is Soft Temporary Disable + */ + if (!cse_is_hfs1_com_soft_temp_disable()) + return 0; + + if (!heci_send_receive(&msg, sizeof(msg), &resp, &resp_size, HECI_MKHI_ADDR)) + return 0; + + if (resp.hdr.result == 0) { + /* Global reset is required after issuing this message */ + cse_request_global_reset(); + } else { + printk(BIOS_ERR, "HECI: ME not in Soft Temporary Disable mode\n"); + } + + return 1; +} + +static void cse_enable(struct device *dev) +{ + enum { + ENABLE, + DISABLE, + DONT_TOUCH = 0xff, + } mode; + + mode = get_uint_option("ime_mode", DONT_TOUCH); + if (mode == DONT_TOUCH) + return; + + if (mode == ENABLE) + cse_soft_enable(); + else if (mode == DISABLE) + cse_soft_disable(); +} + + static struct device_operations cse_ops = { .set_resources = pci_dev_set_resources, .read_resources = pci_dev_read_resources, .enable_resources = pci_dev_enable_resources, .init = pci_dev_init, .ops_pci = &pci_dev_ops_pci, + .enable = cse_enable, }; static const unsigned short pci_device_ids[] = { diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h index 7f455708e3..7ba3c27a45 100644 --- a/src/soc/intel/common/block/include/intelblocks/cse.h +++ b/src/soc/intel/common/block/include/intelblocks/cse.h @@ -8,6 +8,7 @@ /* MKHI Command groups */ #define MKHI_GROUP_ID_CBM 0x0 +#define MKHI_GROUP_ID_FWCAPS 0x3 #define MKHI_GROUP_ID_HMRFPO 0x5 #define MKHI_GROUP_ID_GEN 0xff #define MKHI_GROUP_ID_BUP_COMMON 0xf0 @@ -18,6 +19,13 @@ /* Origin of Global Reset command */ #define GR_ORIGIN_BIOS_POST 0x2 +/* Get/Set Firmware Capabilities Command IDs */ +#define MKHI_FWCAPS_GET_RULE 0x2 +#define MKHI_FWCAPS_SET_RULE 0x3 + +/* Firmware Capabilities Rule IDs */ +#define MKHI_FWCAPS_RULE_SET_ME_DISABLE 0x6 + /* HMRFPO Command Ids */ #define MKHI_HMRFPO_ENABLE 0x1 #define MKHI_HMRFPO_GET_STATUS 0x3 @@ -31,6 +39,9 @@ /* Set End-of-POST in CSE */ #define MKHI_END_OF_POST 0xc +/* Enable IME command */ +#define MKHI_BUP_COMMON_SET_ME_ENABLE 0x03 + /* 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