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