1
2
3
4
5
6#include <common.h>
7#include <dm.h>
8#include <tpm-v1.h>
9#include <asm/state.h>
10#include <asm/unaligned.h>
11#include <linux/crc8.h>
12
13
14#define FIRMWARE_NV_INDEX 0x1007
15#define KERNEL_NV_INDEX 0x1008
16
17#define NV_DATA_PUBLIC_PERMISSIONS_OFFSET 60
18
19
20#define ROLLBACK_SPACE_KERNEL_VERSION 2
21#define ROLLBACK_SPACE_KERNEL_UID 0x4752574C
22
23struct rollback_space_kernel {
24
25 uint8_t struct_version;
26
27 uint32_t uid;
28
29 uint32_t kernel_versions;
30
31 uint8_t reserved[3];
32
33 uint8_t crc8;
34} __packed rollback_space_kernel;
35
36
37
38
39
40#define TPM_REQUEST_HEADER_LENGTH 10
41#define TPM_RESPONSE_HEADER_LENGTH 10
42
43
44enum {
45 NV_GLOBAL_LOCK,
46 NV_SEQ_FIRMWARE,
47 NV_SEQ_KERNEL,
48 NV_SEQ_COUNT,
49};
50
51
52#define NV_DATA_SIZE 0x20
53
54
55
56
57
58static struct tpm_state {
59 uint8_t nvdata[NV_SEQ_COUNT][NV_DATA_SIZE];
60} g_state;
61
62
63
64
65
66
67
68
69
70
71static int sandbox_tpm_read_state(const void *blob, int node)
72{
73 const char *prop;
74 int len;
75 int i;
76
77 if (!blob)
78 return 0;
79
80 for (i = 0; i < NV_SEQ_COUNT; i++) {
81 char prop_name[20];
82
83 sprintf(prop_name, "nvdata%d", i);
84 prop = fdt_getprop(blob, node, prop_name, &len);
85 if (prop && len == NV_DATA_SIZE)
86 memcpy(g_state.nvdata[i], prop, NV_DATA_SIZE);
87 }
88
89 return 0;
90}
91
92
93
94
95
96
97
98
99
100
101static int sandbox_tpm_write_state(void *blob, int node)
102{
103 int i;
104
105
106
107
108
109
110 for (i = 0; i < NV_SEQ_COUNT; i++) {
111 char prop_name[20];
112
113 sprintf(prop_name, "nvdata%d", i);
114 fdt_setprop(blob, node, prop_name, g_state.nvdata[i],
115 NV_DATA_SIZE);
116 }
117
118 return 0;
119}
120
121SANDBOX_STATE_IO(sandbox_tpm, "google,sandbox-tpm", sandbox_tpm_read_state,
122 sandbox_tpm_write_state);
123
124static int index_to_seq(uint32_t index)
125{
126 switch (index) {
127 case FIRMWARE_NV_INDEX:
128 return NV_SEQ_FIRMWARE;
129 case KERNEL_NV_INDEX:
130 return NV_SEQ_KERNEL;
131 case 0:
132 return NV_GLOBAL_LOCK;
133 }
134
135 printf("Invalid nv index %#x\n", index);
136 return -1;
137}
138
139static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf,
140 size_t send_size, uint8_t *recvbuf,
141 size_t *recv_len)
142{
143 struct tpm_state *tpm = dev_get_priv(dev);
144 uint32_t code, index, length, type;
145 uint8_t *data;
146 int seq;
147
148 code = get_unaligned_be32(sendbuf + sizeof(uint16_t) +
149 sizeof(uint32_t));
150 printf("tpm: %zd bytes, recv_len %zd, cmd = %x\n", send_size,
151 *recv_len, code);
152 print_buffer(0, sendbuf, 1, send_size, 0);
153 switch (code) {
154 case 0x65:
155 type = get_unaligned_be32(sendbuf + 14);
156 switch (type) {
157 case 4:
158 index = get_unaligned_be32(sendbuf + 18);
159 printf("Get flags index %#02x\n", index);
160 *recv_len = 22;
161 memset(recvbuf, '\0', *recv_len);
162 put_unaligned_be32(22, recvbuf +
163 TPM_RESPONSE_HEADER_LENGTH);
164 data = recvbuf + TPM_RESPONSE_HEADER_LENGTH +
165 sizeof(uint32_t);
166 switch (index) {
167 case FIRMWARE_NV_INDEX:
168 break;
169 case KERNEL_NV_INDEX:
170
171 put_unaligned_be32(1, data +
172 NV_DATA_PUBLIC_PERMISSIONS_OFFSET);
173 break;
174 }
175 break;
176 case 0x11:
177 index = get_unaligned_be32(sendbuf + 18);
178 printf("Get cap nv index %#02x\n", index);
179 put_unaligned_be32(22, recvbuf +
180 TPM_RESPONSE_HEADER_LENGTH);
181 break;
182 default:
183 printf(" ** Unknown 0x65 command type %#02x\n",
184 type);
185 return -1;
186 }
187 break;
188 case 0xcd:
189 index = get_unaligned_be32(sendbuf + 10);
190 length = get_unaligned_be32(sendbuf + 18);
191 seq = index_to_seq(index);
192 if (seq < 0)
193 return -1;
194 printf("tpm: nvwrite index=%#02x, len=%#02x\n", index, length);
195 memcpy(&tpm->nvdata[seq], sendbuf + 22, length);
196 *recv_len = 12;
197 memset(recvbuf, '\0', *recv_len);
198 break;
199 case 0xcf:
200 index = get_unaligned_be32(sendbuf + 10);
201 length = get_unaligned_be32(sendbuf + 18);
202 seq = index_to_seq(index);
203 if (seq < 0)
204 return -1;
205 printf("tpm: nvread index=%#02x, len=%#02x\n", index, length);
206 *recv_len = TPM_RESPONSE_HEADER_LENGTH + sizeof(uint32_t) +
207 length;
208 memset(recvbuf, '\0', *recv_len);
209 put_unaligned_be32(length, recvbuf +
210 TPM_RESPONSE_HEADER_LENGTH);
211 if (seq == NV_SEQ_KERNEL) {
212 struct rollback_space_kernel rsk;
213
214 data = recvbuf + TPM_RESPONSE_HEADER_LENGTH +
215 sizeof(uint32_t);
216 memset(&rsk, 0, sizeof(struct rollback_space_kernel));
217 rsk.struct_version = 2;
218 rsk.uid = ROLLBACK_SPACE_KERNEL_UID;
219 rsk.crc8 = crc8(0, (unsigned char *)&rsk,
220 offsetof(struct rollback_space_kernel,
221 crc8));
222 memcpy(data, &rsk, sizeof(rsk));
223 } else {
224 memcpy(recvbuf + TPM_RESPONSE_HEADER_LENGTH +
225 sizeof(uint32_t), &tpm->nvdata[seq], length);
226 }
227 break;
228 case 0x14:
229 case 0x15:
230 case 0x5d:
231 case 0x6f:
232 case 0x72:
233 case 0x99:
234 case 0x4000000a:
235 *recv_len = 12;
236 memset(recvbuf, '\0', *recv_len);
237 break;
238 default:
239 printf("Unknown tpm command %02x\n", code);
240 return -1;
241 }
242
243 return 0;
244}
245
246static int sandbox_tpm_get_desc(struct udevice *dev, char *buf, int size)
247{
248 if (size < 15)
249 return -ENOSPC;
250
251 return snprintf(buf, size, "sandbox TPM");
252}
253
254static int sandbox_tpm_probe(struct udevice *dev)
255{
256 struct tpm_state *tpm = dev_get_priv(dev);
257
258 memcpy(tpm, &g_state, sizeof(*tpm));
259
260 return 0;
261}
262
263static int sandbox_tpm_open(struct udevice *dev)
264{
265 return 0;
266}
267
268static int sandbox_tpm_close(struct udevice *dev)
269{
270 return 0;
271}
272
273static const struct tpm_ops sandbox_tpm_ops = {
274 .open = sandbox_tpm_open,
275 .close = sandbox_tpm_close,
276 .get_desc = sandbox_tpm_get_desc,
277 .xfer = sandbox_tpm_xfer,
278};
279
280static const struct udevice_id sandbox_tpm_ids[] = {
281 { .compatible = "google,sandbox-tpm" },
282 { }
283};
284
285U_BOOT_DRIVER(sandbox_tpm) = {
286 .name = "sandbox_tpm",
287 .id = UCLASS_TPM,
288 .of_match = sandbox_tpm_ids,
289 .ops = &sandbox_tpm_ops,
290 .probe = sandbox_tpm_probe,
291 .priv_auto_alloc_size = sizeof(struct tpm_state),
292};
293