1 // Implementation of a TPM driver for the TPM TIS interface
2 //
3 // Copyright (C) 2006-2011 IBM Corporation
4 //
5 // Authors:
6 // Stefan Berger <stefanb@linux.vnet.ibm.com>
7 //
8 // This file may be distributed under the terms of the GNU LGPLv3 license.
9
10 #include "byteorder.h" // be32_to_cpu
11 #include "config.h" // CONFIG_TPM_TIS_SHA1THRESHOLD
12 #include "hw/tpm_drivers.h" // struct tpm_driver
13 #include "std/tcg.h" // TCG_RESPONSE_TIMEOUT
14 #include "output.h" // warn_timeout
15 #include "stacks.h" // yield
16 #include "string.h" // memcpy
17 #include "util.h" // timer_calc_usec
18 #include "x86.h" // readl
19
20 /* low level driver implementation */
21 struct tpm_driver {
22 u32 *timeouts;
23 u32 *durations;
24 void (*set_timeouts)(u32 timeouts[4], u32 durations[3]);
25 u32 (*probe)(void);
26 TPMVersion (*get_tpm_version)(void);
27 u32 (*init)(void);
28 u32 (*activate)(u8 locty);
29 u32 (*ready)(void);
30 u32 (*senddata)(const u8 *const data, u32 len);
31 u32 (*readresp)(u8 *buffer, u32 *len);
32 u32 (*waitdatavalid)(void);
33 u32 (*waitrespready)(enum tpmDurationType to_t);
34 };
35
36 extern struct tpm_driver tpm_drivers[];
37
38 #define TIS_DRIVER_IDX 0
39 #define CRB_DRIVER_IDX 1
40 #define TPM_NUM_DRIVERS 2
41
42 #define TPM_INVALID_DRIVER 0xf
43
44 static const u32 tis_default_timeouts[4] = {
45 TIS_DEFAULT_TIMEOUT_A,
46 TIS_DEFAULT_TIMEOUT_B,
47 TIS_DEFAULT_TIMEOUT_C,
48 TIS_DEFAULT_TIMEOUT_D,
49 };
50
51 static const u32 tpm_default_durations[3] = {
52 TPM_DEFAULT_DURATION_SHORT,
53 TPM_DEFAULT_DURATION_MEDIUM,
54 TPM_DEFAULT_DURATION_LONG,
55 };
56
57 /* determined values */
58 static u32 tpm_default_dur[3];
59 static u32 tpm_default_to[4];
60
61 static u32 crb_cmd_size;
62 static void *crb_cmd;
63 static u32 crb_resp_size;
64 static void *crb_resp;
65
wait_reg8(u8 * reg,u32 time,u8 mask,u8 expect)66 static u32 wait_reg8(u8* reg, u32 time, u8 mask, u8 expect)
67 {
68 if (!CONFIG_TCGBIOS)
69 return 0;
70
71 u32 rc = 1;
72 u32 end = timer_calc_usec(time);
73
74 for (;;) {
75 u8 value = readl(reg);
76 if ((value & mask) == expect) {
77 rc = 0;
78 break;
79 }
80 if (timer_check(end)) {
81 warn_timeout();
82 break;
83 }
84 yield();
85 }
86 return rc;
87 }
88
tis_wait_access(u8 locty,u32 time,u8 mask,u8 expect)89 static u32 tis_wait_access(u8 locty, u32 time, u8 mask, u8 expect)
90 {
91 return wait_reg8(TIS_REG(locty, TIS_REG_ACCESS), time, mask, expect);
92 }
93
tis_wait_sts(u8 locty,u32 time,u8 mask,u8 expect)94 static u32 tis_wait_sts(u8 locty, u32 time, u8 mask, u8 expect)
95 {
96 return wait_reg8(TIS_REG(locty, TIS_REG_STS), time, mask, expect);
97 }
98
crb_wait_reg(u8 locty,u16 reg,u32 time,u8 mask,u8 expect)99 static u32 crb_wait_reg(u8 locty, u16 reg, u32 time, u8 mask, u8 expect)
100 {
101 return wait_reg8(CRB_REG(locty, reg), time, mask, expect);
102 }
103
104 /* if device is not there, return '0', '1' otherwise */
tis_probe(void)105 static u32 tis_probe(void)
106 {
107 if (!CONFIG_TCGBIOS)
108 return 0;
109
110 /* Wait for the interface to report it's ready */
111 u32 rc = tis_wait_access(0, TIS_DEFAULT_TIMEOUT_A,
112 TIS_ACCESS_TPM_REG_VALID_STS,
113 TIS_ACCESS_TPM_REG_VALID_STS);
114 if (rc)
115 return 0;
116
117 u32 didvid = readl(TIS_REG(0, TIS_REG_DID_VID));
118
119 if ((didvid != 0) && (didvid != 0xffffffff))
120 rc = 1;
121
122 /* TPM 2 has an interface register */
123 u32 ifaceid = readl(TIS_REG(0, TIS_REG_IFACE_ID));
124
125 if ((ifaceid & 0xf) != 0xf) {
126 if ((ifaceid & 0xf) == 1) {
127 /* CRB is active; no TIS */
128 return 0;
129 }
130 if ((ifaceid & (1 << 13)) == 0) {
131 /* TIS cannot be selected */
132 return 0;
133 }
134 /* write of 0 to bits 17-18 selects TIS */
135 writel(TIS_REG(0, TIS_REG_IFACE_ID), 0);
136 /* since we only support TIS, we lock it */
137 writel(TIS_REG(0, TIS_REG_IFACE_ID), (1 << 19));
138 }
139
140 return rc;
141 }
142
tis_get_tpm_version(void)143 static TPMVersion tis_get_tpm_version(void)
144 {
145 u32 reg = readl(TIS_REG(0, TIS_REG_IFACE_ID));
146
147 /*
148 * FIFO interface as defined in TIS1.3 is active
149 * Interface capabilities are defined in TIS_REG_INTF_CAPABILITY
150 */
151 if ((reg & 0xf) == 0xf) {
152 reg = readl(TIS_REG(0, TIS_REG_INTF_CAPABILITY));
153 /* Interface 1.3 for TPM 2.0 */
154 if (((reg >> 28) & 0x7) == 3)
155 return TPM_VERSION_2;
156 }
157 /* FIFO interface as defined in PTP for TPM 2.0 is active */
158 else if ((reg & 0xf) == 0) {
159 return TPM_VERSION_2;
160 }
161
162 return TPM_VERSION_1_2;
163 }
164
init_timeout(int driver)165 static void init_timeout(int driver)
166 {
167 if (tpm_drivers[driver].durations == NULL) {
168 u32 *durations = tpm_default_dur;
169 memcpy(durations, tpm_default_durations,
170 sizeof(tpm_default_durations));
171 tpm_drivers[driver].durations = durations;
172 }
173
174 if (tpm_drivers[driver].timeouts == NULL) {
175 u32 *timeouts = tpm_default_to;
176 memcpy(timeouts, tis_default_timeouts,
177 sizeof(tis_default_timeouts));
178 tpm_drivers[driver].timeouts = timeouts;
179 }
180 }
181
tis_init(void)182 static u32 tis_init(void)
183 {
184 if (!CONFIG_TCGBIOS)
185 return 1;
186
187 writeb(TIS_REG(0, TIS_REG_INT_ENABLE), 0);
188
189 init_timeout(TIS_DRIVER_IDX);
190
191 return 1;
192 }
193
194
set_timeouts(u32 timeouts[4],u32 durations[3])195 static void set_timeouts(u32 timeouts[4], u32 durations[3])
196 {
197 if (!CONFIG_TCGBIOS)
198 return;
199
200 u32 *tos = tpm_drivers[TIS_DRIVER_IDX].timeouts;
201 u32 *dus = tpm_drivers[TIS_DRIVER_IDX].durations;
202
203 if (tos && tos != tis_default_timeouts && timeouts)
204 memcpy(tos, timeouts, 4 * sizeof(u32));
205 if (dus && dus != tpm_default_durations && durations)
206 memcpy(dus, durations, 3 * sizeof(u32));
207 }
208
tis_activate(u8 locty)209 static u32 tis_activate(u8 locty)
210 {
211 if (!CONFIG_TCGBIOS)
212 return 0;
213
214 u32 rc = 0;
215 u8 acc;
216 int l;
217 u32 timeout_a = tpm_drivers[TIS_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_A];
218
219 if (!(readb(TIS_REG(locty, TIS_REG_ACCESS)) &
220 TIS_ACCESS_ACTIVE_LOCALITY)) {
221 /* release locality in use top-downwards */
222 for (l = 4; l >= 0; l--)
223 writeb(TIS_REG(l, TIS_REG_ACCESS),
224 TIS_ACCESS_ACTIVE_LOCALITY);
225 }
226
227 /* request access to locality */
228 writeb(TIS_REG(locty, TIS_REG_ACCESS), TIS_ACCESS_REQUEST_USE);
229
230 acc = readb(TIS_REG(locty, TIS_REG_ACCESS));
231 if ((acc & TIS_ACCESS_ACTIVE_LOCALITY)) {
232 writeb(TIS_REG(locty, TIS_REG_STS), TIS_STS_COMMAND_READY);
233 rc = tis_wait_sts(locty, timeout_a,
234 TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY);
235 }
236
237 return rc;
238 }
239
tis_find_active_locality(void)240 static u32 tis_find_active_locality(void)
241 {
242 if (!CONFIG_TCGBIOS)
243 return 0;
244
245 u8 locty;
246
247 for (locty = 0; locty <= 4; locty++) {
248 if ((readb(TIS_REG(locty, TIS_REG_ACCESS)) &
249 TIS_ACCESS_ACTIVE_LOCALITY))
250 return locty;
251 }
252
253 tis_activate(0);
254
255 return 0;
256 }
257
tis_ready(void)258 static u32 tis_ready(void)
259 {
260 if (!CONFIG_TCGBIOS)
261 return 0;
262
263 u32 rc = 0;
264 u8 locty = tis_find_active_locality();
265 u32 timeout_b = tpm_drivers[TIS_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_B];
266
267 writeb(TIS_REG(locty, TIS_REG_STS), TIS_STS_COMMAND_READY);
268 rc = tis_wait_sts(locty, timeout_b,
269 TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY);
270
271 return rc;
272 }
273
tis_senddata(const u8 * const data,u32 len)274 static u32 tis_senddata(const u8 *const data, u32 len)
275 {
276 if (!CONFIG_TCGBIOS)
277 return 0;
278
279 u32 rc = 0;
280 u32 offset = 0;
281 u32 end_loop = 0;
282 u16 burst = 0;
283 u8 locty = tis_find_active_locality();
284 u32 timeout_d = tpm_drivers[TIS_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_D];
285 u32 end = timer_calc_usec(timeout_d);
286
287 do {
288 while (burst == 0) {
289 burst = readl(TIS_REG(locty, TIS_REG_STS)) >> 8;
290 if (burst == 0) {
291 if (timer_check(end)) {
292 warn_timeout();
293 break;
294 }
295 yield();
296 }
297 }
298
299 if (burst == 0) {
300 rc = TCG_RESPONSE_TIMEOUT;
301 break;
302 }
303
304 while (1) {
305 writeb(TIS_REG(locty, TIS_REG_DATA_FIFO), data[offset++]);
306 burst--;
307
308 if (burst == 0 || offset == len)
309 break;
310 }
311
312 if (offset == len)
313 end_loop = 1;
314 } while (end_loop == 0);
315
316 return rc;
317 }
318
tis_readresp(u8 * buffer,u32 * len)319 static u32 tis_readresp(u8 *buffer, u32 *len)
320 {
321 if (!CONFIG_TCGBIOS)
322 return 0;
323
324 u32 rc = 0;
325 u32 offset = 0;
326 u32 sts;
327 u8 locty = tis_find_active_locality();
328
329 while (offset < *len) {
330 buffer[offset] = readb(TIS_REG(locty, TIS_REG_DATA_FIFO));
331 offset++;
332 sts = readb(TIS_REG(locty, TIS_REG_STS));
333 /* data left ? */
334 if ((sts & TIS_STS_DATA_AVAILABLE) == 0)
335 break;
336 }
337
338 *len = offset;
339
340 return rc;
341 }
342
343
tis_waitdatavalid(void)344 static u32 tis_waitdatavalid(void)
345 {
346 if (!CONFIG_TCGBIOS)
347 return 0;
348
349 u32 rc = 0;
350 u8 locty = tis_find_active_locality();
351 u32 timeout_c = tpm_drivers[TIS_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_C];
352
353 if (tis_wait_sts(locty, timeout_c, TIS_STS_VALID, TIS_STS_VALID) != 0)
354 rc = 1;
355
356 return rc;
357 }
358
tis_waitrespready(enum tpmDurationType to_t)359 static u32 tis_waitrespready(enum tpmDurationType to_t)
360 {
361 if (!CONFIG_TCGBIOS)
362 return 0;
363
364 u32 rc = 0;
365 u8 locty = tis_find_active_locality();
366 u32 timeout = tpm_drivers[TIS_DRIVER_IDX].durations[to_t];
367
368 writeb(TIS_REG(locty ,TIS_REG_STS), TIS_STS_TPM_GO);
369
370 if (tis_wait_sts(locty, timeout,
371 TIS_STS_DATA_AVAILABLE, TIS_STS_DATA_AVAILABLE) != 0)
372 rc = 1;
373
374 return rc;
375 }
376
377 #define CRB_STATE_VALID_STS 0b10000000
378 #define CRB_STATE_LOC_ASSIGNED 0x00000010
379 #define CRB_STATE_READY_MASK (CRB_STATE_VALID_STS | CRB_STATE_LOC_ASSIGNED)
380
381 /* if device is not there, return '0', '1' otherwise */
crb_probe(void)382 static u32 crb_probe(void)
383 {
384 if (!CONFIG_TCGBIOS)
385 return 0;
386
387 /* Wait for the interface to report it's ready */
388 u32 rc = crb_wait_reg(0, CRB_REG_LOC_STATE, TIS2_DEFAULT_TIMEOUT_D,
389 CRB_STATE_READY_MASK, CRB_STATE_VALID_STS);
390 if (rc)
391 return 0;
392
393 u32 ifaceid = readl(CRB_REG(0, CRB_REG_INTF_ID));
394
395 if ((ifaceid & 0xf) != 0xf) {
396 if ((ifaceid & 0xf) == 1) {
397 /* CRB is active */
398 } else if ((ifaceid & (1 << 14)) == 0) {
399 /* CRB cannot be selected */
400 return 0;
401 }
402 /* write of 1 to bits 17-18 selects CRB */
403 writel(CRB_REG(0, CRB_REG_INTF_ID), (1 << 17));
404 /* lock it */
405 writel(CRB_REG(0, CRB_REG_INTF_ID), (1 << 19));
406 }
407
408 /* no support for 64 bit addressing yet */
409 if (readl(CRB_REG(0, CRB_REG_CTRL_CMD_HADDR)))
410 return 0;
411
412 u64 addr = readq(CRB_REG(0, CRB_REG_CTRL_RSP_ADDR));
413 if (addr > 0xffffffff)
414 return 0;
415
416 return 1;
417 }
418
crb_get_tpm_version(void)419 static TPMVersion crb_get_tpm_version(void)
420 {
421 /* CRB is supposed to be TPM 2.0 only */
422 return TPM_VERSION_2;
423 }
424
crb_init(void)425 static u32 crb_init(void)
426 {
427 if (!CONFIG_TCGBIOS)
428 return 1;
429
430 crb_cmd = (void*)readl(CRB_REG(0, CRB_REG_CTRL_CMD_LADDR));
431 crb_cmd_size = readl(CRB_REG(0, CRB_REG_CTRL_CMD_SIZE));
432 crb_resp = (void*)readl(CRB_REG(0, CRB_REG_CTRL_RSP_ADDR));
433 crb_resp_size = readl(CRB_REG(0, CRB_REG_CTRL_RSP_SIZE));
434
435 init_timeout(CRB_DRIVER_IDX);
436
437 return 0;
438 }
439
crb_activate(u8 locty)440 static u32 crb_activate(u8 locty)
441 {
442 if (!CONFIG_TCGBIOS)
443 return 0;
444
445 writeb(CRB_REG(locty, CRB_REG_LOC_CTRL), 1);
446
447 return 0;
448 }
449
crb_find_active_locality(void)450 static u32 crb_find_active_locality(void)
451 {
452 if (!CONFIG_TCGBIOS)
453 return 0;
454
455 return 0;
456 }
457
458 #define CRB_CTRL_REQ_CMD_READY 0b1
459 #define CRB_START_INVOKE 0b1
460 #define CRB_CTRL_STS_ERROR 0b1
461
crb_ready(void)462 static u32 crb_ready(void)
463 {
464 if (!CONFIG_TCGBIOS)
465 return 0;
466
467 u32 rc = 0;
468 u8 locty = crb_find_active_locality();
469 u32 timeout_c = tpm_drivers[CRB_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_C];
470
471 writel(CRB_REG(locty, CRB_REG_CTRL_REQ), CRB_CTRL_REQ_CMD_READY);
472 rc = crb_wait_reg(locty, CRB_REG_CTRL_REQ, timeout_c,
473 CRB_CTRL_REQ_CMD_READY, 0);
474
475 return rc;
476 }
477
crb_senddata(const u8 * const data,u32 len)478 static u32 crb_senddata(const u8 *const data, u32 len)
479 {
480 if (!CONFIG_TCGBIOS)
481 return 0;
482
483 if (len > crb_cmd_size)
484 return 1;
485
486 u8 locty = crb_find_active_locality();
487 memcpy(crb_cmd, data, len);
488 writel(CRB_REG(locty, CRB_REG_CTRL_START), CRB_START_INVOKE);
489
490 return 0;
491 }
492
crb_readresp(u8 * buffer,u32 * len)493 static u32 crb_readresp(u8 *buffer, u32 *len)
494 {
495 if (!CONFIG_TCGBIOS)
496 return 0;
497
498 u8 locty = crb_find_active_locality();
499 if (readl(CRB_REG(locty, CRB_REG_CTRL_STS)) & CRB_CTRL_STS_ERROR)
500 return 1;
501
502 if (*len < 6)
503 return 1;
504
505 memcpy(buffer, crb_resp, 6);
506 u32 expected = be32_to_cpu(*(u32 *) &buffer[2]);
507 if (expected < 6)
508 return 1;
509
510 *len = (*len < expected) ? *len : expected;
511
512 memcpy(buffer + 6, crb_resp + 6, *len - 6);
513
514 return 0;
515 }
516
517
crb_waitdatavalid(void)518 static u32 crb_waitdatavalid(void)
519 {
520 return 0;
521 }
522
crb_waitrespready(enum tpmDurationType to_t)523 static u32 crb_waitrespready(enum tpmDurationType to_t)
524 {
525 if (!CONFIG_TCGBIOS)
526 return 0;
527
528 u32 rc = 0;
529 u8 locty = crb_find_active_locality();
530 u32 timeout = tpm_drivers[CRB_DRIVER_IDX].durations[to_t];
531
532 rc = crb_wait_reg(locty, CRB_REG_CTRL_START, timeout,
533 CRB_START_INVOKE, 0);
534
535 return rc;
536 }
537
538 struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = {
539 [TIS_DRIVER_IDX] =
540 {
541 .timeouts = NULL,
542 .durations = NULL,
543 .set_timeouts = set_timeouts,
544 .probe = tis_probe,
545 .get_tpm_version = tis_get_tpm_version,
546 .init = tis_init,
547 .activate = tis_activate,
548 .ready = tis_ready,
549 .senddata = tis_senddata,
550 .readresp = tis_readresp,
551 .waitdatavalid = tis_waitdatavalid,
552 .waitrespready = tis_waitrespready,
553 },
554 [CRB_DRIVER_IDX] =
555 {
556 .timeouts = NULL,
557 .durations = NULL,
558 .set_timeouts = set_timeouts,
559 .probe = crb_probe,
560 .get_tpm_version = crb_get_tpm_version,
561 .init = crb_init,
562 .activate = crb_activate,
563 .ready = crb_ready,
564 .senddata = crb_senddata,
565 .readresp = crb_readresp,
566 .waitdatavalid = crb_waitdatavalid,
567 .waitrespready = crb_waitrespready,
568 },
569 };
570
571 static u8 TPMHW_driver_to_use = TPM_INVALID_DRIVER;
572
573 TPMVersion
tpmhw_probe(void)574 tpmhw_probe(void)
575 {
576 unsigned int i;
577 for (i = 0; i < TPM_NUM_DRIVERS; i++) {
578 struct tpm_driver *td = &tpm_drivers[i];
579 if (td->probe() != 0) {
580 td->init();
581 TPMHW_driver_to_use = i;
582 return td->get_tpm_version();
583 }
584 }
585 return TPM_VERSION_NONE;
586 }
587
588 int
tpmhw_is_present(void)589 tpmhw_is_present(void)
590 {
591 return TPMHW_driver_to_use != TPM_INVALID_DRIVER;
592 }
593
594 int
tpmhw_transmit(u8 locty,struct tpm_req_header * req,void * respbuffer,u32 * respbufferlen,enum tpmDurationType to_t)595 tpmhw_transmit(u8 locty, struct tpm_req_header *req,
596 void *respbuffer, u32 *respbufferlen,
597 enum tpmDurationType to_t)
598 {
599 if (TPMHW_driver_to_use == TPM_INVALID_DRIVER)
600 return -1;
601
602 struct tpm_driver *td = &tpm_drivers[TPMHW_driver_to_use];
603
604 u32 irc = td->activate(locty);
605 if (irc != 0) {
606 /* tpm could not be activated */
607 return -1;
608 }
609
610 irc = td->senddata((void*)req, be32_to_cpu(req->totlen));
611 if (irc != 0)
612 return -1;
613
614 irc = td->waitdatavalid();
615 if (irc != 0)
616 return -1;
617
618 irc = td->waitrespready(to_t);
619 if (irc != 0)
620 return -1;
621
622 irc = td->readresp(respbuffer, respbufferlen);
623 if (irc != 0 ||
624 *respbufferlen < sizeof(struct tpm_rsp_header))
625 return -1;
626
627 td->ready();
628
629 return 0;
630 }
631
632 void
tpmhw_set_timeouts(u32 timeouts[4],u32 durations[3])633 tpmhw_set_timeouts(u32 timeouts[4], u32 durations[3])
634 {
635 struct tpm_driver *td = &tpm_drivers[TPMHW_driver_to_use];
636 td->set_timeouts(timeouts, durations);
637 }
638