summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/amd/common/block/psp/Kconfig12
-rw-r--r--src/soc/amd/common/block/psp/Makefile.inc2
-rw-r--r--src/soc/amd/common/block/psp/psb.c159
-rw-r--r--src/soc/amd/common/block/psp/psp_def.h3
-rw-r--r--src/soc/amd/common/block/psp/psp_gen2.c2
5 files changed, 176 insertions, 2 deletions
diff --git a/src/soc/amd/common/block/psp/Kconfig b/src/soc/amd/common/block/psp/Kconfig
index 22ebb6803b..aa638b8911 100644
--- a/src/soc/amd/common/block/psp/Kconfig
+++ b/src/soc/amd/common/block/psp/Kconfig
@@ -44,3 +44,15 @@ config SOC_AMD_COMMON_BLOCK_PSP_FUSE_SPL
help
Enable sending of set SPL message to PSP. Enable this option if the platform
will require SPL fusing to be performed by PSP.
+
+config PSP_PLATFORM_SECURE_BOOT
+ bool "Platform secure boot enable"
+ depends on SOC_AMD_COMMON_BLOCK_PSP_GEN2
+ default n
+ help
+ Select this config to enable PSP Platform Secure Boot.
+
+ Platform Secure Boot will automatically be fused on boot if the
+ coreboot ROM is properly signed and can not be disabled once fused.
+ Refer AMD PSB user guide doc# 56654, Revision# 1.00, this document is
+ only available with NDA customers.
diff --git a/src/soc/amd/common/block/psp/Makefile.inc b/src/soc/amd/common/block/psp/Makefile.inc
index 4efaf0f2a5..41f6ee2521 100644
--- a/src/soc/amd/common/block/psp/Makefile.inc
+++ b/src/soc/amd/common/block/psp/Makefile.inc
@@ -27,6 +27,8 @@ ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN2),y)
romstage-y += psp_gen2.c
ramstage-y += psp_gen2.c
+ramstage-$(CONFIG_PSP_PLATFORM_SECURE_BOOT) += psb.c
+
smm-y += psp_gen2.c
smm-y += psp_smm_gen2.c
diff --git a/src/soc/amd/common/block/psp/psb.c b/src/soc/amd/common/block/psp/psb.c
new file mode 100644
index 0000000000..57b5bbd55b
--- /dev/null
+++ b/src/soc/amd/common/block/psp/psb.c
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/mmio.h>
+#include <bootstate.h>
+#include <amdblocks/reset.h>
+#include <console/console.h>
+#include <cpu/amd/msr.h>
+#include <types.h>
+#include "psp_def.h"
+
+#define PSB_STATUS_OFFSET 0x10994
+
+#define FUSE_PLATFORM_SECURE_BOOT_EN BIT(24)
+
+#define PSB_TEST_STATUS_MASK 0xff
+#define PSB_FUSING_READY_MASK BIT(8)
+
+/* PSB Test Status and Error Codes (doc#56654) */
+#define PSB_TEST_STATUS_PASS 0x00
+#define PSB_TEST_STATUS_FUSE_READ_ERR 0x3e
+#define PSB_TEST_STATUS_BIOS_KEY_BAD_USAGE 0x81
+#define PSB_TEST_STATUS_BIOS_RTM_SIG_NOENT 0x82
+#define PSB_TEST_STATUS_BIOS_RTM_COPY_ERR 0x83
+#define PSB_TEST_STATUS_BIOS_RTM_BAD_SIG 0x84
+#define PSB_TEST_STATUS_BIOS_KEY_BAD_SIG 0x85
+#define PSB_TEST_STATUS_PLATFORM_BAD_ID 0x86
+#define PSB_TEST_STATUS_BIOS_COPY_BIT_UNSET 0x87
+#define PSB_TEST_STATUS_BIOS_CA_BAD_SIG 0x8a
+#define PSB_TEST_STATUS_BIOS_CA_BAD_USAGE 0x8b
+#define PSB_TEST_STATUS_BIOS_KEY_BAD_REVISION 0x8c
+
+#define FUSE_STATUS_SUCCESS 0x00
+#define FUSE_STATUS_NOT_ALLOWED 0x09
+#define FUSE_STATUS_FUSING_ERR 0x0a
+#define FUSE_STATUS_BOOT_DONE 0x0b
+
+static const char *psb_test_status_to_string(u32 status)
+{
+ switch (status) {
+ case PSB_TEST_STATUS_PASS:
+ return "Psb Test Status PASS";
+ case PSB_TEST_STATUS_FUSE_READ_ERR:
+ return "Error reading fuse info";
+ case PSB_TEST_STATUS_BIOS_KEY_BAD_USAGE:
+ return "OEM BIOS signing key usage flag violation";
+ case PSB_TEST_STATUS_BIOS_RTM_SIG_NOENT:
+ return "BIOS RTM signature entry not found";
+ case PSB_TEST_STATUS_BIOS_RTM_COPY_ERR:
+ return "BIOS copy to DRAM failed";
+ case PSB_TEST_STATUS_BIOS_RTM_BAD_SIG:
+ return "BIOS RTM signature verification failed";
+ case PSB_TEST_STATUS_BIOS_KEY_BAD_SIG:
+ return "OEM BIOS signing key failed signature verification";
+ case PSB_TEST_STATUS_PLATFORM_BAD_ID:
+ return "Platform vendor id and/or model id binding violation";
+ case PSB_TEST_STATUS_BIOS_COPY_BIT_UNSET:
+ return "BIOS copy bit unset for reset image";
+ case PSB_TEST_STATUS_BIOS_CA_BAD_SIG:
+ return "OEM BIOS signing CA key failed signature verification";
+ case PSB_TEST_STATUS_BIOS_CA_BAD_USAGE:
+ return "OEM BIOS signing CA key usage flag violation";
+ case PSB_TEST_STATUS_BIOS_KEY_BAD_REVISION:
+ return "OEM BIOS signing key revision violation";
+ default:
+ return "Unknown failure";
+ }
+}
+
+static const char *fuse_status_to_string(u32 status)
+{
+ switch (status) {
+ case FUSE_STATUS_SUCCESS:
+ return "PSB Fusing completed successfully";
+ case FUSE_STATUS_NOT_ALLOWED:
+ return "Fusing not allowed or already done";
+ case FUSE_STATUS_FUSING_ERR:
+ return "Fuse programming failed";
+ case FUSE_STATUS_BOOT_DONE:
+ return "Issued after BOOT DONE";
+ default:
+ return "Unknown failure";
+ }
+}
+
+static uint32_t get_psb_status(void)
+{
+ return smn_read32(SMN_PSP_PUBLIC_BASE + PSB_STATUS_OFFSET);
+}
+
+/*
+ * Request Platform Secure Boot enablement via the PSP if it is not already
+ * enabled. Upon receiving this command, the PSP will program all PSB fuses
+ * so long as the BIOS signing key token is valid.
+ */
+static enum cb_err psb_enable(void)
+{
+ u32 status;
+ struct mbox_default_buffer buffer = {
+ .header = {
+ .size = sizeof(buffer)
+ }
+ };
+
+ status = get_psb_status();
+ printk(BIOS_INFO, "PSB: Status = %x\n", status);
+
+ if (status & FUSE_PLATFORM_SECURE_BOOT_EN) {
+ printk(BIOS_DEBUG, "PSB: Already enabled\n");
+ return CB_SUCCESS;
+ }
+
+ status = soc_read_c2p38();
+ printk(BIOS_INFO, "PSB: HSTI = %x\n", status);
+
+ const u32 psb_test_status = status & PSB_TEST_STATUS_MASK;
+
+ if (psb_test_status != PSB_TEST_STATUS_PASS) {
+ printk(BIOS_ERR, "PSB: %s\n", psb_test_status_to_string(psb_test_status));
+ return CB_ERR;
+ }
+
+ if (!(status & PSB_FUSING_READY_MASK)) {
+ printk(BIOS_ERR, "PSB: Fusing not allowed\n");
+ return CB_ERR;
+ }
+
+ printk(BIOS_DEBUG, "PSB: Enable... ");
+
+ const int cmd_status = send_psp_command(MBOX_BIOS_CMD_PSB_AUTO_FUSING, &buffer);
+
+ psp_print_cmd_status(cmd_status, &buffer.header);
+
+ if (cmd_status) {
+ printk(BIOS_ERR, "PSB: Fusing request failed: %d\n", cmd_status);
+ return CB_ERR;
+ }
+
+ const u32 fuse_status = read32(&buffer.header.status);
+ if (fuse_status != FUSE_STATUS_SUCCESS) {
+ printk(BIOS_ERR, "PSB: %s\n", fuse_status_to_string(fuse_status));
+ return CB_ERR;
+ }
+
+ printk(BIOS_NOTICE, "PSB: Rebooting\n");
+ cold_reset();
+}
+
+static void enable_secure_boot(void *unused)
+{
+ /*
+ * Enable secure boot before loading payload. Psb fusing is done late in
+ * boot process to avoid any fuse access conflicts with other components
+ * which happens during boot process.
+ */
+ if (psb_enable() == CB_ERR)
+ printk(BIOS_NOTICE, "Enabling PSB failed.\n");
+}
+
+BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_ENTRY, enable_secure_boot, NULL);
diff --git a/src/soc/amd/common/block/psp/psp_def.h b/src/soc/amd/common/block/psp/psp_def.h
index d1a06fbce8..6dcf5b48dc 100644
--- a/src/soc/amd/common/block/psp/psp_def.h
+++ b/src/soc/amd/common/block/psp/psp_def.h
@@ -17,6 +17,7 @@
#define MBOX_BIOS_CMD_CLEAR_S3_STS 0x07
#define MBOX_BIOS_CMD_S3_DATA_INFO 0x08
#define MBOX_BIOS_CMD_NOP 0x09
+#define MBOX_BIOS_CMD_PSB_AUTO_FUSING 0x21
#define MBOX_BIOS_CMD_SET_SPL_FUSE 0x2d
#define MBOX_BIOS_CMD_QUERY_SPL_FUSE 0x47
#define MBOX_BIOS_CMD_ABORT 0xfe
@@ -26,6 +27,8 @@
#define MBOX_BIOS_CMD_SMU_FW 0x19
#define MBOX_BIOS_CMD_SMU_FW2 0x1a
+#define SMN_PSP_PUBLIC_BASE 0x3800000
+
/* command/response format, BIOS builds this in memory
* mbox_buffer_header: generic header
* mbox_buffer: command-specific buffer format
diff --git a/src/soc/amd/common/block/psp/psp_gen2.c b/src/soc/amd/common/block/psp/psp_gen2.c
index 208a9bfca4..1b4918228c 100644
--- a/src/soc/amd/common/block/psp/psp_gen2.c
+++ b/src/soc/amd/common/block/psp/psp_gen2.c
@@ -7,8 +7,6 @@
#include <amdblocks/smn.h>
#include "psp_def.h"
-#define SMN_PSP_PUBLIC_BASE 0x3800000
-
#define PSP_MAILBOX_COMMAND_OFFSET 0x10570 /* 4 bytes */
#define PSP_MAILBOX_BUFFER_L_OFFSET 0x10574 /* 4 bytes */
#define PSP_MAILBOX_BUFFER_H_OFFSET 0x10578 /* 4 bytes */