blob: cf14b55df9f5465b0f779270bd7659e3584a9823 [file] [log] [blame]
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <console/console.h>
4#if CONFIG(SOC_INTEL_COMMON_BLOCK_SA)
5#include <intelblocks/systemagent.h>
6#endif
7
8#include <arch/mmio.h>
9#include <string.h>
10
11#include "txt.h"
12#include "txt_register.h"
13
14/**
15 * Logs microcode or SINIT ACM errors.
16 * Does not log SBIOS ACM errors.
17 */
18static void log_txt_error(const char *phase)
19{
20 const uint64_t txt_error = read64((void *)TXT_ERROR);
21
22 if (txt_error & ACMERROR_TXT_VALID) {
23 printk(BIOS_ERR, "%s: Error occurred\n", phase);
24
25 if (txt_error & ACMERROR_TXT_EXTERNAL)
26 printk(BIOS_ERR, " Caused by: External\n");
27 else
28 printk(BIOS_ERR, " Caused by: Processor\n");
29
30 printk(BIOS_ERR, " Type: ");
31
32 switch (txt_error & TXT_ERROR_MASK) {
33 case 0:
34 printk(BIOS_ERR, "Legacy Shutdown\n");
35 break;
36 case 5:
37 printk(BIOS_ERR, "Load memory type error in ACM area\n");
38 break;
39 case 6:
40 printk(BIOS_ERR, "Unrecognized ACM format\n");
41 break;
42 case 7:
43 printk(BIOS_ERR, "Failure to authenticate\n");
44 break;
45 case 8:
46 printk(BIOS_ERR, "Invalid ACM format\n");
47 break;
48 case 9:
49 printk(BIOS_ERR, "Unexpected Snoop hit\n");
50 break;
51 case 10:
52 printk(BIOS_ERR, "Invalid event\n");
53 break;
54 case 11:
55 printk(BIOS_ERR, "Invalid MLE\n");
56 break;
57 case 12:
58 printk(BIOS_ERR, "Machine check event\n");
59 break;
60 case 13:
61 printk(BIOS_ERR, "VMXAbort\n");
62 break;
63 case 14:
64 printk(BIOS_ERR, "AC memory corruption\n");
65 break;
66 case 15:
67 printk(BIOS_ERR, "Illegal voltage/bus ratio\n");
68 break;
69 default:
70 printk(BIOS_ERR, "unknown\n");
71 break;
72 }
73 }
74}
75
76/**
77 * Dump useful informaation about the BIOS ACM state.
78 * Should run right after console_init() in romstage.
79 * Resets the platform if TXT reset is active and MLE cannot be established.
80 **/
81void intel_txt_log_bios_acm_error(void)
82{
83 uint32_t bios_acm_error;
84 uint64_t acm_status;
85 uint64_t txt_error;
86
87 printk(BIOS_INFO, "TEE-TXT: State of ACM and ucode update:\n");
88
89 bios_acm_error = read32((void *)TXT_BIOSACM_ERRORCODE);
90 acm_status = read64((void *)TXT_SPAD);
91 txt_error = read64((void *)TXT_ERROR);
92
93 /* Errors by BIOS ACM or FIT */
94 if ((txt_error & ACMERROR_TXT_VALID) &&
95 (acm_status & ACMERROR_TXT_VALID)) {
96 intel_txt_log_acm_error(read32((void *)TXT_BIOSACM_ERRORCODE));
97 log_txt_error("FIT MICROCODE");
98 }
99 /* Errors by SINIT */
100 if ((txt_error & ACMERROR_TXT_VALID) &&
101 !(acm_status & ACMERROR_TXT_VALID)) {
102 intel_txt_log_acm_error(txt_error);
103 log_txt_error("SINIT");
104 }
105
106 /* Check for fatal ACM error and TXT reset */
107 uint8_t error = read8((void *)TXT_ESTS);
108 if (error & TXT_ESTS_TXT_RESET_STS) {
109 printk(BIOS_CRIT, "TXT-STS: Intel TXT reset detected\n");
110 intel_txt_log_acm_error(read32((void *)TXT_ERROR));
111 }
112}
113
114/**
115 * Dump information about the provided ACM.
116 */
117void txt_dump_acm_info(const struct acm_header_v0 *acm_header)
118{
119 const struct acm_info_table *info = NULL;
120 if (!acm_header)
121 return;
122
123 printk(BIOS_INFO, "ACM @ %p\n", acm_header);
124
125 const size_t acm_size = (acm_header->size & 0xffffff) << 2;
126 const size_t info_off = (acm_header->header_len + acm_header->scratch_size) * 4;
127
128 if (acm_size > (info_off + sizeof(struct acm_info_table)))
129 info = (const struct acm_info_table *)
130 ((const unsigned char *)acm_header + info_off);
131
132 printk(BIOS_INFO, " ACM: Binary Info\n");
133 if (acm_header->module_type == CHIPSET_ACM)
134 printk(BIOS_INFO, " Type: Chipset ACM\n");
135
136 if (acm_header->module_sub_type == 0)
137 printk(BIOS_INFO, " Subtype: undefined\n");
138 else if (acm_header->module_sub_type == 1)
139 printk(BIOS_INFO, " Subtype: Run at reset\n");
140
141 printk(BIOS_INFO, " Header: v%u.%u\n", acm_header->header_version[0],
142 acm_header->header_version[1]);
143
144 printk(BIOS_INFO, " Chipset: %u\n", acm_header->chipset_id);
145 printk(BIOS_INFO, " Size: %zu\n", acm_size);
146
147 switch (acm_header->flags) {
148 case ACM_FORMAT_FLAGS_PW:
149 printk(BIOS_INFO, " Flags: PW signed (Production Worthy)\n");
150 break;
151 case ACM_FORMAT_FLAGS_NPW:
152 printk(BIOS_INFO, " Flags: NPW signed (Non Production Worthy)\n");
153 break;
154 case ACM_FORMAT_FLAGS_DEBUG:
155 printk(BIOS_INFO, " Flags: Debug signed\n");
156 break;
157 }
158
159 if (acm_header->module_vendor == INTEL_ACM_VENDOR)
160 printk(BIOS_INFO, " Vendor: Intel Corporation\n");
161
162 printk(BIOS_INFO, " Date: %x\n", acm_header->date);
163
164 switch (acm_header->size) {
165 case ACM_FORMAT_SIZE_64KB:
166 printk(BIOS_INFO, " Size: 64KB\n");
167 printk(BIOS_INFO, " CBnT: no\n");
168 break;
169 case ACM_FORMAT_SIZE_128KB:
170 printk(BIOS_INFO, " Size: 128KB\n");
171 printk(BIOS_INFO, " CBnT: no\n");
172 break;
173 case ACM_FORMAT_SIZE_256KB:
174 printk(BIOS_INFO, " Size: 256KB\n");
175 printk(BIOS_INFO, " CBnT: yes\n");
176 break;
177 default:
178 printk(BIOS_INFO, " Size: 0x%08x\n", acm_header->size);
179
180 break;
181 }
182
183 printk(BIOS_INFO, " TXT SVN: %u\n", acm_header->txt_svn);
184 printk(BIOS_INFO, " SE SVN: %u\n", acm_header->se_svn);
185
186 if (!info)
187 return;
188 printk(BIOS_INFO, " Table info:\n");
189 printk(BIOS_INFO, " UUID: ");
190 for (size_t i = 0; i < sizeof(info->uuid); i++)
191 printk(BIOS_INFO, "%02X ", info->uuid[i]);
192 printk(BIOS_INFO, "\n");
193 printk(BIOS_INFO, " Chipset acm type: 0x%x\n", info->chipset_acm_type);
194 printk(BIOS_INFO, " Capabilities: 0x%x\n", info->capabilities);
195}
196
197/**
198 * Dump information about the chipset's TXT capabilities.
199 */
200void txt_dump_chipset_info(void)
201{
202 printk(BIOS_INFO, "TEE-TXT: Chipset Key Hash 0x");
203 for (int i = 0; i < TXT_ACM_KEY_HASH_LEN; i++) {
204 printk(BIOS_INFO, "%llx", read64((void *)TXT_ACM_KEY_HASH +
205 (i * sizeof(uint64_t))));
206 }
207 printk(BIOS_INFO, "\n");
208
209 printk(BIOS_INFO, "TEE-TXT: DIDVID 0x%x\n", read32((void *)TXT_DIDVID));
210 printk(BIOS_INFO, "TEE-TXT: production fused chipset: %s\n",
211 (read64((void *)TXT_VER_FSBIF) & TXT_VER_PRODUCTION_FUSED) ? "true" : "false");
212}
213
214void txt_dump_regions(void)
215{
216 struct txt_biosdataregion *bdr = NULL;
217 uintptr_t tseg = 0;
218 uint64_t reg64;
219
220 reg64 = read64((void *)TXT_HEAP_BASE);
221 if ((reg64 != 0 && reg64 != ~0UL) &&
222 (read64((void *)(uintptr_t)reg64) >= (sizeof(*bdr) + sizeof(uint64_t))))
223 bdr = (void *)((uintptr_t)reg64 + sizeof(uint64_t));
224
225 printk(BIOS_DEBUG, "TEE-TXT: TSEG 0x%lx\n", tseg * MiB);
226 printk(BIOS_DEBUG, "TEE-TXT: TXT.HEAP.BASE 0x%llx\n", read64((void *)TXT_HEAP_BASE));
227 printk(BIOS_DEBUG, "TEE-TXT: TXT.HEAP.SIZE 0x%llx\n", read64((void *)TXT_HEAP_SIZE));
228 printk(BIOS_DEBUG, "TEE-TXT: TXT.SINIT.BASE 0x%llx\n", read64((void *)TXT_SINIT_BASE));
229 printk(BIOS_DEBUG, "TEE-TXT: TXT.SINIT.SIZE 0x%llx\n", read64((void *)TXT_SINIT_SIZE));
230 printk(BIOS_DEBUG, "TEE-TXT: TXT.MSEG.BASE 0x%llx\n", read64((void *)TXT_MSEG_BASE));
231 printk(BIOS_DEBUG, "TEE-TXT: TXT.MSEG.SIZE 0x%llx\n", read64((void *)TXT_MSEG_SIZE));
232
233 if (bdr) {
234 printk(BIOS_DEBUG, "TEE-TXT: BiosDataRegion.bios_sinit_size 0x%x\n",
235 bdr->bios_sinit_size);
236 printk(BIOS_DEBUG, "TEE-TXT: BiosDataRegion.lcp_pd_size 0x%llx\n",
237 bdr->lcp_pd_size);
238 printk(BIOS_DEBUG, "TEE-TXT: BiosDataRegion.lcp_pd_base 0x%llx\n",
239 bdr->lcp_pd_base);
240 }
241}