diff options
author | Tim Wawrzynczak <twawrzynczak@chromium.org> | 2021-06-17 12:40:13 -0600 |
---|---|---|
committer | Werner Zeh <werner.zeh@siemens.com> | 2021-06-25 04:17:23 +0000 |
commit | 064ca184631bf1f99d57d56c481a5ed4a2646cb2 (patch) | |
tree | 5566701b3b7d73fc0bd549ccb5ef457b64726327 /src/soc/intel/common/block | |
parent | 45c46b6c39690290449427df69752dbbf8d593c3 (diff) |
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.
If processing the EOP message fails in any way on a ChromeOS build, (and
not already in recovery mode), recovery mode will be triggered,
otherwise the CSME BWG will be followed, which is in the following
commit.
BUG=b:191362590
Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Change-Id: I6f667905f759cc2337daca4cc6e09694e68ab7e8
Reviewed-on: https://review.coreboot.org/c/coreboot/+/55631
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
Diffstat (limited to 'src/soc/intel/common/block')
-rw-r--r-- | src/soc/intel/common/block/cse/Kconfig | 8 | ||||
-rw-r--r-- | src/soc/intel/common/block/cse/Makefile.inc | 2 | ||||
-rw-r--r-- | src/soc/intel/common/block/cse/cse_eop.c | 108 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/cse.h | 6 |
4 files changed, 124 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/cse/Kconfig b/src/soc/intel/common/block/cse/Kconfig index 044c60bb76..492213e732 100644 --- a/src/soc/intel/common/block/cse/Kconfig +++ b/src/soc/intel/common/block/cse/Kconfig @@ -70,3 +70,11 @@ config SOC_INTEL_CSE_RW_VERSION 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 ensures coreboot will 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/Makefile.inc b/src/soc/intel/common/block/cse/Makefile.inc index 30eb78e091..e21efc6144 100644 --- a/src/soc/intel/common/block/cse/Makefile.inc +++ b/src/soc/intel/common/block/cse/Makefile.inc @@ -4,6 +4,8 @@ ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CSE) += cse.c romstage-$(CONFIG_SOC_INTEL_CSE_LITE_SKU) += cse_lite.c smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_HECI_DISABLE_IN_SMM) += disable_heci.c +ramstage-$(CONFIG_SOC_INTEL_CSE_SET_EOP) += cse_eop.c + ifeq ($(CONFIG_SOC_INTEL_CSE_RW_UPDATE),y) ifneq ($(CONFIG_SOC_INTEL_CSE_RW_FILE),"") CSE_LITE_ME_RW = $(call strip_quotes,$(CONFIG_SOC_INTEL_CSE_RW_CBFS_NAME)) diff --git a/src/soc/intel/common/block/cse/cse_eop.c b/src/soc/intel/common/block/cse/cse_eop.c new file mode 100644 index 0000000000..98e36f027c --- /dev/null +++ b/src/soc/intel/common/block/cse/cse_eop.c @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bootstate.h> +#include <console/console.h> +#include <intelblocks/cse.h> +#include <security/vboot/vboot_common.h> +#include <soc/intel/common/reset.h> +#include <types.h> + +enum cse_eop_result { + CSE_EOP_RESULT_GLOBAL_RESET_REQUESTED, + CSE_EOP_RESULT_SUCCESS, + CSE_EOP_RESULT_ERROR, +}; + +static enum cse_eop_result cse_send_eop(void) +{ + enum { + EOP_REQUESTED_ACTION_CONTINUE = 0, + EOP_REQUESTED_ACTION_GLOBAL_RESET = 1, + }; + struct end_of_post_msg { + struct mkhi_hdr hdr; + } __packed msg = { + .hdr = { + .group_id = MKHI_GROUP_ID_GEN, + .command = MKHI_END_OF_POST, + }, + }; + struct end_of_post_resp { + struct mkhi_hdr hdr; + uint32_t requested_actions; + } __packed resp = {}; + size_t resp_size = sizeof(resp); + + /* + * Prerequisites: + * 1) HFSTS1 CWS is Normal + * 2) HFSTS1 COM is Normal + * 3) Only sent after DID (accomplished by compiling this into ramstage) + */ + if (!cse_is_hfs1_cws_normal() || !cse_is_hfs1_com_normal()) { + printk(BIOS_ERR, "HECI: Prerequisites not met for sending EOP\n"); + return CSE_EOP_RESULT_ERROR; + } + + printk(BIOS_INFO, "HECI: Sending End-of-Post\n"); + + if (!heci_send_receive(&msg, sizeof(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: %u\n", resp.hdr.result); + return CSE_EOP_RESULT_ERROR; + } + + printk(BIOS_INFO, "CSE: EOP requested action: "); + + switch (resp.requested_actions) { + case EOP_REQUESTED_ACTION_GLOBAL_RESET: + printk(BIOS_INFO, "global reset\n"); + return CSE_EOP_RESULT_GLOBAL_RESET_REQUESTED; + case EOP_REQUESTED_ACTION_CONTINUE: + printk(BIOS_INFO, "continue boot\n"); + return CSE_EOP_RESULT_SUCCESS; + default: + printk(BIOS_INFO, "unknown %u\n", resp.requested_actions); + return CSE_EOP_RESULT_ERROR; + } +} + +static void handle_cse_eop_result(enum cse_eop_result result) +{ + switch (result) { + case CSE_EOP_RESULT_GLOBAL_RESET_REQUESTED: + printk(BIOS_INFO, "CSE requested global reset in EOP response, resetting...\n"); + do_global_reset(); + break; + case CSE_EOP_RESULT_SUCCESS: + printk(BIOS_INFO, "CSE EOP successful, continuing boot\n"); + break; + case CSE_EOP_RESULT_ERROR: /* fallthrough */ + default: + printk(BIOS_ERR, "ERROR: Failed to send EOP to CSE, %d\n", result); + /* For vboot, trigger recovery mode if applicable, as there is + likely something very broken in this case. */ + if (CONFIG(VBOOT) && !vboot_recovery_mode_enabled()) + cse_trigger_vboot_recovery(CSE_EOP_FAIL); + break; + } +} + +static void set_cse_end_of_post(void *unused) +{ + handle_cse_eop_result(cse_send_eop()); +} + +/* + * Ideally, to give coreboot maximum flexibility, sending EOP would be done as + * late possible, just before loading the payload, which would be BS_ON_EXIT + * here, but the platforms this is currently supported for all select + * HECI_DISABLE_USING_SMM, which runs in BS_ON_EXIT. Because sending EOP + * requires HECI to be up, and it is not trivial to control the order in which + * these callbacks are issued, it is called on BS_ON_ENTRY. + */ +BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_ENTRY, set_cse_end_of_post, NULL); diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h index eac57d9f5c..43f3137d6a 100644 --- a/src/soc/intel/common/block/include/intelblocks/cse.h +++ b/src/soc/intel/common/block/include/intelblocks/cse.h @@ -25,6 +25,9 @@ /* Get Firmware Version Command Id */ #define MKHI_GEN_GET_FW_VERSION 0x2 +/* Set End-of-POST in CSE */ +#define MKHI_END_OF_POST 0xc + /* 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 @@ -117,6 +120,9 @@ enum csme_failure_reason { /* CSE CBFS RW blob layout is not correct */ CSE_LITE_SKU_LAYOUT_MISMATCH_ERROR = 11, + + /* Error sending EOP to CSE */ + CSE_EOP_FAIL = 12, }; /* set up device for use in early boot enviroument with temp bar */ |