master
c 622 lines 24.6 KB
Raw
1 /*
2 * QTest testcases for TPM TIS on I2C (derived from TPM TIS test)
3 *
4 * Copyright (c) 2023 IBM Corporation
5 * Copyright (c) 2023 Red Hat, Inc.
6 *
7 * Authors:
8 * Stefan Berger <stefanb@linux.ibm.com>
9 * Marc-André Lureau <marcandre.lureau@redhat.com>
10 *
11 * This work is licensed under the terms of the GNU GPL, version 2 or later.
12 * See the COPYING file in the top-level directory.
13 */
14
15 #include "qemu/osdep.h"
16 #include <glib/gstdio.h>
17
18 #include "libqtest-single.h"
19 #include "hw/acpi/tpm.h"
20 #include "hw/pci/pci_ids.h"
21 #include "qtest_aspeed.h"
22 #include "tpm-emu.h"
23 #include "tpm-tis-i2c-util.h"
24
25 #define DEBUG_TIS_TEST 0
26
27 #define DPRINTF(fmt, ...) do { \
28 if (DEBUG_TIS_TEST) { \
29 printf(fmt, ## __VA_ARGS__); \
30 } \
31 } while (0)
32
33 #define DPRINTF_ACCESS \
34 DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \
35 __func__, __LINE__, locty, l, access, pending_request_flag)
36
37 #define DPRINTF_STS \
38 DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts)
39
40 static const uint8_t TPM_CMD[12] =
41 "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00";
42
43
44 static void tpm_tis_i2c_test_basic(const void *data)
45 {
46 uint8_t access;
47 uint32_t v, v2;
48
49 /*
50 * All register accesses below must work without locality 0 being the
51 * active locality. Therefore, ensure access is released.
52 */
53 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_ACCESS,
54 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
55 access = tpm_tis_i2c_readb(global_qtest, 0, TPM_I2C_REG_ACCESS);
56 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
57 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
58
59 /* read interrupt capability -- none are supported */
60 v = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_INT_CAPABILITY);
61 g_assert_cmpint(v, ==, 0);
62
63 /* try to enable all interrupts */
64 tpm_tis_i2c_writel(global_qtest, 0, TPM_I2C_REG_INT_ENABLE, 0xffffffff);
65 v = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_INT_ENABLE);
66 /* none could be enabled */
67 g_assert_cmpint(v, ==, 0);
68
69 /* enable csum */
70 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_DATA_CSUM_ENABLE,
71 TPM_DATA_CSUM_ENABLED);
72 /* check csum enable register has bit 0 set */
73 v = tpm_tis_i2c_readb(global_qtest, 0, TPM_I2C_REG_DATA_CSUM_ENABLE);
74 g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
75 /* reading it as 32bit register returns same result */
76 v = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_DATA_CSUM_ENABLE);
77 g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
78
79 /* disable csum */
80 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_DATA_CSUM_ENABLE, 0);
81 /* check csum enable register has bit 0 clear */
82 v = tpm_tis_i2c_readb(global_qtest, 0, TPM_I2C_REG_DATA_CSUM_ENABLE);
83 g_assert_cmpint(v, ==, 0);
84
85 /* write to unsupported register '1' */
86 tpm_tis_i2c_writel(global_qtest, 0, 1, 0x12345678);
87 v = tpm_tis_i2c_readl(global_qtest, 0, 1);
88 g_assert_cmpint(v, ==, 0xffffffff);
89
90 /* request use of locality */
91 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_ACCESS,
92 TPM_TIS_ACCESS_REQUEST_USE);
93
94 /* read byte from STS + 3 */
95 v = tpm_tis_i2c_readb(global_qtest, 0, TPM_I2C_REG_STS + 3);
96 g_assert_cmpint(v, ==, 0);
97
98 /* check STS after writing to STS + 3 */
99 v = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_STS);
100 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_STS + 3, 0xf);
101 v2 = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_STS);
102 g_assert_cmpint(v, ==, v2);
103
104 /* release access */
105 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_ACCESS,
106 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
107
108 /* select locality 5 -- must not be possible */
109 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_LOC_SEL, 5);
110 v = tpm_tis_i2c_readb(global_qtest, 0, TPM_I2C_REG_LOC_SEL);
111 g_assert_cmpint(v, ==, 0);
112 }
113
114 static void tpm_tis_i2c_test_check_localities(const void *data)
115 {
116 uint8_t locty, l;
117 uint8_t access;
118 uint32_t capability, i2c_cap;
119 uint32_t didvid;
120 uint32_t rid;
121
122 for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) {
123 access = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_ACCESS);
124 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
125 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
126
127 capability = tpm_tis_i2c_readl(global_qtest, locty,
128 TPM_I2C_REG_INTF_CAPABILITY);
129 i2c_cap = (TPM_I2C_CAP_INTERFACE_TYPE |
130 TPM_I2C_CAP_INTERFACE_VER |
131 TPM_I2C_CAP_TPM2_FAMILY |
132 TPM_I2C_CAP_LOCALITY_CAP |
133 TPM_I2C_CAP_BUS_SPEED |
134 TPM_I2C_CAP_DEV_ADDR_CHANGE);
135 g_assert_cmpint(capability, ==, i2c_cap);
136
137 didvid = tpm_tis_i2c_readl(global_qtest, locty, TPM_I2C_REG_DID_VID);
138 g_assert_cmpint(didvid, ==, (1 << 16) | PCI_VENDOR_ID_IBM);
139
140 rid = tpm_tis_i2c_readl(global_qtest, locty, TPM_I2C_REG_RID);
141 g_assert_cmpint(rid, !=, 0);
142 g_assert_cmpint(rid, !=, 0xffffffff);
143
144 /* locality selection must be at locty */
145 l = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_LOC_SEL);
146 g_assert_cmpint(l, ==, locty);
147 }
148 }
149
150 static void tpm_tis_i2c_test_check_access_reg(const void *data)
151 {
152 uint8_t locty;
153 uint8_t access;
154
155 /* do not test locality 4 (hw only) */
156 for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) {
157 access = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_ACCESS);
158 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
159 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
160
161 /* request use of locality */
162 tpm_tis_i2c_writeb(global_qtest, locty, TPM_I2C_REG_ACCESS,
163 TPM_TIS_ACCESS_REQUEST_USE);
164
165 access = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_ACCESS);
166 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
167 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
168 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
169
170 /* release access */
171 tpm_tis_i2c_writeb(global_qtest, locty, TPM_I2C_REG_ACCESS,
172 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
173 access = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_ACCESS);
174 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
175 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
176 }
177 }
178
179 /*
180 * Test case for seizing access by a higher number locality
181 */
182 static void tpm_tis_i2c_test_check_access_reg_seize(const void *data)
183 {
184 int locty, l;
185 uint8_t access;
186 uint8_t pending_request_flag;
187
188 /* do not test locality 4 (hw only) */
189 for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) {
190 pending_request_flag = 0;
191
192 access = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_ACCESS);
193 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
194 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
195
196 /* request use of locality */
197 tpm_tis_i2c_writeb(global_qtest, locty,
198 TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE);
199 access = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_ACCESS);
200 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
201 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
202 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
203
204 /* lower localities cannot seize access */
205 for (l = 0; l < locty; l++) {
206 /* lower locality is not active */
207 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
208 DPRINTF_ACCESS;
209 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
210 pending_request_flag |
211 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
212
213 /* try to request use from 'l' */
214 tpm_tis_i2c_writeb(global_qtest, l,
215 TPM_I2C_REG_ACCESS,
216 TPM_TIS_ACCESS_REQUEST_USE);
217
218 /*
219 * requesting use from 'l' was not possible;
220 * we must see REQUEST_USE and possibly PENDING_REQUEST
221 */
222 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
223 DPRINTF_ACCESS;
224 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
225 TPM_TIS_ACCESS_REQUEST_USE |
226 pending_request_flag |
227 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
228
229 /*
230 * locality 'locty' must be unchanged;
231 * we must see PENDING_REQUEST
232 */
233 access = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_ACCESS);
234 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
235 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
236 TPM_TIS_ACCESS_PENDING_REQUEST |
237 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
238
239 /* try to seize from 'l' */
240 tpm_tis_i2c_writeb(global_qtest, l,
241 TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_SEIZE);
242 /* seize from 'l' was not possible */
243 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
244 DPRINTF_ACCESS;
245 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
246 TPM_TIS_ACCESS_REQUEST_USE |
247 pending_request_flag |
248 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
249
250 /* locality 'locty' must be unchanged */
251 access = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_ACCESS);
252 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
253 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
254 TPM_TIS_ACCESS_PENDING_REQUEST |
255 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
256
257 /*
258 * on the next loop we will have a PENDING_REQUEST flag
259 * set for locality 'l'
260 */
261 pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST;
262 }
263
264 /*
265 * higher localities can 'seize' access but not 'request use';
266 * note: this will activate first l+1, then l+2 etc.
267 */
268 for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) {
269 /* try to 'request use' from 'l' */
270 tpm_tis_i2c_writeb(global_qtest, l, TPM_I2C_REG_ACCESS,
271 TPM_TIS_ACCESS_REQUEST_USE);
272
273 /*
274 * requesting use from 'l' was not possible; we should see
275 * REQUEST_USE and may see PENDING_REQUEST
276 */
277 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
278 DPRINTF_ACCESS;
279 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
280 TPM_TIS_ACCESS_REQUEST_USE |
281 pending_request_flag |
282 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
283
284 /*
285 * locality 'l-1' must be unchanged; we should always
286 * see PENDING_REQUEST from 'l' requesting access
287 */
288 access = tpm_tis_i2c_readb(global_qtest, l - 1, TPM_I2C_REG_ACCESS);
289 DPRINTF_ACCESS;
290 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
291 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
292 TPM_TIS_ACCESS_PENDING_REQUEST |
293 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
294
295 /* try to seize from 'l' */
296 tpm_tis_i2c_writeb(global_qtest, l, TPM_I2C_REG_ACCESS,
297 TPM_TIS_ACCESS_SEIZE);
298
299 /* seize from 'l' was possible */
300 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
301 DPRINTF_ACCESS;
302 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
303 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
304 pending_request_flag |
305 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
306
307 /* l - 1 should show that it has BEEN_SEIZED */
308 access = tpm_tis_i2c_readb(global_qtest, l - 1, TPM_I2C_REG_ACCESS);
309 DPRINTF_ACCESS;
310 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
311 TPM_TIS_ACCESS_BEEN_SEIZED |
312 pending_request_flag |
313 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
314
315 /* clear the BEEN_SEIZED flag and make sure it's gone */
316 tpm_tis_i2c_writeb(global_qtest, l - 1, TPM_I2C_REG_ACCESS,
317 TPM_TIS_ACCESS_BEEN_SEIZED);
318
319 access = tpm_tis_i2c_readb(global_qtest, l - 1, TPM_I2C_REG_ACCESS);
320 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
321 pending_request_flag |
322 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
323 }
324
325 /*
326 * PENDING_REQUEST will not be set if locty = 0 since all localities
327 * were active; in case of locty = 1, locality 0 will be active
328 * but no PENDING_REQUEST anywhere
329 */
330 if (locty <= 1) {
331 pending_request_flag = 0;
332 }
333
334 /* release access from l - 1; this activates locty - 1 */
335 l--;
336
337 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
338 DPRINTF_ACCESS;
339
340 DPRINTF("%s: %d: relinquishing control on l = %d\n",
341 __func__, __LINE__, l);
342 tpm_tis_i2c_writeb(global_qtest, l, TPM_I2C_REG_ACCESS,
343 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
344
345 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
346 DPRINTF_ACCESS;
347 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
348 pending_request_flag |
349 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
350
351 for (l = locty - 1; l >= 0; l--) {
352 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
353 DPRINTF_ACCESS;
354 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
355 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
356 pending_request_flag |
357 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
358
359 /* release this locality */
360 tpm_tis_i2c_writeb(global_qtest, l, TPM_I2C_REG_ACCESS,
361 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
362
363 if (l == 1) {
364 pending_request_flag = 0;
365 }
366 }
367
368 /* no locality may be active now */
369 for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) {
370 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
371 DPRINTF_ACCESS;
372 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
373 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
374 }
375 }
376 }
377
378 /*
379 * Test case for getting access when higher number locality relinquishes access
380 */
381 static void tpm_tis_i2c_test_check_access_reg_release(const void *data)
382 {
383 int locty, l;
384 uint8_t access;
385 uint8_t pending_request_flag;
386
387 /* do not test locality 4 (hw only) */
388 for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) {
389 pending_request_flag = 0;
390
391 access = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_ACCESS);
392 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
393 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
394
395 /* request use of locality */
396 tpm_tis_i2c_writeb(global_qtest, locty, TPM_I2C_REG_ACCESS,
397 TPM_TIS_ACCESS_REQUEST_USE);
398 access = tpm_tis_i2c_readb(global_qtest, locty, TPM_I2C_REG_ACCESS);
399 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
400 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
401 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
402
403 /* request use of all other localities */
404 for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) {
405 if (l == locty) {
406 continue;
407 }
408 /*
409 * request use of locality 'l' -- we MUST see REQUEST USE and
410 * may see PENDING_REQUEST
411 */
412 tpm_tis_i2c_writeb(global_qtest, l, TPM_I2C_REG_ACCESS,
413 TPM_TIS_ACCESS_REQUEST_USE);
414 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
415 DPRINTF_ACCESS;
416 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
417 TPM_TIS_ACCESS_REQUEST_USE |
418 pending_request_flag |
419 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
420 pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST;
421 }
422 /* release locality 'locty' */
423 tpm_tis_i2c_writeb(global_qtest, locty, TPM_I2C_REG_ACCESS,
424 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
425 /*
426 * highest locality should now be active; release it and make sure the
427 * next highest locality is active afterwards
428 */
429 for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) {
430 if (l == locty) {
431 continue;
432 }
433 /* 'l' should be active now */
434 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
435 DPRINTF_ACCESS;
436 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
437 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
438 pending_request_flag |
439 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
440 /* 'l' relinquishes access */
441 tpm_tis_i2c_writeb(global_qtest, l, TPM_I2C_REG_ACCESS,
442 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
443 access = tpm_tis_i2c_readb(global_qtest, l, TPM_I2C_REG_ACCESS);
444 DPRINTF_ACCESS;
445 if (l == 1 || (locty <= 1 && l == 2)) {
446 pending_request_flag = 0;
447 }
448 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
449 pending_request_flag |
450 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
451 }
452 }
453 }
454
455 /*
456 * Test case for transmitting packets
457 */
458 static void tpm_tis_i2c_test_check_transmit(const void *data)
459 {
460 const TPMTestState *s = data;
461 uint8_t access;
462 uint32_t sts, v;
463 uint16_t bcount, csum, bcount2;
464 size_t i;
465
466 /* enable csum */
467 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_DATA_CSUM_ENABLE,
468 TPM_DATA_CSUM_ENABLED);
469 /* check csum enable register has bit 0 set */
470 v = tpm_tis_i2c_readb(global_qtest, 0, TPM_I2C_REG_DATA_CSUM_ENABLE);
471 g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
472 /* reading it as 32bit register returns same result */
473 v = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_DATA_CSUM_ENABLE);
474 g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
475
476 /* request use of locality 0 */
477 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_ACCESS,
478 TPM_TIS_ACCESS_REQUEST_USE);
479 access = tpm_tis_i2c_readb(global_qtest, 0, TPM_I2C_REG_ACCESS);
480 g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
481 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
482 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
483
484 sts = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_STS);
485 DPRINTF_STS;
486
487 g_assert_cmpint(sts & 0xff, ==, 0);
488
489 bcount = (sts >> 8) & 0xffff;
490 g_assert_cmpint(bcount, >=, 128);
491
492 /* read bcount from STS + 1 must work also */
493 bcount2 = tpm_tis_i2c_readw(global_qtest, 0, TPM_I2C_REG_STS + 1);
494 g_assert_cmpint(bcount, ==, bcount2);
495
496 /* ic2 must have bits 26-31 zero */
497 g_assert_cmpint(sts & (0x1f << 26), ==, 0);
498
499 tpm_tis_i2c_writel(global_qtest, 0, TPM_I2C_REG_STS,
500 TPM_TIS_STS_COMMAND_READY);
501 sts = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_STS);
502 DPRINTF_STS;
503 g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY);
504
505 /* transmit command */
506 for (i = 0; i < sizeof(TPM_CMD); i++) {
507 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_DATA_FIFO, TPM_CMD[i]);
508 sts = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_STS);
509 DPRINTF_STS;
510 if (i < sizeof(TPM_CMD) - 1) {
511 g_assert_cmpint(sts & 0xff, ==,
512 TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
513 } else {
514 g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID);
515 }
516 g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount);
517 }
518 /* read the checksum */
519 csum = tpm_tis_i2c_readw(global_qtest, 0, TPM_I2C_REG_DATA_CSUM_GET);
520 g_assert_cmpint(csum, ==, 0x6733);
521
522 /* start processing */
523 tpm_tis_i2c_writeb(global_qtest, 0, TPM_I2C_REG_STS, TPM_TIS_STS_TPM_GO);
524
525 uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND;
526 do {
527 sts = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_STS);
528 if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
529 break;
530 }
531 } while (g_get_monotonic_time() < end_time);
532
533 sts = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_STS);
534 DPRINTF_STS;
535 g_assert_cmpint(sts & 0xff, == ,
536 TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE);
537 bcount = (sts >> 8) & 0xffff;
538
539 /* read response */
540 uint8_t tpm_msg[sizeof(struct tpm_hdr)];
541 g_assert_cmpint(sizeof(tpm_msg), ==, bcount);
542
543 for (i = 0; i < sizeof(tpm_msg); i++) {
544 tpm_msg[i] = tpm_tis_i2c_readb(global_qtest, 0, TPM_I2C_REG_DATA_FIFO);
545 sts = tpm_tis_i2c_readl(global_qtest, 0, TPM_I2C_REG_STS);
546 DPRINTF_STS;
547 if (sts & TPM_TIS_STS_DATA_AVAILABLE) {
548 g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount);
549 }
550 }
551 g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg));
552
553 /* relinquish use of locality 0 */
554 tpm_tis_i2c_writeb(global_qtest, 0,
555 TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_ACTIVE_LOCALITY);
556 access = tpm_tis_i2c_readb(global_qtest, 0, TPM_I2C_REG_ACCESS);
557 }
558
559 int main(int argc, char **argv)
560 {
561 int ret;
562 char *args;
563 char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-i2c-test.XXXXXX", NULL);
564 GThread *thread;
565 TPMTestState test;
566
567 module_call_init(MODULE_INIT_QOM);
568 g_test_init(&argc, &argv, NULL);
569
570 test.addr = g_new0(SocketAddress, 1);
571 test.addr->type = SOCKET_ADDRESS_TYPE_UNIX;
572 test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL);
573 g_mutex_init(&test.data_mutex);
574 g_cond_init(&test.data_cond);
575 test.data_cond_signal = false;
576 test.tpm_version = TPM_VERSION_2_0;
577
578 thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
579 tpm_emu_test_wait_cond(&test);
580
581 aspeed_bus_addr = ast2600_i2c_calc_bus_addr(I2C_DEV_BUS_NUM);
582
583 args = g_strdup_printf(
584 "-machine rainier-bmc -accel tcg "
585 "-chardev socket,id=chr,path=%s "
586 "-tpmdev emulator,id=tpm0,chardev=chr "
587 "-device tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.%d,address=0x%x",
588 test.addr->u.q_unix.path,
589 I2C_DEV_BUS_NUM,
590 I2C_SLAVE_ADDR);
591 qtest_start(args);
592
593 qtest_add_data_func("/tpm-tis-i2c/test_basic", &test,
594 tpm_tis_i2c_test_basic);
595
596 qtest_add_data_func("/tpm-tis-i2c/test_check_localities", &test,
597 tpm_tis_i2c_test_check_localities);
598
599 qtest_add_data_func("/tpm-tis-i2c/check_access_reg", &test,
600 tpm_tis_i2c_test_check_access_reg);
601
602 qtest_add_data_func("/tpm-tis-i2c/check_access_reg_seize", &test,
603 tpm_tis_i2c_test_check_access_reg_seize);
604
605 qtest_add_data_func("/tpm-tis-i2c/check_access_reg_release", &test,
606 tpm_tis_i2c_test_check_access_reg_release);
607
608 qtest_add_data_func("/tpm-tis-i2c/test_check_transmit", &test,
609 tpm_tis_i2c_test_check_transmit);
610
611 ret = g_test_run();
612
613 qtest_end();
614
615 g_thread_join(thread);
616 g_unlink(test.addr->u.q_unix.path);
617 qapi_free_SocketAddress(test.addr);
618 g_rmdir(tmp_path);
619 g_free(tmp_path);
620 g_free(args);
621 return ret;
622 }