jcs's openbsd hax
openbsd
1/* $OpenBSD: tpm.c,v 1.20 2024/05/29 12:21:33 kettenis Exp $ */
2
3/*
4 * Minimal interface to Trusted Platform Module chips implementing the
5 * TPM Interface Spec 1.2, just enough to tell the TPM to save state before
6 * a system suspend.
7 *
8 * Copyright (c) 2008, 2009 Michael Shalayeff
9 * Copyright (c) 2009, 2010 Hans-Joerg Hoexer
10 * Copyright (c) 2016 joshua stein <jcs@openbsd.org>
11 * All rights reserved.
12 *
13 * Permission to use, copy, modify, and distribute this software for any
14 * purpose with or without fee is hereby granted, provided that the above
15 * copyright notice and this permission notice appear in all copies.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
20 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
22 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
23 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 */
25
26#include <sys/param.h>
27#include <sys/systm.h>
28#include <sys/device.h>
29#include <sys/malloc.h>
30
31#include <machine/bus.h>
32#include <machine/apmvar.h>
33
34#include <dev/acpi/acpireg.h>
35#include <dev/acpi/acpivar.h>
36#include <dev/acpi/acpidev.h>
37#include <dev/acpi/amltypes.h>
38#include <dev/acpi/dsdt.h>
39
40/* #define TPM_DEBUG */
41
42#ifdef TPM_DEBUG
43#define DPRINTF(x) printf x
44#else
45#define DPRINTF(x)
46#endif
47
48#define TPM_BUFSIZ 1024
49#define TPM_HDRSIZE 10
50#define TPM_PARAM_SIZE 0x0001
51
52#define TPM_ACCESS 0x0000 /* access register */
53#define TPM_ACCESS_ESTABLISHMENT 0x01 /* establishment */
54#define TPM_ACCESS_REQUEST_USE 0x02 /* request using locality */
55#define TPM_ACCESS_REQUEST_PENDING 0x04 /* pending request */
56#define TPM_ACCESS_SEIZE 0x08 /* request locality seize */
57#define TPM_ACCESS_SEIZED 0x10 /* locality has been seized */
58#define TPM_ACCESS_ACTIVE_LOCALITY 0x20 /* locality is active */
59#define TPM_ACCESS_VALID 0x80 /* bits are valid */
60#define TPM_ACCESS_BITS \
61 "\020\01EST\02REQ\03PEND\04SEIZE\05SEIZED\06ACT\010VALID"
62
63#define TPM_INTERRUPT_ENABLE 0x0008
64#define TPM_GLOBAL_INT_ENABLE 0x80000000 /* enable ints */
65#define TPM_CMD_READY_INT 0x00000080 /* cmd ready enable */
66#define TPM_INT_EDGE_FALLING 0x00000018
67#define TPM_INT_EDGE_RISING 0x00000010
68#define TPM_INT_LEVEL_LOW 0x00000008
69#define TPM_INT_LEVEL_HIGH 0x00000000
70#define TPM_LOCALITY_CHANGE_INT 0x00000004 /* locality change enable */
71#define TPM_STS_VALID_INT 0x00000002 /* int on TPM_STS_VALID is set */
72#define TPM_DATA_AVAIL_INT 0x00000001 /* int on TPM_STS_DATA_AVAIL is set */
73#define TPM_INTERRUPT_ENABLE_BITS \
74 "\020\040ENA\010RDY\03LOCH\02STSV\01DRDY"
75
76#define TPM_INT_VECTOR 0x000c /* 8 bit reg for 4 bit irq vector */
77#define TPM_INT_STATUS 0x0010 /* bits are & 0x87 from TPM_INTERRUPT_ENABLE */
78
79#define TPM_INTF_CAPABILITIES 0x0014 /* capability register */
80#define TPM_INTF_BURST_COUNT_STATIC 0x0100 /* TPM_STS_BMASK static */
81#define TPM_INTF_CMD_READY_INT 0x0080 /* int on ready supported */
82#define TPM_INTF_INT_EDGE_FALLING 0x0040 /* falling edge ints supported */
83#define TPM_INTF_INT_EDGE_RISING 0x0020 /* rising edge ints supported */
84#define TPM_INTF_INT_LEVEL_LOW 0x0010 /* level-low ints supported */
85#define TPM_INTF_INT_LEVEL_HIGH 0x0008 /* level-high ints supported */
86#define TPM_INTF_LOCALITY_CHANGE_INT 0x0004 /* locality-change int (mb 1) */
87#define TPM_INTF_STS_VALID_INT 0x0002 /* TPM_STS_VALID int supported */
88#define TPM_INTF_DATA_AVAIL_INT 0x0001 /* TPM_STS_DATA_AVAIL int supported (mb 1) */
89#define TPM_CAPSREQ \
90 (TPM_INTF_DATA_AVAIL_INT|TPM_INTF_LOCALITY_CHANGE_INT|TPM_INTF_INT_LEVEL_LOW)
91#define TPM_CAPBITS \
92 "\020\01IDRDY\02ISTSV\03ILOCH\04IHIGH\05ILOW\06IEDGE\07IFALL\010IRDY\011BCST"
93
94#define TPM_STS 0x0018 /* status register */
95#define TPM_STS_MASK 0x000000ff /* status bits */
96#define TPM_STS_BMASK 0x00ffff00 /* ro io burst size */
97#define TPM_STS_VALID 0x00000080 /* ro other bits are valid */
98#define TPM_STS_CMD_READY 0x00000040 /* rw chip/signal ready */
99#define TPM_STS_GO 0x00000020 /* wo start the command */
100#define TPM_STS_DATA_AVAIL 0x00000010 /* ro data available */
101#define TPM_STS_DATA_EXPECT 0x00000008 /* ro more data to be written */
102#define TPM_STS_RESP_RETRY 0x00000002 /* wo resend the response */
103#define TPM_STS_BITS "\020\010VALID\07RDY\06GO\05DRDY\04EXPECT\02RETRY"
104
105#define TPM_DATA 0x0024
106#define TPM_ID 0x0f00
107#define TPM_REV 0x0f04
108#define TPM_SIZE 0x5000 /* five pages of the above */
109
110#define TPM_ACCESS_TMO 2000 /* 2sec */
111#define TPM_READY_TMO 2000 /* 2sec */
112#define TPM_READ_TMO 120000 /* 2 minutes */
113#define TPM_BURST_TMO 2000 /* 2sec */
114
115#define TPM2_START_METHOD_TIS 6
116#define TPM2_START_METHOD_CRB 7
117
118#define TPM_CRB_LOC_STATE 0x0
119#define TPM_CRB_LOC_CTRL 0x8
120#define TPM_LOC_STS 0xC
121#define TPM_CRB_INTF_ID 0x30
122#define TPM_CRB_CTRL_EXT 0x38
123#define TPM_CRB_CTRL_REQ 0x40
124#define TPM_CRB_CTRL_STS 0x44
125#define TPM_CRB_CTRL_CANCEL 0x48
126#define TPM_CRB_CTRL_START 0x4C
127#define TPM_CRB_CTRL_CMD_SIZE 0x58
128#define TPM_CRB_CTRL_CMD_LADDR 0x5C
129#define TPM_CRB_CTRL_CMD_HADDR 0x60
130#define TPM_CRB_CTRL_RSP_SIZE 0x64
131#define TPM_CRB_CTRL_RSP_LADDR 0x68
132#define TPM_CRB_CTRL_RSP_HADDR 0x6c
133#define TPM_CRB_DATA_BUFFER 0x80
134
135#define TPM_CRB_LOC_STATE_ESTB (1 << 0)
136#define TPM_CRB_LOC_STATE_ASSIGNED (1 << 1)
137#define TPM_CRB_LOC_ACTIVE_MASK 0x009c
138#define TPM_CRB_LOC_VALID (1 << 7)
139
140#define TPM_CRB_LOC_REQUEST (1 << 0)
141#define TPM_CRB_LOC_RELEASE (1 << 1)
142
143#define TPM_CRB_CTRL_REQ_GO_READY (1 << 0)
144#define TPM_CRB_CTRL_REQ_GO_IDLE (1 << 1)
145
146#define TPM_CRB_CTRL_STS_ERR_BIT (1 << 0)
147#define TPM_CRB_CTRL_STS_IDLE_BIT (1 << 1)
148
149#define TPM_CRB_CTRL_CANCEL_CMD 0x1
150#define TPM_CRB_CTRL_CANCEL_CLEAR 0x0
151
152#define TPM_CRB_CTRL_START_CMD (1 << 0)
153#define TPM_CRB_INT_ENABLED_BIT (1U << 31)
154
155#define TPM2_RC_SUCCESS 0x0000
156#define TPM2_RC_INITIALIZE 0x0100
157#define TPM2_RC_FAILURE 0x0101
158#define TPM2_RC_DISABLED 0x0120
159#define TPM2_RC_RETRY 0x0922
160
161struct tpm_softc {
162 struct device sc_dev;
163
164 bus_space_tag_t sc_bt;
165 bus_space_handle_t sc_bh;
166 bus_size_t sc_bbase;
167
168 struct acpi_softc *sc_acpi;
169 struct aml_node *sc_devnode;
170
171 uint32_t sc_devid;
172 uint32_t sc_rev;
173
174 int sc_tpm20;
175 int sc_tpm_mode;
176#define TPM_TIS 0
177#define TPM_CRB 1
178 bus_size_t sc_cmd_off;
179 bus_size_t sc_rsp_off;
180 size_t sc_cmd_sz;
181 size_t sc_rsp_sz;
182
183 int sc_enabled;
184};
185
186const struct {
187 uint32_t devid;
188 char name[32];
189} tpm_devs[] = {
190 { 0x000615d1, "Infineon SLD9630 1.1" },
191 { 0x000b15d1, "Infineon SLB9635 1.2" },
192 { 0x100214e4, "Broadcom BCM0102" },
193 { 0x00fe1050, "WEC WPCT200" },
194 { 0x687119fa, "SNS SSX35" },
195 { 0x2e4d5453, "STM ST19WP18" },
196 { 0x32021114, "Atmel 97SC3203" },
197 { 0x10408086, "Intel INTC0102" },
198 { 0, "" },
199};
200
201int tpm_match(struct device *, void *, void *);
202void tpm_attach(struct device *, struct device *, void *);
203int tpm_activate(struct device *, int);
204
205int tpm_probe(bus_space_tag_t, bus_space_handle_t);
206int tpm_init_tis(struct tpm_softc *);
207int tpm_init_crb(struct tpm_softc *);
208int tpm_read_tis(struct tpm_softc *, void *, int, size_t *, int);
209int tpm_read_crb(struct tpm_softc *, void *, int);
210int tpm_write_tis(struct tpm_softc *, void *, int);
211int tpm_write_crb(struct tpm_softc *, void *, int);
212int tpm_suspend(struct tpm_softc *);
213int tpm_resume(struct tpm_softc *);
214
215int tpm_waitfor(struct tpm_softc *, bus_space_handle_t, uint32_t, uint32_t, int);
216int tpm_waitfor_status(struct tpm_softc *, uint8_t, int);
217int tpm_request_locality_tis(struct tpm_softc *, int);
218int tpm_request_locality_crb(struct tpm_softc *, int);
219void tpm_release_locality_tis(struct tpm_softc *);
220void tpm_release_locality_crb(struct tpm_softc *);
221uint8_t tpm_status(struct tpm_softc *);
222
223uint32_t tpm2_start_method(struct acpi_softc *);
224
225const struct cfattach tpm_ca = {
226 sizeof(struct tpm_softc),
227 tpm_match,
228 tpm_attach,
229 NULL,
230 tpm_activate
231};
232
233struct cfdriver tpm_cd = {
234 NULL, "tpm", DV_DULL, CD_SKIPHIBERNATE /* XXX */
235};
236
237const char *tpm_hids[] = {
238 "PNP0C31",
239 "ATM1200",
240 "IFX0102",
241 "BCM0101",
242 "BCM0102",
243 "NSC1200",
244 "ICO0102",
245 "MSFT0101",
246 NULL
247};
248
249int
250tpm_match(struct device *parent, void *match, void *aux)
251{
252 struct acpi_attach_args *aa = aux;
253 struct cfdata *cf = match;
254
255 if (aa->aaa_naddr < 1)
256 return 0;
257 return (acpi_matchhids(aa, tpm_hids, cf->cf_driver->cd_name));
258}
259
260void
261tpm_attach(struct device *parent, struct device *self, void *aux)
262{
263 struct tpm_softc *sc = (struct tpm_softc *)self;
264 struct acpi_attach_args *aaa = aux;
265 int64_t sta;
266 uint32_t start_method;
267
268 sc->sc_acpi = (struct acpi_softc *)parent;
269 sc->sc_devnode = aaa->aaa_node;
270 sc->sc_enabled = 0;
271 sc->sc_tpm_mode = TPM_TIS;
272
273 printf(" %s", sc->sc_devnode->name);
274
275 if (strcmp(aaa->aaa_dev, "MSFT0101") == 0 ||
276 strcmp(aaa->aaa_cdev, "MSFT0101") == 0) {
277 sc->sc_tpm20 = 1;
278 /* Identify if using 1.2 TIS or 2.0's CRB methods */
279 start_method = tpm2_start_method(sc->sc_acpi);
280 switch (start_method) {
281 case TPM2_START_METHOD_TIS:
282 /* Already default */
283 break;
284 case TPM2_START_METHOD_CRB:
285 sc->sc_tpm_mode = TPM_CRB;
286 break;
287 default:
288 printf(": unsupported TPM2 start method %d\n", start_method);
289 return;
290 }
291 }
292
293 printf(" %s (%s)", sc->sc_tpm20 ? "2.0" : "1.2",
294 sc->sc_tpm_mode == TPM_TIS ? "TIS" : "CRB");
295
296 sta = acpi_getsta(sc->sc_acpi, sc->sc_devnode);
297 if ((sta & (STA_PRESENT | STA_ENABLED | STA_DEV_OK)) !=
298 (STA_PRESENT | STA_ENABLED | STA_DEV_OK)) {
299 printf(": not enabled\n");
300 return;
301 }
302
303 printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]);
304 sc->sc_bbase = aaa->aaa_addr[0];
305
306 sc->sc_bt = aaa->aaa_bst[0];
307 if (bus_space_map(sc->sc_bt, aaa->aaa_addr[0], aaa->aaa_size[0],
308 0, &sc->sc_bh)) {
309 printf(": can't map registers\n");
310 return;
311 }
312
313 if (sc->sc_tpm_mode == TPM_TIS) {
314 if (!tpm_probe(sc->sc_bt, sc->sc_bh)) {
315 printf(": probe failed\n");
316 return;
317 }
318
319 if (tpm_init_tis(sc) != 0) {
320 printf(": init failed\n");
321 return;
322 }
323 } else {
324 if (tpm_init_crb(sc) != 0) {
325 printf(": init failed\n");
326 return;
327 }
328 }
329
330 printf("\n");
331 sc->sc_enabled = 1;
332}
333
334int
335tpm_activate(struct device *self, int act)
336{
337 struct tpm_softc *sc = (struct tpm_softc *)self;
338
339 switch (act) {
340 case DVACT_SUSPEND:
341 if (!sc->sc_enabled) {
342 DPRINTF(("%s: suspend, but not enabled\n",
343 sc->sc_dev.dv_xname));
344 return 0;
345 }
346 tpm_suspend(sc);
347 break;
348
349 case DVACT_WAKEUP:
350 if (!sc->sc_enabled) {
351 DPRINTF(("%s: wakeup, but not enabled\n",
352 sc->sc_dev.dv_xname));
353 return 0;
354 }
355 tpm_resume(sc);
356 break;
357 }
358
359 return 0;
360}
361
362int
363tpm_suspend(struct tpm_softc *sc)
364{
365 uint8_t command1[] = {
366 0, 0xc1, /* TPM_TAG_RQU_COMMAND */
367 0, 0, 0, 10, /* Length in bytes */
368 0, 0, 0, 0x98 /* TPM_ORD_SaveStates */
369 };
370 uint8_t command2[] = {
371 0x80, 0x01, /* TPM_ST_COMMAND_TAG */
372 0, 0, 0, 12, /* Length in bytes */
373 0, 0, 0x01, 0x45, /* TPM_CC_Shutdown */
374 0x00, 0x01
375 };
376 uint8_t *command;
377 size_t commandlen;
378
379 if (sc->sc_acpi->sc_state == ACPI_STATE_S0)
380 return 0;
381
382 DPRINTF(("%s: saving state preparing for suspend\n",
383 sc->sc_dev.dv_xname));
384
385 if (sc->sc_tpm20) {
386 command = command2;
387 commandlen = sizeof(command2);
388 } else {
389 command = command1;
390 commandlen = sizeof(command1);
391 }
392
393 /*
394 * Tell the chip to save its state so the BIOS can then restore it upon
395 * resume.
396 */
397 if (sc->sc_tpm_mode == TPM_TIS) {
398 tpm_write_tis(sc, command, commandlen);
399 memset(command, 0, commandlen);
400 tpm_read_tis(sc, command, commandlen, NULL, TPM_HDRSIZE);
401 } else {
402 tpm_write_crb(sc, command, commandlen);
403 memset(command, 0, commandlen);
404 tpm_read_crb(sc, command, commandlen);
405 }
406 return 0;
407}
408
409int
410tpm_resume(struct tpm_softc *sc)
411{
412 /*
413 * TODO: The BIOS should have restored the chip's state for us already,
414 * but we should tell the chip to do a self-test here (according to the
415 * Linux driver).
416 */
417
418 DPRINTF(("%s: resume\n", sc->sc_dev.dv_xname));
419 return 0;
420}
421
422uint32_t
423tpm2_start_method(struct acpi_softc *sc)
424{
425 struct acpi_q *entry;
426 struct acpi_tpm2 *p_tpm2 = NULL;
427
428 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
429 if (memcmp(entry->q_table, TPM2_SIG,
430 sizeof(TPM2_SIG) - 1) == 0) {
431 p_tpm2 = entry->q_table;
432 break;
433 }
434 }
435
436 if (!p_tpm2) {
437 DPRINTF((", no TPM2 table"));
438 return 0;
439 }
440
441 return p_tpm2->start_method;
442}
443
444int
445tpm_probe(bus_space_tag_t bt, bus_space_handle_t bh)
446{
447 uint32_t r;
448 int tries = 10000;
449
450 /* wait for chip to settle */
451 while (tries--) {
452 if (bus_space_read_1(bt, bh, TPM_ACCESS) & TPM_ACCESS_VALID)
453 break;
454 else if (!tries) {
455 printf(": timed out waiting for validity\n");
456 return 1;
457 }
458
459 DELAY(10);
460 }
461
462 r = bus_space_read_4(bt, bh, TPM_INTF_CAPABILITIES);
463 if (r == 0xffffffff)
464 return 0;
465
466 return 1;
467}
468
469int
470tpm_init_tis(struct tpm_softc *sc)
471{
472 uint32_t r, intmask;
473 int i;
474
475 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTF_CAPABILITIES);
476 if ((r & TPM_CAPSREQ) != TPM_CAPSREQ ||
477 !(r & (TPM_INTF_INT_EDGE_RISING | TPM_INTF_INT_LEVEL_LOW))) {
478 DPRINTF((": caps too low (caps=%b)\n", r, TPM_CAPBITS));
479 return 0;
480 }
481
482 /* ack and disable all interrupts, we'll be using polling only */
483 intmask = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE);
484 intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
485 TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
486 intmask &= ~TPM_GLOBAL_INT_ENABLE;
487 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE, intmask);
488
489 if (tpm_request_locality_tis(sc, 0)) {
490 printf(", requesting locality failed\n");
491 return 1;
492 }
493
494 sc->sc_devid = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_ID);
495 sc->sc_rev = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_REV);
496
497 for (i = 0; tpm_devs[i].devid; i++)
498 if (tpm_devs[i].devid == sc->sc_devid)
499 break;
500
501 if (tpm_devs[i].devid)
502 printf(", %s rev 0x%x", tpm_devs[i].name, sc->sc_rev);
503 else
504 printf(", device 0x%08x rev 0x%x", sc->sc_devid, sc->sc_rev);
505
506 return 0;
507}
508
509int
510tpm_init_crb(struct tpm_softc *sc)
511{
512 uint32_t intmask;
513 int i;
514
515 if (tpm_request_locality_crb(sc, 0)) {
516 printf(", request locality failed\n");
517 return 1;
518 }
519
520 /* ack and disable all interrupts, we'll be using polling only */
521 intmask = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE);
522 intmask &= ~TPM_CRB_INT_ENABLED_BIT;
523 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE, intmask);
524
525 /* Identify command and response registers and sizes */
526 sc->sc_cmd_off = bus_space_read_4(sc->sc_bt, sc->sc_bh,
527 TPM_CRB_CTRL_CMD_LADDR);
528 sc->sc_cmd_off |= ((uint64_t) bus_space_read_4(sc->sc_bt, sc->sc_bh,
529 TPM_CRB_CTRL_CMD_HADDR) << 32);
530 sc->sc_cmd_sz = bus_space_read_4(sc->sc_bt, sc->sc_bh,
531 TPM_CRB_CTRL_CMD_SIZE);
532
533 sc->sc_rsp_off = bus_space_read_4(sc->sc_bt, sc->sc_bh,
534 TPM_CRB_CTRL_RSP_LADDR);
535 sc->sc_rsp_off |= ((uint64_t) bus_space_read_4(sc->sc_bt, sc->sc_bh,
536 TPM_CRB_CTRL_RSP_HADDR) << 32);
537 sc->sc_rsp_sz = bus_space_read_4(sc->sc_bt, sc->sc_bh,
538 TPM_CRB_CTRL_RSP_SIZE);
539
540 DPRINTF((", cmd @ 0x%lx, %ld, rsp @ 0x%lx, %ld", sc->sc_cmd_off,
541 sc->sc_cmd_sz, sc->sc_rsp_off, sc->sc_rsp_sz));
542
543 sc->sc_cmd_off = sc->sc_cmd_off - sc->sc_bbase;
544 sc->sc_rsp_off = sc->sc_rsp_off - sc->sc_bbase;
545
546 tpm_release_locality_crb(sc);
547
548 /* If it's a unified buffer, the sizes must be the same. */
549 if (sc->sc_cmd_off == sc->sc_rsp_off) {
550 if (sc->sc_cmd_sz != sc->sc_rsp_sz) {
551 printf(", invalid buffer sizes\n");
552 return 1;
553 }
554 }
555
556 for (i = 0; tpm_devs[i].devid; i++)
557 if (tpm_devs[i].devid == sc->sc_devid)
558 break;
559
560 if (tpm_devs[i].devid)
561 printf(", %s rev 0x%x", tpm_devs[i].name, sc->sc_rev);
562 else
563 printf(", device 0x%08x rev 0x%x", sc->sc_devid, sc->sc_rev);
564
565 return 0;
566}
567
568int
569tpm_request_locality_tis(struct tpm_softc *sc, int l)
570{
571 uint32_t r;
572 int to;
573
574 if (l != 0)
575 return EINVAL;
576
577 if ((bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
578 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) ==
579 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY))
580 return 0;
581
582 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
583 TPM_ACCESS_REQUEST_USE);
584
585 to = TPM_ACCESS_TMO * 100; /* steps of 10 microseconds */
586
587 while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
588 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
589 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) {
590 DELAY(10);
591 }
592
593 if ((r & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
594 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
595 DPRINTF(("%s: %s: access %b\n", sc->sc_dev.dv_xname, __func__,
596 r, TPM_ACCESS_BITS));
597 return EBUSY;
598 }
599
600 return 0;
601}
602
603int
604tpm_request_locality_crb(struct tpm_softc *sc, int l)
605{
606 uint32_t r, mask;
607 int to;
608
609 if (l != 0)
610 return EINVAL;
611
612 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_CRB_LOC_CTRL);
613 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_CRB_LOC_CTRL,
614 r | TPM_CRB_LOC_REQUEST);
615
616 to = TPM_ACCESS_TMO * 200;
617 mask = TPM_CRB_LOC_STATE_ASSIGNED | TPM_CRB_LOC_VALID;
618
619 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_CRB_LOC_STATE);
620 while ((r & mask) != mask && to--) {
621 DELAY(10);
622 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_CRB_LOC_STATE);
623 }
624
625 if ((r & mask) != mask) {
626 printf(", CRB loc FAILED");
627 return EBUSY;
628 }
629
630 return 0;
631}
632
633void
634tpm_release_locality_tis(struct tpm_softc *sc)
635{
636 if ((bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
637 (TPM_ACCESS_REQUEST_PENDING|TPM_ACCESS_VALID)) ==
638 (TPM_ACCESS_REQUEST_PENDING|TPM_ACCESS_VALID)) {
639 DPRINTF(("%s: releasing locality\n", sc->sc_dev.dv_xname));
640 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
641 TPM_ACCESS_ACTIVE_LOCALITY);
642 }
643}
644
645void
646tpm_release_locality_crb(struct tpm_softc *sc)
647{
648 uint32_t r;
649
650 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_CRB_LOC_CTRL);
651 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_CRB_LOC_CTRL,
652 r | TPM_CRB_LOC_RELEASE);
653}
654
655int
656tpm_getburst(struct tpm_softc *sc)
657{
658 int burst, burst2, to;
659
660 to = TPM_BURST_TMO * 100; /* steps of 10 microseconds */
661
662 burst = 0;
663 while (burst == 0 && to--) {
664 /*
665 * Burst count has to be read from bits 8 to 23 without
666 * touching any other bits, eg. the actual status bits 0 to 7.
667 */
668 burst = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 1);
669 DPRINTF(("%s: %s: read1(0x%x): 0x%x\n", sc->sc_dev.dv_xname,
670 __func__, TPM_STS + 1, burst));
671 burst2 = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 2);
672 DPRINTF(("%s: %s: read1(0x%x): 0x%x\n", sc->sc_dev.dv_xname,
673 __func__, TPM_STS + 2, burst2));
674 burst |= burst2 << 8;
675 if (burst)
676 return burst;
677
678 DELAY(10);
679 }
680
681 DPRINTF(("%s: getburst timed out\n", sc->sc_dev.dv_xname));
682
683 return 0;
684}
685
686uint8_t
687tpm_status(struct tpm_softc *sc)
688{
689 return bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS) & TPM_STS_MASK;
690}
691
692int
693tpm_waitfor(struct tpm_softc *sc, bus_size_t offset, uint32_t mask,
694 uint32_t val, int msecs)
695{
696 int usecs;
697 uint32_t r;
698
699 usecs = msecs * 1000;
700
701 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, offset);
702 if ((r & mask) == val)
703 return 0;
704
705 while (usecs > 0) {
706 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, offset);
707 if ((r & mask) == val)
708 return 0;
709 DELAY(1);
710 usecs--;
711 }
712
713 DPRINTF(("%s: %s: timed out, status 0x%x != 0x%x\n",
714 sc->sc_dev.dv_xname, __func__, r, mask));
715 return ETIMEDOUT;
716}
717
718int
719tpm_waitfor_status(struct tpm_softc *sc, uint8_t mask, int msecs)
720{
721 int usecs;
722 uint8_t status;
723
724 usecs = msecs * 1000;
725
726 while (((status = tpm_status(sc)) & mask) != mask) {
727 if (usecs == 0) {
728 DPRINTF(("%s: %s: timed out, status 0x%x != 0x%x\n",
729 sc->sc_dev.dv_xname, __func__, status, mask));
730 return status;
731 }
732
733 usecs--;
734 DELAY(1);
735 }
736
737 return 0;
738}
739
740int
741tpm_read_tis(struct tpm_softc *sc, void *buf, int len, size_t *count,
742 int flags)
743{
744 uint8_t *p = buf;
745 uint8_t c;
746 size_t cnt;
747 int rv, n, bcnt;
748
749 DPRINTF(("%s: %s %d:", sc->sc_dev.dv_xname, __func__, len));
750
751 cnt = 0;
752 while (len > 0) {
753 if ((rv = tpm_waitfor_status(sc,
754 TPM_STS_DATA_AVAIL | TPM_STS_VALID, TPM_READ_TMO)))
755 return rv;
756
757 bcnt = tpm_getburst(sc);
758 n = MIN(len, bcnt);
759
760 for (; n--; len--) {
761 c = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_DATA);
762 DPRINTF((" %02x", c));
763 *p++ = c;
764 cnt++;
765 }
766
767 if ((flags & TPM_PARAM_SIZE) == 0 && cnt >= 6)
768 break;
769 }
770
771 DPRINTF(("\n"));
772
773 if (count)
774 *count = cnt;
775
776 return 0;
777}
778
779int
780tpm_read_crb(struct tpm_softc *sc, void *buf, int len)
781{
782 uint8_t *p = buf;
783 uint32_t sz = 0, mask, rc;
784 size_t count = 0;
785 int r;
786
787 DPRINTF(("%s: %s %d:", sc->sc_dev.dv_xname, __func__, len));
788
789 if (len < TPM_HDRSIZE) {
790 printf("%s: %s buf len too small\n", sc->sc_dev.dv_xname,
791 __func__);
792 return EINVAL;
793 }
794
795 while (count < TPM_HDRSIZE) {
796 *p = bus_space_read_1(sc->sc_bt, sc->sc_bh,
797 sc->sc_rsp_off + count);
798 DPRINTF((" %02x", *p));
799 count++;
800 p++;
801 }
802 DPRINTF(("\n"));
803
804 /* Response length is bytes 2-5 in the response header. */
805 p = buf;
806 sz = be32toh(*(uint32_t *) (p + 2));
807 if (sz < TPM_HDRSIZE || sz > sc->sc_rsp_sz) {
808 printf("%s: invalid response size %d\n",
809 sc->sc_dev.dv_xname, sz);
810 return EIO;
811 }
812 if (sz > len)
813 printf("%s: response size too large, truncated to %d\n",
814 sc->sc_dev.dv_xname, len);
815
816 /* Response code is bytes 6-9. */
817 rc = be32toh(*(uint32_t *) (p + 6));
818 if (rc != TPM2_RC_SUCCESS) {
819 printf("%s: command failed (0x%04x)\n", sc->sc_dev.dv_xname,
820 rc);
821 /* Nothing we can do on failure. Still try to idle the tpm. */
822 }
823
824 /* Tell the device to go idle. */
825 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_REQ);
826 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_REQ,
827 r | TPM_CRB_CTRL_REQ_GO_IDLE);
828
829 mask = TPM_CRB_CTRL_STS_IDLE_BIT;
830 if (tpm_waitfor(sc, TPM_CRB_CTRL_STS, mask, mask, 200)) {
831 printf("%s: failed to transition to idle state after read\n",
832 sc->sc_dev.dv_xname);
833 }
834
835 tpm_release_locality_crb(sc);
836
837 DPRINTF(("%s: %s completed\n", sc->sc_dev.dv_xname, __func__));
838 return 0;
839}
840
841int
842tpm_write_tis(struct tpm_softc *sc, void *buf, int len)
843{
844 uint8_t *p = buf;
845 uint8_t status;
846 size_t count = 0;
847 int rv, r;
848
849 if ((rv = tpm_request_locality_tis(sc, 0)) != 0)
850 return rv;
851
852 DPRINTF(("%s: %s %d:", sc->sc_dev.dv_xname, __func__, len));
853 for (r = 0; r < len; r++)
854 DPRINTF((" %02x", (uint8_t)(*(p + r))));
855 DPRINTF(("\n"));
856
857 /* read status */
858 status = tpm_status(sc);
859 if ((status & TPM_STS_CMD_READY) == 0) {
860 /* abort! */
861 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
862 TPM_STS_CMD_READY);
863 if ((rv = tpm_waitfor_status(sc, TPM_STS_CMD_READY,
864 TPM_READ_TMO))) {
865 DPRINTF(("%s: failed waiting for ready after abort "
866 "(0x%x)\n", sc->sc_dev.dv_xname, rv));
867 return rv;
868 }
869 }
870
871 while (count < len - 1) {
872 for (r = tpm_getburst(sc); r > 0 && count < len - 1; r--) {
873 DPRINTF(("%s: %s: write1(0x%x, 0x%x)\n",
874 sc->sc_dev.dv_xname, __func__, TPM_DATA, *p));
875 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_DATA, *p++);
876 count++;
877 }
878 if ((rv = tpm_waitfor_status(sc, TPM_STS_VALID | TPM_STS_DATA_EXPECT,
879 TPM_READ_TMO))) {
880 DPRINTF(("%s: %s: failed waiting for next byte (%d)\n",
881 sc->sc_dev.dv_xname, __func__, rv));
882 return rv;
883 }
884 }
885
886 DPRINTF(("%s: %s: write1(0x%x, 0x%x)\n", sc->sc_dev.dv_xname, __func__,
887 TPM_DATA, *p));
888 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_DATA, *p);
889 count++;
890
891 if ((rv = tpm_waitfor_status(sc, TPM_STS_VALID, TPM_READ_TMO))) {
892 DPRINTF(("%s: %s: failed after last byte (%d)\n",
893 sc->sc_dev.dv_xname, __func__, rv));
894 return rv;
895 }
896
897 if ((status = tpm_status(sc)) & TPM_STS_DATA_EXPECT) {
898 DPRINTF(("%s: %s: final status still expecting data: %b\n",
899 sc->sc_dev.dv_xname, __func__, status, TPM_STS_BITS));
900 return status;
901 }
902
903 DPRINTF(("%s: final status after write: %b\n", sc->sc_dev.dv_xname,
904 status, TPM_STS_BITS));
905
906 /* XXX: are we ever sending non-command data? */
907 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_GO);
908
909 return 0;
910}
911
912int
913tpm_write_crb(struct tpm_softc *sc, void *buf, int len)
914{
915 uint8_t *p = buf;
916 size_t count = 0;
917 uint32_t r, mask;
918
919 if (len > sc->sc_cmd_sz) {
920 printf("%s: requested write length larger than cmd buffer\n",
921 sc->sc_dev.dv_xname);
922 return EINVAL;
923 }
924
925 if (bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_STS)
926 & TPM_CRB_CTRL_STS_ERR_BIT) {
927 printf("%s: device error bit set\n", sc->sc_dev.dv_xname);
928 return EIO;
929 }
930
931 if (tpm_request_locality_crb(sc, 0)) {
932 printf("%s: failed to acquire locality\n", sc->sc_dev.dv_xname);
933 return EIO;
934 }
935
936 /* Clear cancellation bit */
937 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_CANCEL,
938 TPM_CRB_CTRL_CANCEL_CLEAR);
939
940 /* Toggle to idle state (if needed) and then to ready */
941 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_STS);
942 if(!(r & TPM_CRB_CTRL_STS_IDLE_BIT)) {
943 printf("%s: asking device to idle\n", sc->sc_dev.dv_xname);
944 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_REQ);
945 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_REQ,
946 r | TPM_CRB_CTRL_REQ_GO_IDLE);
947
948 mask = TPM_CRB_CTRL_STS_IDLE_BIT;
949 if (tpm_waitfor(sc, TPM_CRB_CTRL_STS, mask, mask, 200)) {
950 printf("%s: failed to transition to idle state before "
951 "write\n", sc->sc_dev.dv_xname);
952 return EIO;
953 }
954 }
955 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_REQ);
956 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_REQ,
957 r | TPM_CRB_CTRL_REQ_GO_READY);
958 mask = TPM_CRB_CTRL_REQ_GO_READY;
959 if (tpm_waitfor(sc, TPM_CRB_CTRL_STS, mask, !mask, 200)) {
960 printf("%s: failed to transition to ready state\n",
961 sc->sc_dev.dv_xname);
962 return EIO;
963 }
964
965 /* Write the command */
966 DPRINTF(("%s: %s %d:", sc->sc_dev.dv_xname, __func__, len));
967 while (count < len) {
968 DPRINTF((" %02x", (uint8_t)(*p)));
969 bus_space_write_1(sc->sc_bt, sc->sc_bh, sc->sc_cmd_off + count,
970 *p++);
971 count++;
972 }
973 DPRINTF(("\n"));
974 bus_space_barrier(sc->sc_bt, sc->sc_bh, sc->sc_cmd_off, len,
975 BUS_SPACE_BARRIER_WRITE);
976 DPRINTF(("%s: %s wrote %lu bytes\n", sc->sc_dev.dv_xname, __func__,
977 count));
978
979 /* Send the Start Command request */
980 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_START,
981 TPM_CRB_CTRL_START_CMD);
982 bus_space_barrier(sc->sc_bt, sc->sc_bh, TPM_CRB_CTRL_START, 4,
983 BUS_SPACE_BARRIER_WRITE);
984
985 /* Check if command was processed */
986 mask = ~0;
987 if (tpm_waitfor(sc, TPM_CRB_CTRL_START, mask, ~mask, 200)) {
988 printf("%s: timeout waiting for device to process command\n",
989 sc->sc_dev.dv_xname);
990 return EIO;
991 }
992
993 return 0;
994}