blob: 46c594cb056479c8e362190cc3d1e62dedfaca2a [file] [log] [blame]
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01003#include <arch/mmio.h>
Angel Pons52082be2020-10-05 12:34:29 +02004#include <console/console.h>
Angel Pons11334722020-10-05 16:34:03 +02005#include <cpu/x86/smm.h>
Angel Pons52082be2020-10-05 12:34:29 +02006#include <types.h>
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01007
8#include "txt.h"
Michał Żygowski7480e872021-11-21 12:47:14 +01009#include "txt_getsec.h"
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010010#include "txt_register.h"
11
Arthur Heymans773ecfe2021-05-12 16:16:19 +020012const char *intel_txt_processor_error_type(uint8_t type)
13{
14 static const char *const names[] = {
15 [0] = "Legacy Shutdown",
16 [5] = "Load memory type error in ACM area",
17 [6] = "Unrecognized ACM format",
18 [7] = "Failure to authenticate",
19 [8] = "Invalid ACM format",
20 [9] = "Unexpected Snoop hit",
21 [10] = "Invalid event",
22 [11] = "Invalid MLE",
23 [12] = "Machine check event",
24 [13] = "VMXAbort",
25 [14] = "AC memory corruption",
26 [15] = "Illegal voltage/bus ratio",
27 };
28
29 return type < ARRAY_SIZE(names) && names[type] ? names[type] : "Unknown";
30}
31
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010032/**
33 * Logs microcode or SINIT ACM errors.
34 * Does not log SBIOS ACM errors.
35 */
36static void log_txt_error(const char *phase)
37{
38 const uint64_t txt_error = read64((void *)TXT_ERROR);
39
40 if (txt_error & ACMERROR_TXT_VALID) {
41 printk(BIOS_ERR, "%s: Error occurred\n", phase);
42
43 if (txt_error & ACMERROR_TXT_EXTERNAL)
44 printk(BIOS_ERR, " Caused by: External\n");
45 else
46 printk(BIOS_ERR, " Caused by: Processor\n");
47
Arthur Heymans773ecfe2021-05-12 16:16:19 +020048 printk(BIOS_ERR, " Type: %s\n",
49 intel_txt_processor_error_type(txt_error & TXT_ERROR_MASK));
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010050 }
51}
52
53/**
54 * Dump useful informaation about the BIOS ACM state.
55 * Should run right after console_init() in romstage.
56 * Resets the platform if TXT reset is active and MLE cannot be established.
57 **/
58void intel_txt_log_bios_acm_error(void)
59{
60 uint32_t bios_acm_error;
61 uint64_t acm_status;
62 uint64_t txt_error;
63
64 printk(BIOS_INFO, "TEE-TXT: State of ACM and ucode update:\n");
65
66 bios_acm_error = read32((void *)TXT_BIOSACM_ERRORCODE);
67 acm_status = read64((void *)TXT_SPAD);
68 txt_error = read64((void *)TXT_ERROR);
69
70 /* Errors by BIOS ACM or FIT */
71 if ((txt_error & ACMERROR_TXT_VALID) &&
72 (acm_status & ACMERROR_TXT_VALID)) {
73 intel_txt_log_acm_error(read32((void *)TXT_BIOSACM_ERRORCODE));
74 log_txt_error("FIT MICROCODE");
75 }
76 /* Errors by SINIT */
77 if ((txt_error & ACMERROR_TXT_VALID) &&
78 !(acm_status & ACMERROR_TXT_VALID)) {
79 intel_txt_log_acm_error(txt_error);
80 log_txt_error("SINIT");
81 }
82
83 /* Check for fatal ACM error and TXT reset */
84 uint8_t error = read8((void *)TXT_ESTS);
85 if (error & TXT_ESTS_TXT_RESET_STS) {
86 printk(BIOS_CRIT, "TXT-STS: Intel TXT reset detected\n");
87 intel_txt_log_acm_error(read32((void *)TXT_ERROR));
88 }
89}
90
91/**
92 * Dump information about the provided ACM.
93 */
94void txt_dump_acm_info(const struct acm_header_v0 *acm_header)
95{
96 const struct acm_info_table *info = NULL;
97 if (!acm_header)
98 return;
99
100 printk(BIOS_INFO, "ACM @ %p\n", acm_header);
101
102 const size_t acm_size = (acm_header->size & 0xffffff) << 2;
103 const size_t info_off = (acm_header->header_len + acm_header->scratch_size) * 4;
104
105 if (acm_size > (info_off + sizeof(struct acm_info_table)))
106 info = (const struct acm_info_table *)
107 ((const unsigned char *)acm_header + info_off);
108
109 printk(BIOS_INFO, " ACM: Binary Info\n");
110 if (acm_header->module_type == CHIPSET_ACM)
111 printk(BIOS_INFO, " Type: Chipset ACM\n");
112
113 if (acm_header->module_sub_type == 0)
114 printk(BIOS_INFO, " Subtype: undefined\n");
115 else if (acm_header->module_sub_type == 1)
116 printk(BIOS_INFO, " Subtype: Run at reset\n");
117
118 printk(BIOS_INFO, " Header: v%u.%u\n", acm_header->header_version[0],
119 acm_header->header_version[1]);
120
Christian Walter6e536bc2020-09-30 13:42:35 +0200121 printk(BIOS_INFO, " Chipset: %x\n", acm_header->chipset_id);
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100122 printk(BIOS_INFO, " Size: %zu\n", acm_size);
123
124 switch (acm_header->flags) {
125 case ACM_FORMAT_FLAGS_PW:
126 printk(BIOS_INFO, " Flags: PW signed (Production Worthy)\n");
127 break;
128 case ACM_FORMAT_FLAGS_NPW:
129 printk(BIOS_INFO, " Flags: NPW signed (Non Production Worthy)\n");
130 break;
131 case ACM_FORMAT_FLAGS_DEBUG:
132 printk(BIOS_INFO, " Flags: Debug signed\n");
133 break;
134 }
135
136 if (acm_header->module_vendor == INTEL_ACM_VENDOR)
137 printk(BIOS_INFO, " Vendor: Intel Corporation\n");
138
139 printk(BIOS_INFO, " Date: %x\n", acm_header->date);
140
141 switch (acm_header->size) {
142 case ACM_FORMAT_SIZE_64KB:
143 printk(BIOS_INFO, " Size: 64KB\n");
144 printk(BIOS_INFO, " CBnT: no\n");
145 break;
146 case ACM_FORMAT_SIZE_128KB:
147 printk(BIOS_INFO, " Size: 128KB\n");
148 printk(BIOS_INFO, " CBnT: no\n");
149 break;
150 case ACM_FORMAT_SIZE_256KB:
151 printk(BIOS_INFO, " Size: 256KB\n");
152 printk(BIOS_INFO, " CBnT: yes\n");
153 break;
154 default:
155 printk(BIOS_INFO, " Size: 0x%08x\n", acm_header->size);
156
157 break;
158 }
159
160 printk(BIOS_INFO, " TXT SVN: %u\n", acm_header->txt_svn);
161 printk(BIOS_INFO, " SE SVN: %u\n", acm_header->se_svn);
162
163 if (!info)
164 return;
165 printk(BIOS_INFO, " Table info:\n");
166 printk(BIOS_INFO, " UUID: ");
167 for (size_t i = 0; i < sizeof(info->uuid); i++)
168 printk(BIOS_INFO, "%02X ", info->uuid[i]);
169 printk(BIOS_INFO, "\n");
170 printk(BIOS_INFO, " Chipset acm type: 0x%x\n", info->chipset_acm_type);
171 printk(BIOS_INFO, " Capabilities: 0x%x\n", info->capabilities);
172}
173
174/**
175 * Dump information about the chipset's TXT capabilities.
176 */
177void txt_dump_chipset_info(void)
178{
179 printk(BIOS_INFO, "TEE-TXT: Chipset Key Hash 0x");
180 for (int i = 0; i < TXT_ACM_KEY_HASH_LEN; i++) {
181 printk(BIOS_INFO, "%llx", read64((void *)TXT_ACM_KEY_HASH +
182 (i * sizeof(uint64_t))));
183 }
184 printk(BIOS_INFO, "\n");
185
186 printk(BIOS_INFO, "TEE-TXT: DIDVID 0x%x\n", read32((void *)TXT_DIDVID));
187 printk(BIOS_INFO, "TEE-TXT: production fused chipset: %s\n",
Michał Żygowski9734e802021-11-21 12:29:58 +0100188 intel_txt_chipset_is_production_fused() ? "true" : "false");
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100189}
190
191void txt_dump_regions(void)
192{
193 struct txt_biosdataregion *bdr = NULL;
Angel Pons11334722020-10-05 16:34:03 +0200194
195 uintptr_t tseg_base;
196 size_t tseg_size;
197
198 smm_region(&tseg_base, &tseg_size);
199
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100200 uint64_t reg64;
201
202 reg64 = read64((void *)TXT_HEAP_BASE);
203 if ((reg64 != 0 && reg64 != ~0UL) &&
204 (read64((void *)(uintptr_t)reg64) >= (sizeof(*bdr) + sizeof(uint64_t))))
205 bdr = (void *)((uintptr_t)reg64 + sizeof(uint64_t));
206
Angel Pons11334722020-10-05 16:34:03 +0200207 printk(BIOS_DEBUG, "TEE-TXT: TSEG 0x%lx, size %zu MiB\n", tseg_base, tseg_size / MiB);
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100208 printk(BIOS_DEBUG, "TEE-TXT: TXT.HEAP.BASE 0x%llx\n", read64((void *)TXT_HEAP_BASE));
209 printk(BIOS_DEBUG, "TEE-TXT: TXT.HEAP.SIZE 0x%llx\n", read64((void *)TXT_HEAP_SIZE));
210 printk(BIOS_DEBUG, "TEE-TXT: TXT.SINIT.BASE 0x%llx\n", read64((void *)TXT_SINIT_BASE));
211 printk(BIOS_DEBUG, "TEE-TXT: TXT.SINIT.SIZE 0x%llx\n", read64((void *)TXT_SINIT_SIZE));
212 printk(BIOS_DEBUG, "TEE-TXT: TXT.MSEG.BASE 0x%llx\n", read64((void *)TXT_MSEG_BASE));
213 printk(BIOS_DEBUG, "TEE-TXT: TXT.MSEG.SIZE 0x%llx\n", read64((void *)TXT_MSEG_SIZE));
214
215 if (bdr) {
216 printk(BIOS_DEBUG, "TEE-TXT: BiosDataRegion.bios_sinit_size 0x%x\n",
217 bdr->bios_sinit_size);
218 printk(BIOS_DEBUG, "TEE-TXT: BiosDataRegion.lcp_pd_size 0x%llx\n",
219 bdr->lcp_pd_size);
220 printk(BIOS_DEBUG, "TEE-TXT: BiosDataRegion.lcp_pd_base 0x%llx\n",
221 bdr->lcp_pd_base);
222 }
223}
Michał Żygowski7480e872021-11-21 12:47:14 +0100224
225void txt_dump_getsec_parameters(void)
226{
227 uint32_t version_mask;
228 uint32_t version_numbers_supported;
229 uint32_t max_size_acm_area;
230 uint32_t memory_type_mask;
231 uint32_t senter_function_disable;
232 uint32_t txt_feature_flags;
233
234 if (!getsec_parameter(&version_mask, &version_numbers_supported,
235 &max_size_acm_area, &memory_type_mask,
236 &senter_function_disable, &txt_feature_flags)) {
237 printk(BIOS_WARNING, "Could not obtain GETSEC parameters\n");
238 return;
239 }
240 printk(BIOS_DEBUG, "TEE-TXT: GETSEC[PARAMETERS] returned:\n");
241 printk(BIOS_DEBUG, " ACM Version comparison mask: %08x\n", version_mask);
242 printk(BIOS_DEBUG, " ACM Version numbers supported: %08x\n",
243 version_numbers_supported);
244 printk(BIOS_DEBUG, " Max size of authenticated code execution area: %08x\n",
245 max_size_acm_area);
246 printk(BIOS_DEBUG, " External memory types supported during AC mode: %08x\n",
247 memory_type_mask);
248 printk(BIOS_DEBUG, " Selective SENTER functionality control: %02x\n",
249 (senter_function_disable >> 8) & 0x7f);
250 printk(BIOS_DEBUG, " Feature Extensions Flags: %08x\n", txt_feature_flags);
251 printk(BIOS_DEBUG, "\tS-CRTM Capability rooted in: ");
252 if (txt_feature_flags & GETSEC_PARAMS_TXT_EXT_CRTM_SUPPORT) {
253 printk(BIOS_DEBUG, "processor\n");
254 } else {
255 printk(BIOS_DEBUG, "BIOS\n");
256 }
257 printk(BIOS_DEBUG, "\tMachine Check Register: ");
258 if (txt_feature_flags & GETSEC_PARAMS_TXT_EXT_MACHINE_CHECK) {
259 printk(BIOS_DEBUG, "preserved\n");
260 } else {
261 printk(BIOS_DEBUG, "must be clear\n");
262 }
263}