tpm.c revision 1.13 1 /* $NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $ */
2
3 /*
4 * Copyright (c) 2019 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Maxime Villard.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 2008, 2009 Michael Shalayeff
34 * Copyright (c) 2009, 2010 Hans-Joerg Hoexer
35 * All rights reserved.
36 *
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
42 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
43 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
44 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
45 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
46 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
47 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48 */
49
50 #include <sys/cdefs.h>
51 __KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $");
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
56 #include <sys/malloc.h>
57 #include <sys/proc.h>
58 #include <sys/device.h>
59 #include <sys/conf.h>
60 #include <sys/bus.h>
61 #include <sys/pmf.h>
62
63 #include <dev/ic/tpmreg.h>
64 #include <dev/ic/tpmvar.h>
65
66 #include "ioconf.h"
67
68 #define TPM_BUFSIZ 1024
69 #define TPM_HDRSIZE 10
70 #define TPM_PARAM_SIZE 0x0001 /* that's a flag */
71
72 /* Timeouts. */
73 #define TPM_ACCESS_TMO 2000 /* 2sec */
74 #define TPM_READY_TMO 2000 /* 2sec */
75 #define TPM_READ_TMO 2000 /* 2sec */
76 #define TPM_BURST_TMO 2000 /* 2sec */
77
78 #define TPM_CAPS_REQUIRED \
79 (TPM_INTF_DATA_AVAIL_INT|TPM_INTF_LOCALITY_CHANGE_INT| \
80 TPM_INTF_INT_LEVEL_LOW)
81
82 static const struct {
83 uint32_t devid;
84 const char *name;
85 int flags;
86 #define TPM_DEV_NOINTS 0x0001
87 } tpm_devs[] = {
88 { 0x000615d1, "IFX SLD 9630 TT 1.1", 0 },
89 { 0x000b15d1, "IFX SLB 9635 TT 1.2", 0 },
90 { 0x100214e4, "Broadcom BCM0102", TPM_DEV_NOINTS },
91 { 0x00fe1050, "WEC WPCT200", 0 },
92 { 0x687119fa, "SNS SSX35", 0 },
93 { 0x2e4d5453, "STM ST19WP18", 0 },
94 { 0x32021114, "ATML 97SC3203", TPM_DEV_NOINTS },
95 { 0x10408086, "INTEL INTC0102", 0 },
96 { 0, "", TPM_DEV_NOINTS },
97 };
98
99 static inline int
100 tpm_tmotohz(int tmo)
101 {
102 struct timeval tv;
103
104 tv.tv_sec = tmo / 1000;
105 tv.tv_usec = 1000 * (tmo % 1000);
106
107 return tvtohz(&tv);
108 }
109
110 static int
111 tpm_request_locality(struct tpm_softc *sc, int l)
112 {
113 uint32_t r;
114 int to, rv;
115
116 if (l != 0)
117 return EINVAL;
118
119 if ((bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
120 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) ==
121 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY))
122 return 0;
123
124 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
125 TPM_ACCESS_REQUEST_USE);
126
127 to = tpm_tmotohz(TPM_ACCESS_TMO);
128
129 while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
130 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
131 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) {
132 rv = tsleep(sc->sc_init, PRIBIO | PCATCH, "tpm_locality", 1);
133 if (rv && rv != EWOULDBLOCK) {
134 return rv;
135 }
136 }
137
138 if ((r & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
139 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
140 return EBUSY;
141 }
142
143 return 0;
144 }
145
146 static int
147 tpm_getburst(struct tpm_softc *sc)
148 {
149 int burst, to, rv;
150
151 to = tpm_tmotohz(TPM_BURST_TMO);
152
153 while (to--) {
154 /*
155 * Burst count is in bits 23:8, so read the two higher bytes.
156 */
157 burst = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 1);
158 burst |= bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 2)
159 << 8;
160
161 if (burst)
162 return burst;
163
164 rv = tsleep(sc, PRIBIO | PCATCH, "tpm_getburst", 1);
165 if (rv && rv != EWOULDBLOCK) {
166 return 0;
167 }
168 }
169
170 return 0;
171 }
172
173 static inline uint8_t
174 tpm_status(struct tpm_softc *sc)
175 {
176 return bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS) &
177 TPM_STS_STATUS_BITS;
178 }
179
180 /* -------------------------------------------------------------------------- */
181
182 /*
183 * Save TPM state on suspend. On resume we don't do anything, since the BIOS
184 * is supposed to restore the previously saved state.
185 */
186
187 bool
188 tpm12_suspend(device_t dev, const pmf_qual_t *qual)
189 {
190 struct tpm_softc *sc = device_private(dev);
191 static const uint8_t command[] = {
192 0, 193, /* TPM_TAG_RQU_COMMAND */
193 0, 0, 0, 10, /* Length in bytes */
194 0, 0, 0, 156 /* TPM_ORD_SaveStates */
195 };
196 uint8_t scratch[sizeof(command)];
197
198 (*sc->sc_write)(sc, &command, sizeof(command));
199 (*sc->sc_read)(sc, &scratch, sizeof(scratch), NULL, 0);
200
201 return true;
202 }
203
204 bool
205 tpm12_resume(device_t dev, const pmf_qual_t *qual)
206 {
207 return true;
208 }
209
210 /* -------------------------------------------------------------------------- */
211
212 /*
213 * Wait for given status bits using polling.
214 */
215 static int
216 tpm_waitfor_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan)
217 {
218 int rv;
219
220 while (((sc->sc_status = tpm_status(sc)) & mask) != mask && to--) {
221 rv = tsleep(chan, PRIBIO | PCATCH, "tpm_poll", 1);
222 if (rv && rv != EWOULDBLOCK) {
223 return rv;
224 }
225 }
226
227 return 0;
228 }
229
230 /*
231 * Wait for given status bits using interrupts.
232 */
233 static int
234 tpm_waitfor_int(struct tpm_softc *sc, uint8_t mask, int tmo, wchan_t chan,
235 int inttype)
236 {
237 int rv, to;
238
239 sc->sc_status = tpm_status(sc);
240 if ((sc->sc_status & mask) == mask)
241 return 0;
242
243 /*
244 * Enable interrupt on tpm chip. Note that interrupts on our
245 * level (SPL_TTY) are disabled (see tpm{read,write} et al) and
246 * will not be delivered to the cpu until we call tsleep(9) below.
247 */
248 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
249 bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) |
250 inttype);
251 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
252 bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) |
253 TPM_GLOBAL_INT_ENABLE);
254
255 sc->sc_status = tpm_status(sc);
256 if ((sc->sc_status & mask) == mask) {
257 rv = 0;
258 goto out;
259 }
260
261 to = tpm_tmotohz(tmo);
262
263 /*
264 * tsleep(9) enables interrupts on the cpu and returns after
265 * wake up with interrupts disabled again. Note that interrupts
266 * generated by the tpm chip while being at SPL_TTY are not lost
267 * but held and delivered as soon as the cpu goes below SPL_TTY.
268 */
269 rv = tsleep(chan, PRIBIO | PCATCH, "tpm_wait", to);
270
271 sc->sc_status = tpm_status(sc);
272 if ((sc->sc_status & mask) == mask)
273 rv = 0;
274
275 out:
276 /* Disable interrupts on tpm chip again. */
277 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
278 bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) &
279 ~TPM_GLOBAL_INT_ENABLE);
280 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
281 bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) &
282 ~inttype);
283
284 return rv;
285 }
286
287 /*
288 * Wait on given status bits, use interrupts where possible, otherwise poll.
289 */
290 static int
291 tpm_waitfor(struct tpm_softc *sc, uint8_t bits, int tmo, wchan_t chan)
292 {
293 int retry, to, rv;
294 uint8_t todo;
295
296 /*
297 * We use interrupts for TPM_STS_DATA_AVAIL and TPM_STS_VALID (if the
298 * TPM chip supports them) as waiting for those can take really long.
299 * The other TPM_STS* are not needed very often so we do not support
300 * them.
301 */
302 if (sc->sc_vector != -1) {
303 todo = bits;
304
305 /*
306 * Wait for data ready. This interrupt only occurs when both
307 * TPM_STS_VALID and TPM_STS_DATA_AVAIL are asserted. Thus we
308 * don't have to bother with TPM_STS_VALID separately and can
309 * just return.
310 *
311 * This only holds for interrupts! When using polling both
312 * flags have to be waited for, see below.
313 */
314 if ((bits & TPM_STS_DATA_AVAIL) &&
315 (sc->sc_capabilities & TPM_INTF_DATA_AVAIL_INT))
316 return tpm_waitfor_int(sc, bits, tmo, chan,
317 TPM_DATA_AVAIL_INT);
318
319 /* Wait for status valid bit. */
320 if ((bits & TPM_STS_VALID) &&
321 (sc->sc_capabilities & TPM_INTF_STS_VALID_INT)) {
322 rv = tpm_waitfor_int(sc, bits, tmo, chan,
323 TPM_STS_VALID_INT);
324 if (rv)
325 return rv;
326 todo = bits & ~TPM_STS_VALID;
327 }
328
329 /*
330 * When all flags have been taken care of, return. Otherwise
331 * use polling for eg TPM_STS_CMD_READY.
332 */
333 if (todo == 0)
334 return 0;
335 }
336
337 retry = 3;
338
339 restart:
340 /*
341 * If requested, wait for TPM_STS_VALID before dealing with any other
342 * flag. Eg when both TPM_STS_DATA_AVAIL and TPM_STS_VALID are
343 * requested, wait for the latter first.
344 */
345 todo = bits;
346 if (bits & TPM_STS_VALID)
347 todo = TPM_STS_VALID;
348 to = tpm_tmotohz(tmo);
349 again:
350 if ((rv = tpm_waitfor_poll(sc, todo, to, chan)) != 0)
351 return rv;
352
353 if ((todo & sc->sc_status) == TPM_STS_VALID) {
354 /* Now wait for other flags. */
355 todo = bits & ~TPM_STS_VALID;
356 to++;
357 goto again;
358 }
359
360 if ((todo & sc->sc_status) != todo) {
361 if (retry-- && (bits & TPM_STS_VALID)) {
362 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
363 TPM_STS_RESP_RETRY);
364 goto restart;
365 }
366 return EIO;
367 }
368
369 return 0;
370 }
371
372 int
373 tpm_intr(void *v)
374 {
375 struct tpm_softc *sc = v;
376 uint32_t reg;
377
378 reg = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS);
379 if (!(reg & (TPM_CMD_READY_INT | TPM_LOCALITY_CHANGE_INT |
380 TPM_STS_VALID_INT | TPM_DATA_AVAIL_INT)))
381 return 0;
382
383 if (reg & TPM_STS_VALID_INT)
384 wakeup(sc);
385 if (reg & TPM_CMD_READY_INT)
386 wakeup(sc->sc_write);
387 if (reg & TPM_DATA_AVAIL_INT)
388 wakeup(sc->sc_read);
389 if (reg & TPM_LOCALITY_CHANGE_INT)
390 wakeup(sc->sc_init);
391
392 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS, reg);
393
394 return 1;
395 }
396
397 /* -------------------------------------------------------------------------- */
398
399 /*
400 * TPM using TIS 1.2 interface.
401 */
402
403 int
404 tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh)
405 {
406 uint32_t cap;
407 uint8_t reg;
408 int tmo;
409
410 cap = bus_space_read_4(bt, bh, TPM_INTF_CAPABILITY);
411 if (cap == 0xffffffff)
412 return 0;
413 if ((cap & TPM_CAPS_REQUIRED) != TPM_CAPS_REQUIRED)
414 return 0;
415 if (!(cap & (TPM_INTF_INT_EDGE_RISING | TPM_INTF_INT_LEVEL_LOW)))
416 return 0;
417
418 /* Request locality 0. */
419 bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE);
420
421 /* Wait for it to become active. */
422 tmo = TPM_ACCESS_TMO; /* Milliseconds. */
423 while ((reg = bus_space_read_1(bt, bh, TPM_ACCESS) &
424 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
425 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && tmo--) {
426 DELAY(1000); /* 1 millisecond. */
427 }
428 if ((reg & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
429 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
430 return 0;
431 }
432
433 if (bus_space_read_4(bt, bh, TPM_ID) == 0xffffffff)
434 return 0;
435
436 return 1;
437 }
438
439 static int
440 tpm_tis12_irqinit(struct tpm_softc *sc, int irq, int idx)
441 {
442 uint32_t reg;
443
444 if ((irq == -1) || (tpm_devs[idx].flags & TPM_DEV_NOINTS)) {
445 sc->sc_vector = -1;
446 return 0;
447 }
448
449 /* Ack and disable all interrupts. */
450 reg = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE);
451 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
452 reg & ~TPM_GLOBAL_INT_ENABLE);
453 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS,
454 bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS));
455
456 /* Program interrupt vector. */
457 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_INT_VECTOR, irq);
458 sc->sc_vector = irq;
459
460 /* Program interrupt type. */
461 reg &= ~(TPM_INT_EDGE_RISING|TPM_INT_EDGE_FALLING|TPM_INT_LEVEL_HIGH|
462 TPM_INT_LEVEL_LOW);
463 reg |= TPM_GLOBAL_INT_ENABLE|TPM_CMD_READY_INT|TPM_LOCALITY_CHANGE_INT|
464 TPM_STS_VALID_INT|TPM_DATA_AVAIL_INT;
465 if (sc->sc_capabilities & TPM_INTF_INT_EDGE_RISING)
466 reg |= TPM_INT_EDGE_RISING;
467 else if (sc->sc_capabilities & TPM_INTF_INT_EDGE_FALLING)
468 reg |= TPM_INT_EDGE_FALLING;
469 else if (sc->sc_capabilities & TPM_INTF_INT_LEVEL_HIGH)
470 reg |= TPM_INT_LEVEL_HIGH;
471 else
472 reg |= TPM_INT_LEVEL_LOW;
473
474 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE, reg);
475
476 return 0;
477 }
478
479 int
480 tpm_tis12_init(struct tpm_softc *sc, int irq)
481 {
482 int i;
483
484 sc->sc_capabilities = bus_space_read_4(sc->sc_bt, sc->sc_bh,
485 TPM_INTF_CAPABILITY);
486 sc->sc_devid = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_ID);
487 sc->sc_rev = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_REV);
488
489 for (i = 0; tpm_devs[i].devid; i++) {
490 if (tpm_devs[i].devid == sc->sc_devid)
491 break;
492 }
493
494 if (tpm_devs[i].devid)
495 aprint_normal_dev(sc->sc_dev, "%s rev 0x%x\n",
496 tpm_devs[i].name, sc->sc_rev);
497 else
498 aprint_normal_dev(sc->sc_dev, "device 0x%08x rev 0x%x\n",
499 sc->sc_devid, sc->sc_rev);
500
501 if (tpm_tis12_irqinit(sc, irq, i))
502 return 1;
503
504 if (tpm_request_locality(sc, 0))
505 return 1;
506
507 /* Abort whatever it thought it was doing. */
508 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
509
510 return 0;
511 }
512
513 int
514 tpm_tis12_start(struct tpm_softc *sc, int flag)
515 {
516 int rv;
517
518 if (flag == UIO_READ) {
519 rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
520 TPM_READ_TMO, sc->sc_read);
521 return rv;
522 }
523
524 /* Request the 0th locality. */
525 if ((rv = tpm_request_locality(sc, 0)) != 0)
526 return rv;
527
528 sc->sc_status = tpm_status(sc);
529 if (sc->sc_status & TPM_STS_CMD_READY)
530 return 0;
531
532 /* Abort previous and restart. */
533 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
534 rv = tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO, sc->sc_write);
535 if (rv)
536 return rv;
537
538 return 0;
539 }
540
541 int
542 tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count,
543 int flags)
544 {
545 uint8_t *p = buf;
546 size_t cnt;
547 int rv, n, bcnt;
548
549 cnt = 0;
550 while (len > 0) {
551 rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
552 TPM_READ_TMO, sc->sc_read);
553 if (rv)
554 return rv;
555
556 bcnt = tpm_getburst(sc);
557 n = MIN(len, bcnt);
558
559 for (; n--; len--) {
560 *p++ = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_DATA);
561 cnt++;
562 }
563
564 if ((flags & TPM_PARAM_SIZE) == 0 && cnt >= 6)
565 break;
566 }
567
568 if (count)
569 *count = cnt;
570
571 return 0;
572 }
573
574 int
575 tpm_tis12_write(struct tpm_softc *sc, const void *buf, size_t len)
576 {
577 const uint8_t *p = buf;
578 size_t cnt;
579 int rv, r;
580
581 if (len == 0)
582 return 0;
583 if ((rv = tpm_request_locality(sc, 0)) != 0)
584 return rv;
585
586 cnt = 0;
587 while (cnt < len - 1) {
588 for (r = tpm_getburst(sc); r > 0 && cnt < len - 1; r--) {
589 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_DATA, *p++);
590 cnt++;
591 }
592 if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc))) {
593 return rv;
594 }
595 sc->sc_status = tpm_status(sc);
596 if (!(sc->sc_status & TPM_STS_DATA_EXPECT)) {
597 return EIO;
598 }
599 }
600
601 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_DATA, *p++);
602 cnt++;
603
604 if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc))) {
605 return rv;
606 }
607 if ((sc->sc_status & TPM_STS_DATA_EXPECT) != 0) {
608 return EIO;
609 }
610
611 return 0;
612 }
613
614 int
615 tpm_tis12_end(struct tpm_softc *sc, int flag, int err)
616 {
617 int rv = 0;
618
619 if (flag == UIO_READ) {
620 rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_read);
621 if (rv)
622 return rv;
623
624 /* Still more data? */
625 sc->sc_status = tpm_status(sc);
626 if (!err && ((sc->sc_status & TPM_STS_DATA_AVAIL) ==
627 TPM_STS_DATA_AVAIL)) {
628 rv = EIO;
629 }
630
631 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
632 TPM_STS_CMD_READY);
633
634 /* Release the 0th locality. */
635 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
636 TPM_ACCESS_ACTIVE_LOCALITY);
637 } else {
638 /* Hungry for more? */
639 sc->sc_status = tpm_status(sc);
640 if (!err && (sc->sc_status & TPM_STS_DATA_EXPECT)) {
641 rv = EIO;
642 }
643
644 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
645 err ? TPM_STS_CMD_READY : TPM_STS_GO);
646 }
647
648 return rv;
649 }
650
651 /* -------------------------------------------------------------------------- */
652
653 static dev_type_open(tpmopen);
654 static dev_type_close(tpmclose);
655 static dev_type_read(tpmread);
656 static dev_type_write(tpmwrite);
657 static dev_type_ioctl(tpmioctl);
658
659 const struct cdevsw tpm_cdevsw = {
660 .d_open = tpmopen,
661 .d_close = tpmclose,
662 .d_read = tpmread,
663 .d_write = tpmwrite,
664 .d_ioctl = tpmioctl,
665 .d_stop = nostop,
666 .d_tty = notty,
667 .d_poll = nopoll,
668 .d_mmap = nommap,
669 .d_kqfilter = nokqfilter,
670 .d_discard = nodiscard,
671 .d_flag = D_OTHER,
672 };
673
674 #define TPMUNIT(a) minor(a)
675
676 static int
677 tpmopen(dev_t dev, int flag, int mode, struct lwp *l)
678 {
679 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
680
681 if (sc == NULL)
682 return ENXIO;
683 if (sc->sc_flags & TPM_OPEN)
684 return EBUSY;
685
686 sc->sc_flags |= TPM_OPEN;
687
688 return 0;
689 }
690
691 static int
692 tpmclose(dev_t dev, int flag, int mode, struct lwp *l)
693 {
694 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
695
696 if (sc == NULL)
697 return ENXIO;
698 if (!(sc->sc_flags & TPM_OPEN))
699 return EINVAL;
700
701 sc->sc_flags &= ~TPM_OPEN;
702
703 return 0;
704 }
705
706 static int
707 tpmread(dev_t dev, struct uio *uio, int flags)
708 {
709 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
710 uint8_t buf[TPM_BUFSIZ], *p;
711 size_t cnt, len, n;
712 int rv, s;
713
714 if (sc == NULL)
715 return ENXIO;
716
717 s = spltty();
718 if ((rv = (*sc->sc_start)(sc, UIO_READ)))
719 goto out;
720
721 if ((rv = (*sc->sc_read)(sc, buf, TPM_HDRSIZE, &cnt, 0))) {
722 (*sc->sc_end)(sc, UIO_READ, rv);
723 goto out;
724 }
725
726 len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5];
727 if (len > uio->uio_resid) {
728 rv = EIO;
729 (*sc->sc_end)(sc, UIO_READ, rv);
730 goto out;
731 }
732
733 /* Copy out header. */
734 if ((rv = uiomove(buf, cnt, uio))) {
735 (*sc->sc_end)(sc, UIO_READ, rv);
736 goto out;
737 }
738
739 /* Get remaining part of the answer (if anything is left). */
740 for (len -= cnt, p = buf, n = sizeof(buf); len > 0; p = buf, len -= n,
741 n = sizeof(buf)) {
742 n = MIN(n, len);
743 if ((rv = (*sc->sc_read)(sc, p, n, NULL, TPM_PARAM_SIZE))) {
744 (*sc->sc_end)(sc, UIO_READ, rv);
745 goto out;
746 }
747 p += n;
748 if ((rv = uiomove(buf, p - buf, uio))) {
749 (*sc->sc_end)(sc, UIO_READ, rv);
750 goto out;
751 }
752 }
753
754 rv = (*sc->sc_end)(sc, UIO_READ, rv);
755 out:
756 splx(s);
757 return rv;
758 }
759
760 static int
761 tpmwrite(dev_t dev, struct uio *uio, int flags)
762 {
763 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
764 uint8_t buf[TPM_BUFSIZ];
765 int n, rv, s;
766
767 if (sc == NULL)
768 return ENXIO;
769
770 s = spltty();
771
772 n = MIN(sizeof(buf), uio->uio_resid);
773 if ((rv = uiomove(buf, n, uio))) {
774 goto out;
775 }
776 if ((rv = (*sc->sc_start)(sc, UIO_WRITE))) {
777 goto out;
778 }
779 if ((rv = (*sc->sc_write)(sc, buf, n))) {
780 goto out;
781 }
782
783 rv = (*sc->sc_end)(sc, UIO_WRITE, rv);
784 out:
785 splx(s);
786 return rv;
787 }
788
789 static int
790 tpmioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
791 {
792 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
793 struct tpm_ioc_getinfo *info;
794
795 if (sc == NULL)
796 return ENXIO;
797
798 switch (cmd) {
799 case TPM_IOC_GETINFO:
800 info = addr;
801 info->api_version = TPM_API_VERSION;
802 info->tpm_version = sc->sc_ver;
803 info->device_id = sc->sc_devid;
804 info->device_rev = sc->sc_rev;
805 info->device_caps = sc->sc_capabilities;
806 return 0;
807 default:
808 break;
809 }
810
811 return ENOTTY;
812 }
813