/* SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include #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);