Arthur Heymans | ee55d71 | 2021-05-12 16:22:05 +0200 | [diff] [blame^] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include <arch/mmio.h> |
| 4 | #include <console/console.h> |
| 5 | #include <cpu/x86/msr.h> |
| 6 | #include <cpu/intel/msr.h> |
| 7 | #include <stdint.h> |
| 8 | #include <security/intel/txt/txt.h> |
| 9 | |
| 10 | #include "cbnt.h" |
| 11 | |
| 12 | #define LOG(...) printk(BIOS_INFO, "CBnT: " __VA_ARGS__) |
| 13 | |
| 14 | union sacm_info { |
| 15 | struct { |
| 16 | uint64_t nem_enabled : 1; |
| 17 | uint64_t tpm_type : 2; |
| 18 | uint64_t tpm_success : 1; |
| 19 | uint64_t facb : 1; |
| 20 | uint64_t measured_boot : 1; |
| 21 | uint64_t verified_boot : 1; |
| 22 | uint64_t revoked : 1; |
| 23 | uint64_t : 24; |
| 24 | uint64_t btg_cap : 1; |
| 25 | uint64_t : 1; |
| 26 | uint64_t txt_cap : 1; |
| 27 | uint64_t : 29; |
| 28 | }; |
| 29 | msr_t msr; |
| 30 | uint64_t raw; |
| 31 | }; |
| 32 | |
| 33 | _Static_assert(sizeof(union sacm_info) == sizeof(uint64_t), "Wrong size of sacm_info"); |
| 34 | |
| 35 | static const char *const tpm_type[] = { |
| 36 | "No TPM", |
| 37 | "TPM 1.2", |
| 38 | "TPM 2.0", |
| 39 | "PTT", |
| 40 | }; |
| 41 | |
| 42 | union cbnt_bootstatus { |
| 43 | struct { |
| 44 | uint64_t : 59; |
| 45 | uint64_t bios_trusted : 1; |
| 46 | uint64_t txt_dis_pol : 1; |
| 47 | uint64_t btg_startup_err : 1; |
| 48 | uint64_t txt_err : 1; |
| 49 | uint64_t type7 : 1; |
| 50 | }; |
| 51 | uint64_t raw; |
| 52 | }; |
| 53 | _Static_assert(sizeof(union cbnt_bootstatus) == sizeof(uint64_t), |
| 54 | "Wrong size of cbnt_bootstatus"); |
| 55 | |
| 56 | union cbnt_errorcode { |
| 57 | struct { |
| 58 | uint32_t type : 15; |
| 59 | uint32_t : 15; |
| 60 | uint32_t external : 1; |
| 61 | uint32_t valid : 1; |
| 62 | } microcode; |
| 63 | struct { |
| 64 | uint32_t ac_type : 4; |
| 65 | uint32_t class : 6; |
| 66 | uint32_t major : 5; |
| 67 | uint32_t minor_invalid : 1; |
| 68 | uint32_t minor : 9; |
| 69 | uint32_t : 5; |
| 70 | uint32_t external : 1; |
| 71 | uint32_t valid : 1; |
| 72 | } sinit; |
| 73 | uint32_t raw; |
| 74 | }; |
| 75 | |
| 76 | _Static_assert(sizeof(union cbnt_errorcode) == sizeof(uint32_t), |
| 77 | "Wrong size of cbnt_errorcode"); |
| 78 | |
| 79 | union cbnt_biosacm_errorcode { |
| 80 | struct { |
| 81 | uint32_t ac_type : 4; |
| 82 | uint32_t class : 6; |
| 83 | uint32_t major : 5; |
| 84 | uint32_t minor_invalid : 1; |
| 85 | uint32_t minor : 12; |
| 86 | uint32_t : 2; |
| 87 | uint32_t external : 1; |
| 88 | uint32_t valid : 1; |
| 89 | } txt; |
| 90 | struct { |
| 91 | uint32_t ac_type : 4; |
| 92 | uint32_t class : 6; |
| 93 | uint32_t error : 5; |
| 94 | uint32_t acm_started : 1; |
| 95 | uint32_t km_id : 4; |
| 96 | uint32_t bp : 5; |
| 97 | uint32_t : 6; |
| 98 | uint32_t valid : 1; |
| 99 | } btg; |
| 100 | uint32_t raw; |
| 101 | }; |
| 102 | _Static_assert(sizeof(union cbnt_biosacm_errorcode) == sizeof(uint32_t), |
| 103 | "Wrong size of cbnt_biosacm_errorcode"); |
| 104 | |
| 105 | |
| 106 | static const char *decode_err_type(uint8_t type) |
| 107 | { |
| 108 | switch (type) { |
| 109 | case 0: |
| 110 | return "BIOS ACM Error"; |
| 111 | case 1: |
| 112 | return "SINIT ACM Error"; |
| 113 | case 3: |
| 114 | return "Boot Guard Error"; |
| 115 | default: |
| 116 | return "Reserved"; |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | void intel_cbnt_log_registers(void) |
| 121 | { |
| 122 | const union sacm_info acm_info = { .msr = rdmsr(MSR_BOOT_GUARD_SACM_INFO) }; |
| 123 | LOG("SACM INFO MSR (0x13A) raw: 0x%016llx\n", acm_info.raw); |
| 124 | LOG(" NEM status: %ul\n", acm_info.nem_enabled); |
| 125 | LOG(" TPM type: %s\n", tpm_type[acm_info.tpm_type]); |
| 126 | LOG(" TPM succes: %ul\n", acm_info.tpm_success); |
| 127 | LOG(" FACB: %ul\n", acm_info.facb); |
| 128 | LOG(" measured boot: %ul\n", acm_info.measured_boot); |
| 129 | LOG(" verified boot: %ul\n", acm_info.verified_boot); |
| 130 | LOG(" revoked: %ul\n", acm_info.revoked); |
| 131 | LOG(" BtG capable: %ul\n", acm_info.btg_cap); |
| 132 | LOG(" TXT capable: %ul\n", acm_info.txt_cap); |
| 133 | |
| 134 | const union cbnt_bootstatus btsts = { |
| 135 | .raw = read64p(CBNT_BOOTSTATUS), |
| 136 | }; |
| 137 | LOG("BOOTSTATUS (0xA0) raw: 0x%016llx\n", btsts.raw); |
| 138 | LOG(" Bios trusted: %ul\n", btsts.bios_trusted); |
| 139 | LOG(" TXT disabled by policy: %ul\n", btsts.txt_dis_pol); |
| 140 | LOG(" Bootguard startup error: %ul\n", btsts.btg_startup_err); |
| 141 | LOG(" TXT ucode or ACM error: %ul\n", btsts.txt_err); |
| 142 | LOG(" TXT measurement type 7: %ul\n", btsts.type7); |
| 143 | |
| 144 | const union cbnt_errorcode err = { |
| 145 | .raw = read32p(CBNT_ERRORCODE), |
| 146 | }; |
| 147 | LOG("ERRORCODE (0x30) raw: 0x%08x\n", err.raw); |
| 148 | /* It looks like the hardware does not set the txt error bit properly */ |
| 149 | const bool txt_err_valid = btsts.txt_err || true; |
| 150 | if (txt_err_valid && !btsts.txt_dis_pol) { |
| 151 | if (err.microcode.valid && !err.microcode.external) { |
| 152 | LOG("ERRORCODE is ucode error\n"); |
| 153 | LOG(" type: %s\n", |
| 154 | intel_txt_processor_error_type(err.microcode.type)); |
| 155 | } else if (err.sinit.valid && err.sinit.external) { |
| 156 | LOG("ERRORCODE is SINIT error\n"); |
| 157 | const char *type = decode_err_type(err.sinit.ac_type); |
| 158 | LOG(" AC Module Type: %s\n", type); |
| 159 | LOG(" class: 0x%x\n", err.sinit.class); |
| 160 | LOG(" major: 0x%x\n", err.sinit.major); |
| 161 | if (!err.sinit.minor_invalid) |
| 162 | LOG(" minor: 0x%x\n", err.sinit.minor); |
| 163 | } |
| 164 | } else if (txt_err_valid && btsts.txt_dis_pol) { |
| 165 | LOG("TXT disabled in Policy\n"); |
| 166 | } |
| 167 | |
| 168 | const union cbnt_biosacm_errorcode biosacm_err = { |
| 169 | .raw = read32p(CBNT_BIOSACM_ERRORCODE), |
| 170 | }; |
| 171 | LOG("BIOSACM_ERRORCODE (0x328) raw: 0x%08x\n", biosacm_err.raw); |
| 172 | if (txt_err_valid && biosacm_err.txt.valid) { |
| 173 | LOG("BIOSACM_ERRORCODE: TXT ucode or ACM error\n"); |
| 174 | const char *type = decode_err_type(biosacm_err.txt.ac_type); |
| 175 | LOG(" AC Module Type: %s\n", type); |
| 176 | LOG(" class: 0x%x\n", biosacm_err.txt.class); |
| 177 | LOG(" major: 0x%x\n", biosacm_err.txt.major); |
| 178 | if (!biosacm_err.txt.minor_invalid) |
| 179 | LOG(" minor: 0x%x\n", biosacm_err.txt.minor); |
| 180 | LOG(" External: 0x%x\n", biosacm_err.txt.external); |
| 181 | } |
| 182 | |
| 183 | if (btsts.btg_startup_err && biosacm_err.btg.valid) { |
| 184 | LOG("BIOSACM_ERRORCODE: Bootguard error\n"); |
| 185 | const char *type = decode_err_type(biosacm_err.btg.ac_type); |
| 186 | LOG(" AC Module Type: %s\n", type); |
| 187 | LOG(" class: 0x%x\n", biosacm_err.btg.class); |
| 188 | LOG(" error: 0x%x\n", biosacm_err.btg.error); |
| 189 | LOG(" ACM started: %u\n", biosacm_err.btg.acm_started); |
| 190 | LOG(" KMID: 0x%x\n", biosacm_err.btg.km_id); |
| 191 | LOG(" BootPolicies: 0x%x\n", biosacm_err.btg.bp); |
| 192 | } |
| 193 | } |