coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
getsec.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <cf9_reset.h>
4 #include <console/console.h>
6 #include <cpu/x86/cr.h>
7 #include <cpu/x86/cache.h>
8 #include <cpu/x86/mp.h>
9 #include <cpu/x86/msr.h>
10 #include <types.h>
11 
12 #include "txt_register.h"
13 #include "txt_getsec.h"
14 
15 /**
16  * Check for SMX support and enable it if possible.
17  *
18  * Returns false on error, true on success.
19  */
20 static bool getsec_enabled(void)
21 {
22  unsigned int ecx = cpuid_ecx(1);
23  /*
24  * Check if SMX and VMX is supported by CPU.
25  */
26  if (!(ecx & CPUID_SMX) || !(ecx & CPUID_VMX)) {
27  printk(BIOS_ERR, "SMX/VMX not supported by CPU\n");
28  return false;
29  }
30  /*
31  * This requirement is not needed for ENTERACCS, but for SENTER (see SDM).
32  * Skip check in romstage because IA32_FEATURE_CONTROL cannot be unlocked
33  * even after a global reset e.g. on Sandy/IvyBridge. However the register
34  * gets set properly in ramstage where all CPUs are already initialized.
35  */
37  /*
38  * Check if SMX, VMX and GetSec instructions haven't been disabled.
39  */
41  if ((msr.lo & 0xff06) != 0xff06) {
42  printk(BIOS_ERR, "GETSEC not enabled in IA32_FEATURE_CONTROL MSR\n");
43  return false;
44  }
45  }
46  /*
47  * Enable SMX. Required to execute GetSec instruction.
48  * Chapter 2.2.4.3
49  * Intel TXT Software Development Guide (Document: 315168-015)
50  */
52 
53  return true;
54 }
55 
57 {
59 
60  if (!(msr.lo & FEATURE_CONTROL_LOCK_BIT)) {
61  /*
62  * MSR not locked, enable necessary GETSEC and VMX settings.
63  * We do not lock this MSR here, though.
64  */
65  msr.lo |= 0xff06;
67 
68  } else if ((msr.lo & 0xff06) != 0xff06) {
69  /*
70  * MSR is locked without necessary GETSEC and VMX settings.
71  * This can happen after internally reflashing a coreboot
72  * image with different settings, and then doing a warm
73  * reboot. Perform a full reset in order to unlock the MSR.
74  */
76  "IA32_FEATURE_CONTROL MSR locked with GETSEC and/or VMX disabled.\n"
77  "Will perform a full reset to unlock this MSR.\n");
78 
79  full_reset();
80  }
81 }
82 
83 /**
84  * Get information as returned by getsec[PARAMETER].
85  * Arguments can be set to NULL if not needed.
86  *
87  * Returns false on error, true on success.
88  */
89 bool getsec_parameter(uint32_t *version_mask,
90  uint32_t *version_numbers_supported,
91  uint32_t *max_size_acm_area,
92  uint32_t *memory_type_mask,
93  uint32_t *senter_function_disable,
94  uint32_t *txt_feature_flags)
95 {
96  uint32_t i, eax, ebx, ecx;
97 
98  if (!getsec_enabled())
99  return false;
100 
101  /*
102  * SAFER MODE EXTENSIONS REFERENCE.
103  * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D
104  */
105  for (i = 0; i < 0x1f; i++) {
106  /* Getsec[PARAMETERS] */
107  asm volatile ("getsec\n"
108  : "=a" (eax), "=b" (ebx), "=c" (ecx)
109  : "a" (IA32_GETSEC_PARAMETERS), "b" (i) :);
110  switch (eax & 0x1f) {
111  case 0: /* NULL - Exit marker */
112  return true;
113  case 1: /* Supported AC module versions */
114  if (version_mask)
115  *version_mask = ebx;
116  if (version_numbers_supported)
117  *version_numbers_supported = ecx;
118  break;
119  case 2: /* Max size of authenticated code execution area */
120  if (max_size_acm_area)
121  *max_size_acm_area = eax & ~0x1f;
122  break;
123  case 3: /* External memory types supported during AC mode */
124  if (memory_type_mask)
125  *memory_type_mask = eax;
126  break;
127  case 4: /* Selective SENTER functionality control */
128  if (senter_function_disable)
129  *senter_function_disable = eax & (0x3f00);
130  break;
131  case 5: /* TXT extensions support */
132  if (txt_feature_flags)
133  *txt_feature_flags = eax & (0x60);
134  break;
135  }
136  }
137 
138  return true;
139 }
140 
141 /**
142  * Get capabilities as returned by getsec[CAPABILITIES].
143  *
144  * Returns false on error, true on success.
145  */
146 
148 {
149  if (!getsec_enabled())
150  return false;
151 
152  asm volatile ("getsec\n"
153  : "=a" (*eax)
154  : "a" (IA32_GETSEC_CAPABILITIES), "b" (0) :);
155 
156  return true;
157 }
static unsigned int cpuid_ecx(unsigned int op)
Definition: cpu.h:106
void full_reset(void)
Definition: cf9_reset.c:45
#define printk(level,...)
Definition: stdlib.h:16
#define CR4_SMXE
Definition: cr.h:126
static __always_inline void write_cr4(CRx_TYPE data)
Definition: cr.h:88
static __always_inline CRx_TYPE read_cr4(void)
Definition: cr.h:76
void enable_getsec_or_reset(void)
Definition: getsec.c:56
static bool getsec_enabled(void)
Check for SMX support and enable it if possible.
Definition: getsec.c:20
bool getsec_capabilities(uint32_t *eax)
Get capabilities as returned by getsec[CAPABILITIES].
Definition: getsec.c:147
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
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
#define IA32_FEATURE_CONTROL
Definition: msr.h:20
#define FEATURE_CONTROL_LOCK_BIT
Definition: msr.h:21
#define CPUID_VMX
Definition: msr.h:24
static __always_inline void wrmsr(unsigned int index, msr_t msr)
Definition: msr.h:157
#define CPUID_SMX
Definition: msr.h:25
#define BIOS_NOTICE
BIOS_NOTICE - Unexpected but relatively insignificant.
Definition: loglevel.h:100
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define ENV_ROMSTAGE_OR_BEFORE
Definition: rules.h:263
unsigned int uint32_t
Definition: stdint.h:14
unsigned int lo
Definition: msr.h:111
#define IA32_GETSEC_PARAMETERS
Definition: txt_register.h:141
#define IA32_GETSEC_CAPABILITIES
Definition: txt_register.h:137