diff options
Diffstat (limited to 'src/soc/amd/common/block/psp/psb.c')
-rw-r--r-- | src/soc/amd/common/block/psp/psb.c | 159 |
1 files changed, 159 insertions, 0 deletions
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); |