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