<p>frank vibrans has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/21993">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">(WIP) soc/amd/common: Add PSP-to-BIOS mailbox<br><br>Add PSP-to-BIOS mailbox communications path. It is characterized and<br>enabled by the config value "HAVE_PSP2C_MBOX". It is initialized<br>via the SMI command port with the value APM_CNT_PSP_SMM_INIT. This<br>communications path allows the PSP to request services from the BIOS.<br>The request comes to the BIOS via an SMI and a data block located in<br>SMM space that the PSP can access.<br><br>TODO: Change the initialization mechanism to use the command<br>APM_CNT_GNVS_UPDATE that is not currently in place, and implement the<br>services available to the PSP.<br><br>Change-Id: I8e174b277cab45bf5e386425042e542cfef817e9<br>Signed-off-by: Frank Vibrans <frank.vibrans@scarletltd.com><br>---<br>M src/soc/amd/common/block/include/amdblocks/psp.h<br>M src/soc/amd/common/block/psp/Kconfig<br>M src/soc/amd/common/block/psp/Makefile.inc<br>A src/soc/amd/common/block/psp/p2cmbox.c<br>M src/soc/amd/common/block/psp/psp.c<br>5 files changed, 215 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/93/21993/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/src/soc/amd/common/block/include/amdblocks/psp.h b/src/soc/amd/common/block/include/amdblocks/psp.h<br>index 7915b1f..8d731d6 100644<br>--- a/src/soc/amd/common/block/include/amdblocks/psp.h<br>+++ b/src/soc/amd/common/block/include/amdblocks/psp.h<br>@@ -31,6 +31,16 @@<br> #define MBOX_BIOS_CMD_NOP 0x09<br> #define MBOX_BIOS_CMD_ABORT 0xfe<br> <br>+/* Definitions for MboxBiosCmdSmmInfo buffer - command 0x2 */<br>+#define PSP_SMMINFO_TYPE_IO 0<br>+#define PSP_SMMINFO_TYPE_MMIO 1<br>+#define PSP_SMMINFO_TYPE_PCI 2<br>+<br>+#define PSP_SMMINFO_WIDTH_BYTE 0<br>+#define PSP_SMMINFO_WIDTH_WORD 1<br>+#define PSP_SMMINFO_WIDTH_DWORD 2<br>+#define PSP_SMMINFO_WIDTH_QWORD 3<br>+<br> /* generic PSP interface status */<br> #define STATUS_INITIALIZED 0x1<br> #define STATUS_ERROR 0x2<br>@@ -91,6 +101,21 @@<br> struct smm_req_buffer req;<br> } __attribute__((packed));<br> <br>+/* PSP-to-BIOS form of the mailbox. This differs from the BIOS-to-PSP form<br>+ * because the command/response buffer occurs at a fixed location in the<br>+ * mailbox data space (offset 8) rather than somewhere in the stack.<br>+ */<br>+struct p2c_cmd_resp {<br>+ struct mbox_buffer_header hdr;<br>+ u64 cmd_buf[1]; /* Placeholder for rest of P2C data space */<br>+} __packed;<br>+<br>+struct p2c_mbox {<br>+ u32 p2c_command;<br>+ u32 p2c_status;<br>+ struct p2c_cmd_resp response;<br>+} __packed;<br>+<br> /* send_psp_command() error codes */<br> #define PSPSTS_SUCCESS 0<br> #define PSPSTS_NOBASE 1<br>@@ -99,6 +124,21 @@<br> #define PSPSTS_SEND_ERROR 4<br> #define PSPSTS_INIT_TIMEOUT 5<br> #define PSPSTS_CMD_TIMEOUT 6<br>+<br>+/* Size of PSP data space located in SMM space */<br>+#define PSP_SMM_DATA_BLK_SIZE (4 * 1024)<br>+<br>+/* PSP to BIOS commands */<br>+#define PSP_GET_ATTRIBUTE 0x81<br>+#define PSP_SET_ATTRIBUTE 0x82 /* Not currently supported */<br>+#define PSP_GET_BLOCKSIZE 0x83<br>+#define PSP_READ_FW_VOLUME 0x84<br>+#define PSP_WRITE_FW_VOLUME 0x85<br>+#define PSP_ERASE_FW_VOLUME 0x86<br>+<br>+/* PSP to BIOS status bits */<br>+#define PSP_CMD_STATUS_CMD_READY (1 << 31)<br>+#define PSP_CMD_STATUS_CHKSUM_ENABLE (1 << 8)<br> <br> #if !defined(__SIMPLE_DEVICE__)<br> #include <device/device.h><br>@@ -138,4 +178,11 @@<br> int psp_notify_smm_info(uintptr_t base, size_t length, uintptr_t psp_data_base,<br> size_t psp_data_length, struct smm_trigger_info *smm_trig_info);<br> <br>+/* TODO: Replace this with APM_CNT_GNVS_UPDATE */<br>+#define APM_CNT_PSP_SMM_INIT 0xd8<br>+<br>+/* PSP-to-BIOS related functions that run in SMM */<br>+void psp_smm_init(void);<br>+void psp_p2cmbox_event(void);<br>+<br> #endif /* __AMD_PSP_H__ */<br>diff --git a/src/soc/amd/common/block/psp/Kconfig b/src/soc/amd/common/block/psp/Kconfig<br>index 69958f2..db58683 100644<br>--- a/src/soc/amd/common/block/psp/Kconfig<br>+++ b/src/soc/amd/common/block/psp/Kconfig<br>@@ -4,3 +4,10 @@<br> help<br> This option builds in the Platform Security Processor initialization<br> functions.<br>+<br>+config HAVE_PSP2C_MBOX<br>+ bool<br>+ default n<br>+ help<br>+ This option builds in the PSP to BIOS mailbox functions needed for<br>+ PSP fTPM support.<br>diff --git a/src/soc/amd/common/block/psp/Makefile.inc b/src/soc/amd/common/block/psp/Makefile.inc<br>index b4f3b8d..1683e58 100644<br>--- a/src/soc/amd/common/block/psp/Makefile.inc<br>+++ b/src/soc/amd/common/block/psp/Makefile.inc<br>@@ -1,3 +1,4 @@<br> romstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP) += psp.c<br> ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP) += psp.c<br> smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP) += psp.c<br>+smm-$(CONFIG_HAVE_PSP2C_MBOX) += p2cmbox.c<br>diff --git a/src/soc/amd/common/block/psp/p2cmbox.c b/src/soc/amd/common/block/psp/p2cmbox.c<br>new file mode 100644<br>index 0000000..d9e49c9<br>--- /dev/null<br>+++ b/src/soc/amd/common/block/psp/p2cmbox.c<br>@@ -0,0 +1,147 @@<br>+/*<br>+ * This file is part of the coreboot project.<br>+ *<br>+ * Copyright (C) 2017 Advanced Micro Devices, Inc.<br>+ *<br>+ * This program is free software; you can redistribute it and/or modify<br>+ * it under the terms of the GNU General Public License as published by<br>+ * the Free Software Foundation; version 2 of the License.<br>+ *<br>+ * This program is distributed in the hope that it will be useful,<br>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>+ * GNU General Public License for more details.<br>+ */<br>+<br>+#include <stddef.h><br>+#include <arch/io.h><br>+#include <console/console.h><br>+#include <cpu/x86/msr.h><br>+#include <cpu/amd/amdfam15.h><br>+#include <amdblocks/psp.h><br>+#include <soc/southbridge.h><br>+#include <soc/smi.h><br>+<br>+/* PSP uses psp_p2c_data as the PSP mailbox and command/response buffer<br>+ * for PSP-to-BIOS communications.<br>+ */<br>+uint8_t __attribute__ ((aligned (32))) psp_p2c_data[PSP_SMM_DATA_BLK_SIZE];<br>+<br>+static uint32_t get_p2c_command(struct p2c_mbox *mbox)<br>+{<br>+ return read32((uint32_t *)mbox->p2c_command);<br>+}<br>+<br>+static uint32_t get_p2c_cmdlen(struct p2c_mbox *mbox)<br>+{<br>+ return read32((uint32_t *)mbox->response.hdr.size);<br>+}<br>+<br>+static uint32_t get_p2c_status(struct p2c_mbox *mbox)<br>+{<br>+ return read32((uint32_t *)mbox->p2c_status);<br>+}<br>+<br>+static void set_p2c_status(struct p2c_mbox *mbox, uint32_t new_status)<br>+{<br>+ uint32_t status = read32((uint32_t *)mbox->p2c_status);<br>+ status |= new_status;<br>+ write32((uint32_t *)mbox->p2c_status,status);<br>+}<br>+<br>+static bool test_checksum(void *start, size_t len)<br>+{<br>+ uint8_t test_sum = 0;<br>+ uint8_t *tptr = start;<br>+ int i;<br>+<br>+ for (i = 0; i < len; i++) {<br>+ test_sum += read8(tptr + i);<br>+ };<br>+<br>+ return test_sum != 0;<br>+}<br>+<br>+void psp_p2cmbox_event(void)<br>+{<br>+ struct p2c_mbox *psp_p2c_mbox = (struct p2c_mbox *)&psp_p2c_data;<br>+<br>+ /* Check if a command is ready */<br>+ uint32_t cmd_status = get_p2c_status(psp_p2c_mbox);<br>+ if (!(cmd_status & PSP_CMD_STATUS_CMD_READY)) {<br>+ printk(BIOS_ERR, "PSP: Command not ready in SMI. ");<br>+ return;<br>+ }<br>+<br>+ /* Test checksum if necessary */<br>+ if (cmd_status & PSP_CMD_STATUS_CHKSUM_ENABLE) {<br>+ uint32_t length = get_p2c_cmdlen(psp_p2c_mbox);<br>+ if (test_checksum(psp_p2c_mbox, length)) {<br>+ printk(BIOS_ERR, "PSP: Checksum failure. ");<br>+ return;<br>+ }<br>+ };<br>+<br>+ uint32_t psp_cmd = get_p2c_command(psp_p2c_mbox);<br>+ /* TODO: Fill out this skeleton to provide the functionality suggested<br>+ * here.<br>+ */<br>+ switch (psp_cmd) {<br>+ case PSP_GET_ATTRIBUTE:<br>+ break;<br>+ case PSP_GET_BLOCKSIZE:<br>+ break;<br>+ case PSP_READ_FW_VOLUME:<br>+ break;<br>+ case PSP_WRITE_FW_VOLUME:<br>+ break;<br>+ case PSP_ERASE_FW_VOLUME:<br>+ break;<br>+ case PSP_SET_ATTRIBUTE: /* Not currently supported by PSP */<br>+ default:<br>+ break;<br>+ }<br>+}<br>+<br>+static void psp_p2cmbox_init(void)<br>+{<br>+ struct smm_trigger_info trig_info;<br>+<br>+ /* Have FakeSMI0 generate an SMI with status routed to SmiStatus4 */<br>+ configure_smi(SMITYPE_FAKE0, SMI_MODE_SMI);<br>+<br>+ /* Determine MBoxBiosCmdSmmInfo message parameters */<br>+ /* SMI trigger information */<br>+ trig_info.address = (uintptr_t)(APU_SMI_BASE + SMI_REG_SMITRIG0);<br>+ trig_info.address_type = PSP_SMMINFO_TYPE_MMIO;<br>+ trig_info.value_width = PSP_SMMINFO_WIDTH_DWORD;<br>+ trig_info.value_and_mask = ~SMITRG0_FAKE0;<br>+ trig_info.value_or_mask = SMITRG0_FAKE0;<br>+<br>+ /* TSEG information */<br>+ msr_t msr = rdmsr(MSR_TSEG_BASE);<br>+ uintptr_t tseg_base = ((uint64_t)msr.hi << 32) | (uint64_t)msr.lo;<br>+ msr = rdmsr(MSR_SMM_MASK);<br>+ /* Ignore mask bits 32-47 because a TSEG > 4GB is not likely. */<br>+ size_t tseg_length = ~msr.lo + 1;<br>+<br>+ /* PSP SMM data buffer information */<br>+ uintptr_t psp_data_base = (uintptr_t)&psp_p2c_data;<br>+ size_t psp_data_length = PSP_SMM_DATA_BLK_SIZE;<br>+<br>+ /* Send the MBoxBiosCmdSmmInfo command to the PSP. Failure is<br>+ * announced by printk in psp_notify_smm_info function.<br>+ */<br>+ if (psp_notify_smm_info(tseg_base, tseg_length, psp_data_base,<br>+ psp_data_length, (struct smm_trigger_info *)&trig_info))<br>+ return;<br>+<br>+ /* Tell the PSP the mailbox is initialized */<br>+ struct p2c_mbox *psp_p2c_mbox = (struct p2c_mbox *)&psp_p2c_data;<br>+ set_p2c_status(psp_p2c_mbox, STATUS_INITIALIZED);<br>+}<br>+<br>+void psp_smm_init(void)<br>+{<br>+ psp_p2cmbox_init();<br>+}<br>diff --git a/src/soc/amd/common/block/psp/psp.c b/src/soc/amd/common/block/psp/psp.c<br>index 5bbdf41..aa58030 100644<br>--- a/src/soc/amd/common/block/psp/psp.c<br>+++ b/src/soc/amd/common/block/psp/psp.c<br>@@ -16,10 +16,12 @@<br> #include <stddef.h><br> #include <types.h><br> #include <arch/io.h><br>+#include <bootstate.h><br> #include <timer.h><br> #include <cpu/x86/msr.h><br> #include <device/pci_def.h><br> #include <console/console.h><br>+#include <soc/smi.h><br> #include <amdblocks/psp.h><br> #if !ENV_SMM<br> # include <Porting.h><br>@@ -259,3 +261,14 @@<br> <br> return cmd_status;<br> }<br>+<br>+#if IS_ENABLED(CONFIG_HAVE_PSP2C_MBOX)<br>+static void psp_smm_initialize(void *unused)<br>+{<br>+ /* TODO: Replace APM_CNT_PSP_SMM_INIT with APM_CNT_GNVS_UPDATE */<br>+ /* Trigger SMI that starts PSP SMM initialization */<br>+ outb(APM_CNT_PSP_SMM_INIT, pm_acpi_smi_cmd_port());<br>+}<br>+<br>+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, psp_smm_initialize, NULL);<br>+#endif<br></pre><p>To view, visit <a href="https://review.coreboot.org/21993">change 21993</a>. To unsubscribe, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/21993"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I8e174b277cab45bf5e386425042e542cfef817e9 </div>
<div style="display:none"> Gerrit-Change-Number: 21993 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: frank vibrans <frank.vibrans@scarletltd.com> </div>