blob: 437c55edd80d9c859154ef65938f93e134bfc789 [file] [log] [blame]
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <arch/mmio.h>
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01004#include <console/console.h>
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01005#include <cbfs.h>
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01006#include <cpu/x86/cr.h>
Angel Pons52082be2020-10-05 12:34:29 +02007#include <cpu/x86/lapic.h>
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01008#include <cpu/x86/mp.h>
Angel Pons038cef92020-10-14 17:58:36 +02009#include <cpu/x86/mtrr.h>
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010010#include <lib.h>
11#include <smp/node.h>
Angel Pons52082be2020-10-05 12:34:29 +020012#include <string.h>
13#include <types.h>
Angel Pons1fc43aa2020-08-04 17:54:01 +020014
15#if CONFIG(SOC_INTEL_COMMON_BLOCK_SA)
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010016#include <soc/intel/common/reset.h>
Angel Pons1fc43aa2020-08-04 17:54:01 +020017#else
18#include <cf9_reset.h>
19#endif
20
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010021#include "txt.h"
22#include "txt_register.h"
23#include "txt_getsec.h"
24
Angel Pons1fc43aa2020-08-04 17:54:01 +020025/* Usual security practice: if an unexpected error happens, reboot */
26static void __noreturn txt_reset_platform(void)
27{
28#if CONFIG(SOC_INTEL_COMMON_BLOCK_SA)
29 global_reset();
30#else
31 full_reset();
32#endif
33}
34
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010035/**
36 * Dump the ACM error status bits.
37 *
38 * @param acm_error The status register to dump
39 * @return -1 on error (register is not valid)
40 * 0 on error (Class > 0 and Major > 0)
41 * 1 on success (Class == 0 and Major == 0 and progress > 0)
42 */
43int intel_txt_log_acm_error(const uint32_t acm_error)
44{
45 if (!(acm_error & ACMERROR_TXT_VALID))
46 return -1;
47
48 const uint8_t type = (acm_error & ACMERROR_TXT_TYPE_CODE)
49 >> ACMERROR_TXT_TYPE_SHIFT;
50
51 switch (type) {
52 case ACMERROR_TXT_AC_MODULE_TYPE_BIOS:
53 printk(BIOS_ERR, "BIOSACM");
54 break;
55 case ACMERROR_TXT_AC_MODULE_TYPE_SINIT:
56 printk(BIOS_ERR, "SINIT");
57 break;
58 default:
59 printk(BIOS_ERR, "ACM");
60 break;
61 }
62 printk(BIOS_ERR, ": Error code valid\n");
63
64 if (acm_error & ACMERROR_TXT_EXTERNAL)
65 printk(BIOS_ERR, " Caused by: External\n");
66 else
67 printk(BIOS_ERR, " Caused by: Processor\n");
68
69 const uint32_t class = (acm_error & ACMERROR_TXT_CLASS_CODE)
70 >> ACMERROR_TXT_CLASS_SHIFT;
71 const uint32_t major = (acm_error & ACMERROR_TXT_MAJOR_CODE)
72 >> ACMERROR_TXT_MAJOR_SHIFT;
73 const uint32_t minor = (acm_error & ACMERROR_TXT_MINOR_CODE)
74 >> ACMERROR_TXT_MINOR_SHIFT;
75 const uint32_t progress = (acm_error & ACMERROR_TXT_PROGRESS_CODE)
76 >> ACMERROR_TXT_PROGRESS_SHIFT;
77
78 if (!minor) {
79 if (class == 0 && major == 0 && progress > 0) {
80 printk(BIOS_ERR, " Execution successful\n");
81 printk(BIOS_ERR, " Progress code 0x%x\n", progress);
82 } else {
83 printk(BIOS_ERR, " Error Class: %x\n", class);
84 printk(BIOS_ERR, " Error: %x.%x\n", major, progress);
85 }
86 } else {
87 printk(BIOS_ERR, " ACM didn't start\n");
88 printk(BIOS_ERR, " Error Type: 0x%x\n", acm_error & 0xffffff);
89 return -1;
90 }
91
92 return (acm_error & ACMERROR_TXT_EXTERNAL) && class == 0 && major == 0 && progress > 0;
93}
94
95void intel_txt_log_spad(void)
96{
97 const uint64_t acm_status = read64((void *)TXT_SPAD);
98
99 printk(BIOS_INFO, "TXT-STS: ACM verification ");
100
101 if (acm_status & ACMSTS_VERIFICATION_ERROR)
102 printk(BIOS_INFO, "error\n");
103 else
104 printk(BIOS_INFO, "successful\n");
105
106 printk(BIOS_INFO, "TXT-STS: IBB ");
107
108 if (acm_status & ACMSTS_IBB_MEASURED)
109 printk(BIOS_INFO, "measured\n");
110 else
111 printk(BIOS_INFO, "not measured\n");
112
113 printk(BIOS_INFO, "TXT-STS: TXT is ");
114
115 if (acm_status & ACMSTS_TXT_DISABLED)
116 printk(BIOS_INFO, "disabled\n");
117 else
118 printk(BIOS_INFO, "not disabled\n");
119
120 printk(BIOS_INFO, "TXT-STS: BIOS is ");
121
122 if (acm_status & ACMSTS_BIOS_TRUSTED)
123 printk(BIOS_INFO, "trusted\n");
124 else
125 printk(BIOS_INFO, "not trusted\n");
126}
127
128/* Returns true if secrets might be in memory */
129bool intel_txt_memory_has_secrets(void)
130{
131 bool ret;
132 if (!CONFIG(INTEL_TXT))
133 return false;
134
135 ret = (read8((void *)TXT_ESTS) & TXT_ESTS_WAKE_ERROR_STS) ||
136 (read64((void *)TXT_E2STS) & TXT_E2STS_SECRET_STS);
137
138 if (ret)
139 printk(BIOS_CRIT, "TXT-STS: Secrets in memory!\n");
140 return ret;
141}
142
143static struct acm_info_table *find_info_table(const void *ptr)
144{
145 const struct acm_header_v0 *acm_header = (struct acm_header_v0 *)ptr;
146
147 return (struct acm_info_table *)(ptr +
148 (acm_header->header_len + acm_header->scratch_size) * sizeof(uint32_t));
149}
150
151/**
152 * Validate that the provided ACM is useable on this platform.
153 */
154static int validate_acm(const void *ptr)
155{
156 const struct acm_header_v0 *acm_header = (struct acm_header_v0 *)ptr;
157 uint32_t max_size_acm_area = 0;
158
159 if (acm_header->module_type != CHIPSET_ACM)
160 return ACM_E_TYPE_NOT_MATCH;
161
162 /* Seems inconsistent across generations. */
163 if (acm_header->module_sub_type != 0 && acm_header->module_sub_type != 1)
164 return ACM_E_MODULE_SUB_TYPE_WRONG;
165
166 if (acm_header->module_vendor != INTEL_ACM_VENDOR)
167 return ACM_E_MODULE_VENDOR_NOT_INTEL;
168
John Zhao536e9652020-08-04 11:29:08 -0700169 if (acm_header->size == 0)
170 return ACM_E_SIZE_INCORRECT;
171
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100172 if (((acm_header->header_len + acm_header->scratch_size) * sizeof(uint32_t) +
173 sizeof(struct acm_info_table)) > (acm_header->size & 0xffffff) * sizeof(uint32_t)) {
174 return ACM_E_SIZE_INCORRECT;
175 }
176
177 if (!getsec_parameter(NULL, NULL, &max_size_acm_area, NULL, NULL, NULL))
178 return ACM_E_CANT_CALL_GETSEC;
179
180 /*
181 * Causes #GP if acm_header->size > processor internal authenticated
182 * code area capacity.
183 * SAFER MODE EXTENSIONS REFERENCE.
184 * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D
185 */
186 const size_t acm_len = 1UL << log2_ceil((acm_header->size & 0xffffff) << 2);
187 if (max_size_acm_area < acm_len) {
188 printk(BIOS_ERR, "TEE-TXT: BIOS ACM doesn't fit into AC execution region\n");
189 return ACM_E_NOT_FIT_INTO_CPU_ACM_MEM;
190 }
191
192 struct acm_info_table *info = find_info_table(ptr);
193 if (!info)
194 return ACM_E_NO_INFO_TABLE;
195 if (info->chipset_acm_type != BIOS)
196 return ACM_E_NOT_BIOS_ACM;
197
198 static const u8 acm_uuid[] = {
199 0xaa, 0x3a, 0xc0, 0x7f, 0xa7, 0x46, 0xdb, 0x18,
200 0x2e, 0xac, 0x69, 0x8f, 0x8d, 0x41, 0x7f, 0x5a,
201 };
202 if (memcmp(acm_uuid, info->uuid, sizeof(acm_uuid)) != 0)
203 return ACM_E_UUID_NOT_MATCH;
204
205 if ((acm_header->flags & ACM_FORMAT_FLAGS_DEBUG) ==
206 (read64((void *)TXT_VER_FSBIF) & TXT_VER_PRODUCTION_FUSED))
207 return ACM_E_PLATFORM_IS_NOT_PROD;
208
209 return 0;
210}
211
212/*
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200213 * Prepare to run the BIOS ACM: mmap it from the CBFS and verify that it
214 * can be launched. Returns pointer to ACM on success, NULL on failure.
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100215 */
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200216static void *intel_txt_prepare_bios_acm(struct region_device *acm, size_t *acm_len)
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100217{
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200218 void *acm_data = NULL;
219
220 if (!acm || !acm_len)
221 return NULL;
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100222
Julius Werner77639e42021-02-05 16:51:25 -0800223 acm_data = cbfs_map(CONFIG_INTEL_TXT_CBFS_BIOS_ACM, acm_len);
224 if (!acm_data) {
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100225 printk(BIOS_ERR, "TEE-TXT: Couldn't locate BIOS ACM in CBFS.\n");
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200226 return NULL;
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100227 }
228
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100229 /*
230 * CPU enforces only 4KiB alignment.
231 * Chapter A.1.1
232 * Intel TXT Software Development Guide (Document: 315168-015)
233 */
234 if (!IS_ALIGNED((uintptr_t)acm_data, 4096)) {
235 printk(BIOS_ERR, "TEE-TXT: BIOS ACM isn't mapped at page boundary.\n");
Julius Werner77639e42021-02-05 16:51:25 -0800236 cbfs_unmap(acm_data);
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200237 return NULL;
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100238 }
239
240 /*
241 * Causes #GP if not multiple of 64.
242 * SAFER MODE EXTENSIONS REFERENCE.
243 * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D
244 */
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200245 if (!IS_ALIGNED(*acm_len, 64)) {
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100246 printk(BIOS_ERR, "TEE-TXT: BIOS ACM size isn't multiple of 64.\n");
Julius Werner77639e42021-02-05 16:51:25 -0800247 cbfs_unmap(acm_data);
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200248 return NULL;
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100249 }
250
251 /*
252 * The ACM should be aligned to it's size, but that's not possible, as
253 * some ACMs are not power of two. Use the next power of two for verification.
254 */
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200255 if (!IS_ALIGNED((uintptr_t)acm_data, (1UL << log2_ceil(*acm_len)))) {
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100256 printk(BIOS_ERR, "TEE-TXT: BIOS ACM isn't aligned to its size.\n");
Julius Werner77639e42021-02-05 16:51:25 -0800257 cbfs_unmap(acm_data);
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200258 return NULL;
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100259 }
260
Angel Pons038cef92020-10-14 17:58:36 +0200261 /*
262 * When setting up the MTRRs to cache the BIOS ACM, one must cache less than
263 * a page (4 KiB) of unused memory after the BIOS ACM. On Haswell, failure
264 * to do so will cause a TXT reset with Class Code 5, Major Error Code 2.
265 */
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200266 if (popcnt(ALIGN_UP(*acm_len, 4096)) > get_var_mtrr_count()) {
Angel Pons038cef92020-10-14 17:58:36 +0200267 printk(BIOS_ERR, "TEE-TXT: Not enough MTRRs to cache this BIOS ACM's size.\n");
Julius Werner77639e42021-02-05 16:51:25 -0800268 cbfs_unmap(acm_data);
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200269 return NULL;
Angel Pons038cef92020-10-14 17:58:36 +0200270 }
271
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100272 if (CONFIG(INTEL_TXT_LOGGING))
273 txt_dump_acm_info(acm_data);
274
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200275 const int ret = validate_acm(acm_data);
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100276 if (ret < 0) {
277 printk(BIOS_ERR, "TEE-TXT: Validation of ACM failed with: %d\n", ret);
Julius Werner77639e42021-02-05 16:51:25 -0800278 cbfs_unmap(acm_data);
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200279 return NULL;
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100280 }
281
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200282 return acm_data;
283}
284
Angel Pons6c49f402020-08-28 02:02:00 +0200285#define MCU_BASE_ADDR (TXT_BASE + 0x278)
286#define BIOACM_ADDR (TXT_BASE + 0x27c)
287#define APINIT_ADDR (TXT_BASE + 0x290)
288#define SEMAPHORE (TXT_BASE + 0x294)
289
290/* Returns on failure, resets the computer on success */
291void intel_txt_run_sclean(void)
292{
293 struct region_device acm;
294 size_t acm_len;
295
296 void *acm_data = intel_txt_prepare_bios_acm(&acm, &acm_len);
297
298 if (!acm_data)
299 return;
300
301 /* FIXME: Do we need to program these two? */
302 //write32((void *)MCU_BASE_ADDR, 0xffe1a990);
303 //write32((void *)APINIT_ADDR, 0xfffffff0);
304
305 write32((void *)BIOACM_ADDR, (uintptr_t)acm_data);
306 write32((void *)SEMAPHORE, 0);
307
308 /*
309 * The time SCLEAN will take depends on the installed RAM size.
310 * On Haswell with 8 GiB of DDR3, it takes five or ten minutes. (rough estimate)
311 */
312 printk(BIOS_ALERT, "TEE-TXT: Invoking SCLEAN. This can take several minutes.\n");
313
314 /*
315 * Invoke the BIOS ACM. If successful, the system will reset with memory unlocked.
316 */
317 getsec_sclean((uintptr_t)acm_data, acm_len);
318
319 /*
320 * However, if this function returns, the BIOS ACM could not be invoked. This is bad.
321 */
322 printk(BIOS_CRIT, "TEE-TXT: getsec_sclean could not launch the BIOS ACM.\n");
323
324 rdev_munmap(&acm, acm_data);
325}
326
Angel Pons7b4d67cf2020-10-20 14:17:42 +0200327/*
328 * Test all bits for TXT execution.
329 *
330 * @return 0 on success
331 */
332int intel_txt_run_bios_acm(const u8 input_params)
333{
334 struct region_device acm;
335 size_t acm_len;
336
337 void *acm_data = intel_txt_prepare_bios_acm(&acm, &acm_len);
338
339 if (!acm_data)
340 return -1;
341
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100342 /* Call into assembly which invokes the referenced ACM */
343 getsec_enteraccs(input_params, (uintptr_t)acm_data, acm_len);
344
345 rdev_munmap(&acm, acm_data);
346
347 const uint64_t acm_status = read64((void *)TXT_SPAD);
348 if (acm_status & ACMERROR_TXT_VALID) {
349 printk(BIOS_ERR, "TEE-TXT: FATAL ACM launch error !\n");
350 /*
351 * WARNING !
352 * To clear TXT.BIOSACM.ERRORCODE you must issue a cold reboot!
353 */
354 intel_txt_log_acm_error(read32((void *)TXT_BIOSACM_ERRORCODE));
355 return -1;
356 }
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100357
358 return 0;
359}
360
361 /* Returns true if cond is not met */
362static bool check_precondition(const int cond)
363{
364 printk(BIOS_DEBUG, "%s\n", cond ? "true" : "false");
365 return !cond;
366}
367
368/*
369 * Test all bits that are required for Intel TXT.
370 * Enable SMX if available.
371 *
372 * @return 0 on success
373 */
374bool intel_txt_prepare_txt_env(void)
375{
376 bool failure = false;
377 uint32_t txt_feature_flags = 0;
378
379 unsigned int ecx = cpuid_ecx(1);
380
381 printk(BIOS_DEBUG, "TEE-TXT: CPU supports SMX: ");
382 failure |= check_precondition(ecx & CPUID_SMX);
383
384 printk(BIOS_DEBUG, "TEE-TXT: CPU supports VMX: ");
385 failure |= check_precondition(ecx & CPUID_VMX);
386
387 msr_t msr = rdmsr(IA32_FEATURE_CONTROL);
388 if (!(msr.lo & BIT(0))) {
389 printk(BIOS_ERR, "TEE-TXT: IA32_FEATURE_CONTROL is not locked\n");
Angel Pons1fc43aa2020-08-04 17:54:01 +0200390 txt_reset_platform();
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +0100391 }
392
393 printk(BIOS_DEBUG, "TEE-TXT: IA32_FEATURE_CONTROL\n");
394 printk(BIOS_DEBUG, " VMXON in SMX enable: ");
395 failure |= check_precondition(msr.lo & BIT(1));
396
397 printk(BIOS_DEBUG, " VMXON outside SMX enable: ");
398 failure |= check_precondition(msr.lo & FEATURE_ENABLE_VMX);
399
400 printk(BIOS_DEBUG, " register is locked: ");
401 failure |= check_precondition(msr.lo & BIT(0));
402
403 /* IA32_FEATURE_CONTROL enables getsec instructions */
404 printk(BIOS_DEBUG, " GETSEC (all instructions) is enabled: ");
405 failure |= check_precondition((msr.lo & 0xff00) == 0xff00);
406
407 /* Prevent crash and opt out early */
408 if (failure)
409 return true;
410
411 uint32_t eax = 0;
412 /*
413 * GetSec[CAPABILITIES]
414 * SAFER MODE EXTENSIONS REFERENCE.
415 * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D
416 * Must check BIT0 of TXT chipset has been detected by CPU.
417 */
418 if (!getsec_capabilities(&eax))
419 return true;
420
421 printk(BIOS_DEBUG, "TEE-TXT: GETSEC[CAPABILITIES] returned:\n");
422 printk(BIOS_DEBUG, " TXT capable chipset: %s\n", (eax & BIT(0)) ? "true" : "false");
423
424 printk(BIOS_DEBUG, " ENTERACCS available: %s\n", (eax & BIT(2)) ? "true" : "false");
425 printk(BIOS_DEBUG, " EXITAC available: %s\n", (eax & BIT(3)) ? "true" : "false");
426 printk(BIOS_DEBUG, " SENTER available: %s\n", (eax & BIT(4)) ? "true" : "false");
427 printk(BIOS_DEBUG, " SEXIT available: %s\n", (eax & BIT(5)) ? "true" : "false");
428 printk(BIOS_DEBUG, " PARAMETERS available: %s\n", (eax & BIT(6)) ? "true" : "false");
429
430 /*
431 * Causes #GP if function is not supported by getsec.
432 * SAFER MODE EXTENSIONS REFERENCE.
433 * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D
434 * Order Number: 325383-060US
435 */
436 if ((eax & 0x7d) != 0x7d)
437 failure = true;
438
439 const uint64_t status = read64((void *)TXT_SPAD);
440
441 if (status & ACMSTS_TXT_DISABLED) {
442 printk(BIOS_INFO, "TEE-TXT: TXT disabled by BIOS policy in FIT.\n");
443 failure = true;
444 }
445
446 /*
447 * Only the BSP must call getsec[ENTERACCS].
448 * SAFER MODE EXTENSIONS REFERENCE.
449 * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D
450 * Order Number: 325383-060US
451 */
452 if (!boot_cpu()) {
453 printk(BIOS_ERR, "TEE-TXT: BSP flag not set in APICBASE_MSR.\n");
454 failure = true;
455 }
456
457 /*
458 * There must be no MCEs pending.
459 * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D
460 * Order Number: 325383-060US
461 */
462 msr = rdmsr(IA32_MCG_STATUS);
463 if (msr.lo & 0x4) {
464 printk(BIOS_ERR, "TEE-TXT: IA32_MCG_STATUS.MCIP is set.\n");
465 failure = true;
466 }
467
468 if (!getsec_parameter(NULL, NULL, NULL, NULL, NULL, &txt_feature_flags)) {
469 return true;
470 } else {
471 printk(BIOS_DEBUG, "TEE-TXT: Machine Check Register: ");
472 if (txt_feature_flags & GETSEC_PARAMS_TXT_EXT_MACHINE_CHECK)
473 printk(BIOS_DEBUG, "preserved\n");
474 else
475 printk(BIOS_DEBUG, "must be clear\n");
476 }
477
478 if (!(txt_feature_flags & GETSEC_PARAMS_TXT_EXT_MACHINE_CHECK)) {
479 /*
480 * Make sure there are no uncorrectable MCE errors.
481 * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D
482 */
483 msr = rdmsr(IA32_MCG_CAP);
484 size_t max_mc_msr = msr.lo & MCA_BANKS_MASK;
485 for (size_t i = 0; i < max_mc_msr; i++) {
486 msr = rdmsr(IA32_MC0_STATUS + 4 * i);
487 if (!(msr.hi & MCA_STATUS_HI_UC))
488 continue;
489
490 printk(BIOS_ERR, "TEE-TXT: IA32_MC%zd_STATUS.UC is set.\n", i);
491 failure = true;
492 break;
493 }
494 }
495
496 /* Need to park all APs. */
497 if (CONFIG(PARALLEL_MP_AP_WORK))
498 mp_park_aps();
499
500 return failure;
501}