coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
logging.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/mmio.h>
4 #include <console/console.h>
5 #include <cpu/x86/smm.h>
6 #include <types.h>
7 
8 #include "txt.h"
9 #include "txt_getsec.h"
10 #include "txt_register.h"
11 
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 
32 /**
33  * Logs microcode or SINIT ACM errors.
34  * Does not log SBIOS ACM errors.
35  */
36 static 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 
48  printk(BIOS_ERR, " Type: %s\n",
50  }
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  **/
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)) {
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");
88  }
89 }
90 
91 /**
92  * Dump information about the provided ACM.
93  */
94 void 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 
121  printk(BIOS_INFO, " Chipset: %x\n", acm_header->chipset_id);
122  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;
129  printk(BIOS_INFO, " Flags: NPW signed (Non Production Worthy)\n");
130  break;
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) {
143  printk(BIOS_INFO, " Size: 64KB\n");
144  printk(BIOS_INFO, " CBnT: no\n");
145  break;
147  printk(BIOS_INFO, " Size: 128KB\n");
148  printk(BIOS_INFO, " CBnT: no\n");
149  break;
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  */
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",
188  intel_txt_chipset_is_production_fused() ? "true" : "false");
189 }
190 
192 {
193  struct txt_biosdataregion *bdr = NULL;
194 
195  uintptr_t tseg_base;
196  size_t tseg_size;
197 
198  smm_region(&tseg_base, &tseg_size);
199 
200  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 
207  printk(BIOS_DEBUG, "TEE-TXT: TSEG 0x%lx, size %zu MiB\n", tseg_base, tseg_size / MiB);
208  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 }
224 
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 }
static uint32_t read32(const void *addr)
Definition: mmio.h:22
uint64_t read64(const void *addr)
static uint8_t read8(const void *addr)
Definition: mmio.h:12
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define MiB
Definition: helpers.h:76
#define printk(level,...)
Definition: stdlib.h:16
static struct smmstore_params_info info
Definition: ramstage.c:12
bool getsec_parameter(uint32_t *version_mask, uint32_t *version_numbers_supported, uint32_t *max_size_acm_area, uint32_t *memory_type_mask, uint32_t *senter_function_disable, uint32_t *txt_feature_flags)
Get information as returned by getsec[PARAMETER].
Definition: getsec.c:89
void smm_region(uintptr_t *start, size_t *size)
Definition: memmap.c:50
unsigned int type
Definition: edid.c:57
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_CRIT
BIOS_CRIT - Recovery unlikely.
Definition: loglevel.h:56
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
int intel_txt_log_acm_error(const uint32_t acm_error)
Dump the ACM error status bits.
Definition: common.c:49
bool intel_txt_chipset_is_production_fused(void)
Definition: common.c:149
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21
unsigned long long uint64_t
Definition: stdint.h:17
unsigned char uint8_t
Definition: stdint.h:8
uint16_t header_version[2]
Definition: txt_register.h:195
uint32_t size
Definition: txt_register.h:200
uint16_t txt_svn
Definition: txt_register.h:201
uint16_t se_svn
Definition: txt_register.h:202
uint16_t module_type
Definition: txt_register.h:192
uint16_t module_sub_type
Definition: txt_register.h:193
uint32_t scratch_size
Definition: txt_register.h:211
uint32_t module_vendor
Definition: txt_register.h:198
uint16_t flags
Definition: txt_register.h:197
uint16_t chipset_id
Definition: txt_register.h:196
uint32_t date
Definition: txt_register.h:199
uint32_t header_len
Definition: txt_register.h:194
uint32_t bios_sinit_size
Definition: txt_register.h:276
void txt_dump_regions(void)
Definition: logging.c:191
void intel_txt_log_bios_acm_error(void)
Dump useful informaation about the BIOS ACM state.
Definition: logging.c:58
void txt_dump_getsec_parameters(void)
Definition: logging.c:225
void txt_dump_chipset_info(void)
Dump information about the chipset's TXT capabilities.
Definition: logging.c:177
void txt_dump_acm_info(const struct acm_header_v0 *acm_header)
Dump information about the provided ACM.
Definition: logging.c:94
const char * intel_txt_processor_error_type(uint8_t type)
Definition: logging.c:12
static void log_txt_error(const char *phase)
Logs microcode or SINIT ACM errors.
Definition: logging.c:36
#define TXT_DIDVID
Definition: txt_register.h:62
#define TXT_ERROR
Definition: txt_register.h:25
#define ACM_FORMAT_SIZE_64KB
Definition: txt_register.h:156
#define TXT_ESTS
Definition: txt_register.h:17
#define ACMERROR_TXT_EXTERNAL
Definition: txt_register.h:27
#define TXT_HEAP_SIZE
Definition: txt_register.h:79
#define TXT_SPAD
Definition: txt_register.h:50
#define INTEL_ACM_VENDOR
Definition: txt_register.h:149
#define TXT_MSEG_SIZE
Definition: txt_register.h:85
#define TXT_ESTS_TXT_RESET_STS
Definition: txt_register.h:18
@ CHIPSET_ACM
Definition: txt_register.h:178
#define TXT_ERROR_MASK
Definition: txt_register.h:44
#define TXT_HEAP_BASE
Definition: txt_register.h:78
#define GETSEC_PARAMS_TXT_EXT_MACHINE_CHECK
Definition: txt_register.h:146
#define ACM_FORMAT_SIZE_128KB
Definition: txt_register.h:157
#define ACM_FORMAT_FLAGS_NPW
Definition: txt_register.h:152
#define TXT_SINIT_SIZE
Definition: txt_register.h:75
#define ACM_FORMAT_FLAGS_PW
Definition: txt_register.h:151
#define GETSEC_PARAMS_TXT_EXT_CRTM_SUPPORT
Definition: txt_register.h:145
#define TXT_ACM_KEY_HASH
Definition: txt_register.h:95
#define TXT_ACM_KEY_HASH_LEN
Definition: txt_register.h:96
#define TXT_MSEG_BASE
Definition: txt_register.h:84
#define ACMERROR_TXT_VALID
Definition: txt_register.h:26
#define ACM_FORMAT_SIZE_256KB
Definition: txt_register.h:158
#define TXT_SINIT_BASE
Definition: txt_register.h:74
#define ACM_FORMAT_FLAGS_DEBUG
Definition: txt_register.h:153
#define TXT_BIOSACM_ERRORCODE
Definition: txt_register.h:91