diff options
-rw-r--r-- | src/soc/amd/common/block/psp/Kconfig | 12 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/Makefile.inc | 2 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/psb.c | 159 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/psp_def.h | 3 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/psp_gen2.c | 2 |
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 */ |