Ritul Guru | 8da3804 | 2022-01-10 18:44:24 +0530 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include <arch/mmio.h> |
| 4 | #include <bootstate.h> |
| 5 | #include <amdblocks/reset.h> |
Felix Held | 2badaa5 | 2022-08-19 16:57:20 +0200 | [diff] [blame^] | 6 | #include <amdblocks/smn.h> |
Ritul Guru | 8da3804 | 2022-01-10 18:44:24 +0530 | [diff] [blame] | 7 | #include <console/console.h> |
| 8 | #include <cpu/amd/msr.h> |
| 9 | #include <types.h> |
| 10 | #include "psp_def.h" |
| 11 | |
| 12 | #define PSB_STATUS_OFFSET 0x10994 |
| 13 | |
| 14 | #define FUSE_PLATFORM_SECURE_BOOT_EN BIT(24) |
| 15 | |
| 16 | #define PSB_TEST_STATUS_MASK 0xff |
| 17 | #define PSB_FUSING_READY_MASK BIT(8) |
| 18 | |
| 19 | /* PSB Test Status and Error Codes (doc#56654) */ |
| 20 | #define PSB_TEST_STATUS_PASS 0x00 |
| 21 | #define PSB_TEST_STATUS_FUSE_READ_ERR 0x3e |
| 22 | #define PSB_TEST_STATUS_BIOS_KEY_BAD_USAGE 0x81 |
| 23 | #define PSB_TEST_STATUS_BIOS_RTM_SIG_NOENT 0x82 |
| 24 | #define PSB_TEST_STATUS_BIOS_RTM_COPY_ERR 0x83 |
| 25 | #define PSB_TEST_STATUS_BIOS_RTM_BAD_SIG 0x84 |
| 26 | #define PSB_TEST_STATUS_BIOS_KEY_BAD_SIG 0x85 |
| 27 | #define PSB_TEST_STATUS_PLATFORM_BAD_ID 0x86 |
| 28 | #define PSB_TEST_STATUS_BIOS_COPY_BIT_UNSET 0x87 |
| 29 | #define PSB_TEST_STATUS_BIOS_CA_BAD_SIG 0x8a |
| 30 | #define PSB_TEST_STATUS_BIOS_CA_BAD_USAGE 0x8b |
| 31 | #define PSB_TEST_STATUS_BIOS_KEY_BAD_REVISION 0x8c |
| 32 | |
| 33 | #define FUSE_STATUS_SUCCESS 0x00 |
| 34 | #define FUSE_STATUS_NOT_ALLOWED 0x09 |
| 35 | #define FUSE_STATUS_FUSING_ERR 0x0a |
| 36 | #define FUSE_STATUS_BOOT_DONE 0x0b |
| 37 | |
| 38 | static const char *psb_test_status_to_string(u32 status) |
| 39 | { |
| 40 | switch (status) { |
| 41 | case PSB_TEST_STATUS_PASS: |
| 42 | return "Psb Test Status PASS"; |
| 43 | case PSB_TEST_STATUS_FUSE_READ_ERR: |
| 44 | return "Error reading fuse info"; |
| 45 | case PSB_TEST_STATUS_BIOS_KEY_BAD_USAGE: |
| 46 | return "OEM BIOS signing key usage flag violation"; |
| 47 | case PSB_TEST_STATUS_BIOS_RTM_SIG_NOENT: |
| 48 | return "BIOS RTM signature entry not found"; |
| 49 | case PSB_TEST_STATUS_BIOS_RTM_COPY_ERR: |
| 50 | return "BIOS copy to DRAM failed"; |
| 51 | case PSB_TEST_STATUS_BIOS_RTM_BAD_SIG: |
| 52 | return "BIOS RTM signature verification failed"; |
| 53 | case PSB_TEST_STATUS_BIOS_KEY_BAD_SIG: |
| 54 | return "OEM BIOS signing key failed signature verification"; |
| 55 | case PSB_TEST_STATUS_PLATFORM_BAD_ID: |
| 56 | return "Platform vendor id and/or model id binding violation"; |
| 57 | case PSB_TEST_STATUS_BIOS_COPY_BIT_UNSET: |
| 58 | return "BIOS copy bit unset for reset image"; |
| 59 | case PSB_TEST_STATUS_BIOS_CA_BAD_SIG: |
| 60 | return "OEM BIOS signing CA key failed signature verification"; |
| 61 | case PSB_TEST_STATUS_BIOS_CA_BAD_USAGE: |
| 62 | return "OEM BIOS signing CA key usage flag violation"; |
| 63 | case PSB_TEST_STATUS_BIOS_KEY_BAD_REVISION: |
| 64 | return "OEM BIOS signing key revision violation"; |
| 65 | default: |
| 66 | return "Unknown failure"; |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | static const char *fuse_status_to_string(u32 status) |
| 71 | { |
| 72 | switch (status) { |
| 73 | case FUSE_STATUS_SUCCESS: |
| 74 | return "PSB Fusing completed successfully"; |
| 75 | case FUSE_STATUS_NOT_ALLOWED: |
| 76 | return "Fusing not allowed or already done"; |
| 77 | case FUSE_STATUS_FUSING_ERR: |
| 78 | return "Fuse programming failed"; |
| 79 | case FUSE_STATUS_BOOT_DONE: |
| 80 | return "Issued after BOOT DONE"; |
| 81 | default: |
| 82 | return "Unknown failure"; |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | static uint32_t get_psb_status(void) |
| 87 | { |
| 88 | return smn_read32(SMN_PSP_PUBLIC_BASE + PSB_STATUS_OFFSET); |
| 89 | } |
| 90 | |
| 91 | /* |
| 92 | * Request Platform Secure Boot enablement via the PSP if it is not already |
| 93 | * enabled. Upon receiving this command, the PSP will program all PSB fuses |
| 94 | * so long as the BIOS signing key token is valid. |
| 95 | */ |
| 96 | static enum cb_err psb_enable(void) |
| 97 | { |
| 98 | u32 status; |
| 99 | struct mbox_default_buffer buffer = { |
| 100 | .header = { |
| 101 | .size = sizeof(buffer) |
| 102 | } |
| 103 | }; |
| 104 | |
| 105 | status = get_psb_status(); |
| 106 | printk(BIOS_INFO, "PSB: Status = %x\n", status); |
| 107 | |
| 108 | if (status & FUSE_PLATFORM_SECURE_BOOT_EN) { |
| 109 | printk(BIOS_DEBUG, "PSB: Already enabled\n"); |
| 110 | return CB_SUCCESS; |
| 111 | } |
| 112 | |
| 113 | status = soc_read_c2p38(); |
| 114 | printk(BIOS_INFO, "PSB: HSTI = %x\n", status); |
| 115 | |
| 116 | const u32 psb_test_status = status & PSB_TEST_STATUS_MASK; |
| 117 | |
| 118 | if (psb_test_status != PSB_TEST_STATUS_PASS) { |
| 119 | printk(BIOS_ERR, "PSB: %s\n", psb_test_status_to_string(psb_test_status)); |
| 120 | return CB_ERR; |
| 121 | } |
| 122 | |
| 123 | if (!(status & PSB_FUSING_READY_MASK)) { |
| 124 | printk(BIOS_ERR, "PSB: Fusing not allowed\n"); |
| 125 | return CB_ERR; |
| 126 | } |
| 127 | |
| 128 | printk(BIOS_DEBUG, "PSB: Enable... "); |
| 129 | |
| 130 | const int cmd_status = send_psp_command(MBOX_BIOS_CMD_PSB_AUTO_FUSING, &buffer); |
| 131 | |
| 132 | psp_print_cmd_status(cmd_status, &buffer.header); |
| 133 | |
| 134 | if (cmd_status) { |
| 135 | printk(BIOS_ERR, "PSB: Fusing request failed: %d\n", cmd_status); |
| 136 | return CB_ERR; |
| 137 | } |
| 138 | |
| 139 | const u32 fuse_status = read32(&buffer.header.status); |
| 140 | if (fuse_status != FUSE_STATUS_SUCCESS) { |
| 141 | printk(BIOS_ERR, "PSB: %s\n", fuse_status_to_string(fuse_status)); |
| 142 | return CB_ERR; |
| 143 | } |
| 144 | |
| 145 | printk(BIOS_NOTICE, "PSB: Rebooting\n"); |
| 146 | cold_reset(); |
| 147 | } |
| 148 | |
| 149 | static void enable_secure_boot(void *unused) |
| 150 | { |
| 151 | /* |
| 152 | * Enable secure boot before loading payload. Psb fusing is done late in |
| 153 | * boot process to avoid any fuse access conflicts with other components |
| 154 | * which happens during boot process. |
| 155 | */ |
| 156 | if (psb_enable() == CB_ERR) |
| 157 | printk(BIOS_NOTICE, "Enabling PSB failed.\n"); |
| 158 | } |
| 159 | |
| 160 | BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_ENTRY, enable_secure_boot, NULL); |