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:
		@@ -11,6 +11,7 @@
 | 
				
			|||||||
#include <device/pci_ids.h>
 | 
					#include <device/pci_ids.h>
 | 
				
			||||||
#include <device/pci_ops.h>
 | 
					#include <device/pci_ops.h>
 | 
				
			||||||
#include <intelblocks/cse.h>
 | 
					#include <intelblocks/cse.h>
 | 
				
			||||||
 | 
					#include <option.h>
 | 
				
			||||||
#include <security/vboot/misc.h>
 | 
					#include <security/vboot/misc.h>
 | 
				
			||||||
#include <security/vboot/vboot_common.h>
 | 
					#include <security/vboot/vboot_common.h>
 | 
				
			||||||
#include <soc/iomap.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
 | 
					#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 = {
 | 
					static struct device_operations cse_ops = {
 | 
				
			||||||
	.set_resources		= pci_dev_set_resources,
 | 
						.set_resources		= pci_dev_set_resources,
 | 
				
			||||||
	.read_resources		= pci_dev_read_resources,
 | 
						.read_resources		= pci_dev_read_resources,
 | 
				
			||||||
	.enable_resources	= pci_dev_enable_resources,
 | 
						.enable_resources	= pci_dev_enable_resources,
 | 
				
			||||||
	.init			= pci_dev_init,
 | 
						.init			= pci_dev_init,
 | 
				
			||||||
	.ops_pci		= &pci_dev_ops_pci,
 | 
						.ops_pci		= &pci_dev_ops_pci,
 | 
				
			||||||
 | 
						.enable			= cse_enable,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const unsigned short pci_device_ids[] = {
 | 
					static const unsigned short pci_device_ids[] = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* MKHI Command groups */
 | 
					/* MKHI Command groups */
 | 
				
			||||||
#define MKHI_GROUP_ID_CBM	0x0
 | 
					#define MKHI_GROUP_ID_CBM	0x0
 | 
				
			||||||
 | 
					#define MKHI_GROUP_ID_FWCAPS	0x3
 | 
				
			||||||
#define MKHI_GROUP_ID_HMRFPO	0x5
 | 
					#define MKHI_GROUP_ID_HMRFPO	0x5
 | 
				
			||||||
#define MKHI_GROUP_ID_GEN	0xff
 | 
					#define MKHI_GROUP_ID_GEN	0xff
 | 
				
			||||||
#define MKHI_GROUP_ID_BUP_COMMON	0xf0
 | 
					#define MKHI_GROUP_ID_BUP_COMMON	0xf0
 | 
				
			||||||
@@ -18,6 +19,13 @@
 | 
				
			|||||||
/* Origin of Global Reset command */
 | 
					/* Origin of Global Reset command */
 | 
				
			||||||
#define GR_ORIGIN_BIOS_POST	0x2
 | 
					#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 */
 | 
					/* HMRFPO Command Ids */
 | 
				
			||||||
#define MKHI_HMRFPO_ENABLE	0x1
 | 
					#define MKHI_HMRFPO_ENABLE	0x1
 | 
				
			||||||
#define MKHI_HMRFPO_GET_STATUS	0x3
 | 
					#define MKHI_HMRFPO_GET_STATUS	0x3
 | 
				
			||||||
@@ -31,6 +39,9 @@
 | 
				
			|||||||
/* Set End-of-POST in CSE */
 | 
					/* Set End-of-POST in CSE */
 | 
				
			||||||
#define MKHI_END_OF_POST	0xc
 | 
					#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 */
 | 
					/* Boot partition info and set boot partition info command ids */
 | 
				
			||||||
#define MKHI_BUP_COMMON_GET_BOOT_PARTITION_INFO	0x1c
 | 
					#define MKHI_BUP_COMMON_GET_BOOT_PARTITION_INFO	0x1c
 | 
				
			||||||
#define MKHI_BUP_COMMON_SET_BOOT_PARTITION_INFO	0x1d
 | 
					#define MKHI_BUP_COMMON_SET_BOOT_PARTITION_INFO	0x1d
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user