Attention is currently required from: Patrick Rudolph. Tim Wawrzynczak has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/55631 )
Change subject: soc/intel/common/cse: Add support for sending CSE End-of-Post message ......................................................................
soc/intel/common/cse: Add support for sending CSE End-of-Post message
The CSE expects the boot firmware to send it an End-of-Post message before loading the OS. This is a security feature, and is done to ensure that the CSE will no longer perform certain sensitive commands that are not intended to be exposed to the OS.
Signed-off-by: Tim Wawrzynczak twawrzynczak@chromium.org Change-Id: I6f667905f759cc2337daca4cc6e09694e68ab7e8 --- M src/soc/intel/common/block/cse/Kconfig M src/soc/intel/common/block/cse/cse.c M src/soc/intel/common/block/include/intelblocks/cse.h 3 files changed, 109 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/31/55631/1
diff --git a/src/soc/intel/common/block/cse/Kconfig b/src/soc/intel/common/block/cse/Kconfig index 044c60b..e5f9537 100644 --- a/src/soc/intel/common/block/cse/Kconfig +++ b/src/soc/intel/common/block/cse/Kconfig @@ -70,3 +70,11 @@ 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). + +config SOC_INTEL_CSE_SET_EOP + bool + default n + help + This config will have coreboot send the CSE the End-of-POST message + just prior to loading the payload. This is a security feature so the + CSE will no longer respond to Pre-Boot commands. diff --git a/src/soc/intel/common/block/cse/cse.c b/src/soc/intel/common/block/cse/cse.c index c6f87b4..7767269 100644 --- a/src/soc/intel/common/block/cse/cse.c +++ b/src/soc/intel/common/block/cse/cse.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h> +#include <bootstate.h> #include <commonlib/helpers.h> #include <console/console.h> #include <device/mmio.h> @@ -9,6 +10,7 @@ #include <device/pci_ids.h> #include <device/pci_ops.h> #include <intelblocks/cse.h> +#include <soc/intel/common/reset.h> #include <soc/iomap.h> #include <soc/pci_devs.h> #include <soc/me.h> @@ -794,6 +796,65 @@ return resp.status; }
+/* From #627331, ADL Intel CSME 16.0 BIOS Spec */ +enum cse_eop_result cse_send_eop(void) +{ + enum eop_requested_action { + EOP_REQUESTED_ACTION_CONTINUE = 0, + EOP_REQUESTED_ACTION_GLOBAL_RESET = 1, + }; + struct end_of_post_msg { + struct mkhi_hdr hdr; + }; + struct end_of_post_resp { + struct mkhi_hdr hdr; + uint32_t requested_actions; + } __packed; + struct end_of_post_msg msg = { + .hdr = { + .group_id = MKHI_GROUP_ID_GEN, + .command = 0x0c, + }, + }; + struct end_of_post_resp resp; + size_t resp_size = sizeof(resp); + + /* + * Prerequisites: + * 1) HFSTS1 CWS = Normal + * 2) HFSTS1 COM = Normal + * 3) Only sent after DID (ensuring this is the responsibility of the caller) + */ + if (!cse_is_hfs1_cws_normal()) { + printk(BIOS_ERR, "HECI: CSE's current working state is not Normal\n"); + return CSE_EOP_RESULT_ERROR; + } + + if (!cse_is_hfs1_com_normal()) { + printk(BIOS_ERR, "HECI: CSE's current operating mode is not Normal\n"); + return CSE_EOP_RESULT_ERROR; + } + + printk(BIOS_INFO, "HECI: Sending End-of-Post\n"); + + if (!heci_send_receive(&msg, sizeof(struct end_of_post_msg), &resp, &resp_size)) { + printk(BIOS_ERR, "HECI: EOP send/receive fail\n"); + return CSE_EOP_RESULT_ERROR; + } + + if (resp.hdr.result) { + printk(BIOS_ERR, "HECI: EOP Resp Failed: %d\n", resp.hdr.result); + return CSE_EOP_RESULT_ERROR; + } + + if (resp.requested_actions == EOP_REQUESTED_ACTION_GLOBAL_RESET) + return CSE_EOP_RESULT_GLOBAL_RESET_REQUESTED; + else if (resp.requested_actions == EOP_REQUESTED_ACTION_CONTINUE) + return CSE_EOP_RESULT_SUCCESS; + else + return CSE_EOP_RESULT_ERROR; +} + void print_me_fw_version(void *unused) { struct version { @@ -924,4 +985,32 @@ .devices = pci_device_ids };
+static void set_cse_end_of_post(void *unused) +{ + if (!CONFIG(SOC_INTEL_CSE_SET_EOP)) + return; + + enum cse_eop_result result = cse_send_eop(); + + switch (result) { + case CSE_EOP_RESULT_ERROR: + printk(BIOS_ERR, "ERROR: Failed to send EOP to CSE, it will still respond to" + " pre-boot commands!\n"); + break; + case CSE_EOP_RESULT_GLOBAL_RESET_REQUESTED: + printk(BIOS_INFO, "CSE requested global reset in EOP response, sending global" + " reset\n"); + do_global_reset(); + break; + case CSE_EOP_RESULT_SUCCESS: + printk(BIOS_INFO, "CSE EOP successful, continuing boot\n"); + break; + default: + printk(BIOS_ERR, "ERROR: Invalid response to cse_send_eop(): %d\n", (int)result); + break; + } +} + +BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_ENTRY, set_cse_end_of_post, NULL); + #endif diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h index 1a95e2e..0bce080 100644 --- a/src/soc/intel/common/block/include/intelblocks/cse.h +++ b/src/soc/intel/common/block/include/intelblocks/cse.h @@ -241,4 +241,16 @@ /* Perform a board-specific reset sequence for CSE RO<->RW jump */ void cse_board_reset(void);
+enum cse_eop_result { + CSE_EOP_RESULT_SUCCESS, + CSE_EOP_RESULT_ERROR, + CSE_EOP_RESULT_GLOBAL_RESET_REQUESTED, +}; + +/* Send End-of-POST message to CSE; in case the HECI interface is disabled in the + * SoC finalize operation, this must be performed prior to this. It also cannot + * be sent prior to DRAM Init Done (DID). + */ +enum cse_eop_result cse_send_eop(void); + #endif // SOC_INTEL_COMMON_CSE_H