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 <tcrawford@system76.com>
This commit is contained in:
Tim Crawford
2021-09-09 16:51:36 -06:00
parent 3be5988d50
commit 386654ac73
2 changed files with 135 additions and 0 deletions

View File

@@ -11,6 +11,7 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <intelblocks/cse.h>
#include <option.h>
#include <security/vboot/misc.h>
#include <security/vboot/vboot_common.h>
#include <soc/iomap.h>
@@ -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[] = {

View File

@@ -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