1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/mmio.h>
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <cpu/intel/msr.h>
#include <stdint.h>
#include <security/intel/txt/txt.h>
#include "cbnt.h"
#define LOG(...) printk(BIOS_INFO, "CBnT: " __VA_ARGS__)
union sacm_info {
struct {
uint64_t nem_enabled : 1;
uint64_t tpm_type : 2;
uint64_t tpm_success : 1;
uint64_t facb : 1;
uint64_t measured_boot : 1;
uint64_t verified_boot : 1;
uint64_t revoked : 1;
uint64_t : 24;
uint64_t btg_cap : 1;
uint64_t : 1;
uint64_t txt_cap : 1;
uint64_t : 29;
};
msr_t msr;
uint64_t raw;
};
_Static_assert(sizeof(union sacm_info) == sizeof(uint64_t), "Wrong size of sacm_info");
static const char *const tpm_type[] = {
"No TPM",
"TPM 1.2",
"TPM 2.0",
"PTT",
};
union cbnt_bootstatus {
struct {
uint64_t : 59;
uint64_t bios_trusted : 1;
uint64_t txt_dis_pol : 1;
uint64_t btg_startup_err : 1;
uint64_t txt_err : 1;
uint64_t type7 : 1;
};
uint64_t raw;
};
_Static_assert(sizeof(union cbnt_bootstatus) == sizeof(uint64_t),
"Wrong size of cbnt_bootstatus");
union cbnt_errorcode {
struct {
uint32_t type : 15;
uint32_t : 15;
uint32_t external : 1;
uint32_t valid : 1;
} microcode;
struct {
uint32_t ac_type : 4;
uint32_t class : 6;
uint32_t major : 5;
uint32_t minor_invalid : 1;
uint32_t minor : 9;
uint32_t : 5;
uint32_t external : 1;
uint32_t valid : 1;
} sinit;
uint32_t raw;
};
_Static_assert(sizeof(union cbnt_errorcode) == sizeof(uint32_t),
"Wrong size of cbnt_errorcode");
union cbnt_biosacm_errorcode {
struct {
uint32_t ac_type : 4;
uint32_t class : 6;
uint32_t major : 5;
uint32_t minor_invalid : 1;
uint32_t minor : 12;
uint32_t : 2;
uint32_t external : 1;
uint32_t valid : 1;
} txt;
struct {
uint32_t ac_type : 4;
uint32_t class : 6;
uint32_t error : 5;
uint32_t acm_started : 1;
uint32_t km_id : 4;
uint32_t bp : 5;
uint32_t : 6;
uint32_t valid : 1;
} btg;
uint32_t raw;
};
_Static_assert(sizeof(union cbnt_biosacm_errorcode) == sizeof(uint32_t),
"Wrong size of cbnt_biosacm_errorcode");
static const char *decode_err_type(uint8_t type)
{
switch (type) {
case 0:
return "BIOS ACM Error";
case 1:
return "SINIT ACM Error";
case 3:
return "Boot Guard Error";
default:
return "Reserved";
}
}
void intel_cbnt_log_registers(void)
{
const union sacm_info acm_info = { .msr = rdmsr(MSR_BOOT_GUARD_SACM_INFO) };
LOG("SACM INFO MSR (0x13A) raw: 0x%016llx\n", acm_info.raw);
LOG(" NEM status: %u\n", acm_info.nem_enabled);
LOG(" TPM type: %s\n", tpm_type[acm_info.tpm_type]);
LOG(" TPM succes: %u\n", acm_info.tpm_success);
LOG(" FACB: %u\n", acm_info.facb);
LOG(" measured boot: %u\n", acm_info.measured_boot);
LOG(" verified boot: %u\n", acm_info.verified_boot);
LOG(" revoked: %u\n", acm_info.revoked);
LOG(" BtG capable: %u\n", acm_info.btg_cap);
LOG(" TXT capable: %u\n", acm_info.txt_cap);
const union cbnt_bootstatus btsts = {
.raw = read64p(CBNT_BOOTSTATUS),
};
LOG("BOOTSTATUS (0xA0) raw: 0x%016llx\n", btsts.raw);
LOG(" Bios trusted: %u\n", btsts.bios_trusted);
LOG(" TXT disabled by policy: %u\n", btsts.txt_dis_pol);
LOG(" Bootguard startup error: %u\n", btsts.btg_startup_err);
LOG(" TXT ucode or ACM error: %u\n", btsts.txt_err);
LOG(" TXT measurement type 7: %u\n", btsts.type7);
const union cbnt_errorcode err = {
.raw = read32p(CBNT_ERRORCODE),
};
LOG("ERRORCODE (0x30) raw: 0x%08x\n", err.raw);
/* It looks like the hardware does not set the txt error bit properly */
const bool txt_err_valid = btsts.txt_err || true;
if (txt_err_valid && !btsts.txt_dis_pol) {
if (err.microcode.valid && !err.microcode.external) {
LOG("ERRORCODE is ucode error\n");
LOG(" type: %s\n",
intel_txt_processor_error_type(err.microcode.type));
} else if (err.sinit.valid && err.sinit.external) {
LOG("ERRORCODE is SINIT error\n");
const char *type = decode_err_type(err.sinit.ac_type);
LOG(" AC Module Type: %s\n", type);
LOG(" class: 0x%x\n", err.sinit.class);
LOG(" major: 0x%x\n", err.sinit.major);
if (!err.sinit.minor_invalid)
LOG(" minor: 0x%x\n", err.sinit.minor);
}
} else if (txt_err_valid && btsts.txt_dis_pol) {
LOG("TXT disabled in Policy\n");
}
const union cbnt_biosacm_errorcode biosacm_err = {
.raw = read32p(CBNT_BIOSACM_ERRORCODE),
};
LOG("BIOSACM_ERRORCODE (0x328) raw: 0x%08x\n", biosacm_err.raw);
if (txt_err_valid && biosacm_err.txt.valid) {
LOG("BIOSACM_ERRORCODE: TXT ucode or ACM error\n");
const char *type = decode_err_type(biosacm_err.txt.ac_type);
LOG(" AC Module Type: %s\n", type);
LOG(" class: 0x%x\n", biosacm_err.txt.class);
LOG(" major: 0x%x\n", biosacm_err.txt.major);
if (!biosacm_err.txt.minor_invalid)
LOG(" minor: 0x%x\n", biosacm_err.txt.minor);
LOG(" External: 0x%x\n", biosacm_err.txt.external);
}
if (btsts.btg_startup_err && biosacm_err.btg.valid) {
LOG("BIOSACM_ERRORCODE: Bootguard error\n");
const char *type = decode_err_type(biosacm_err.btg.ac_type);
LOG(" AC Module Type: %s\n", type);
LOG(" class: 0x%x\n", biosacm_err.btg.class);
LOG(" error: 0x%x\n", biosacm_err.btg.error);
LOG(" ACM started: %u\n", biosacm_err.btg.acm_started);
LOG(" KMID: 0x%x\n", biosacm_err.btg.km_id);
LOG(" BootPolicies: 0x%x\n", biosacm_err.btg.bp);
}
}
|