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