Home | History | Annotate | Line # | Download | only in ic
tpm.c revision 1.12.4.1
      1 /*	$NetBSD: tpm.c,v 1.12.4.1 2020/04/13 08:04:22 martin 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.12.4.1 2020/04/13 08:04:22 martin 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 CTASSERT(sizeof(struct tpm_header) == 10);
     69 
     70 #define TPM_BUFSIZ	1024
     71 
     72 #define TPM_PARAM_SIZE	0x0001	/* that's a flag */
     73 
     74 /* Timeouts. */
     75 #define TPM_ACCESS_TMO	2000	/* 2sec */
     76 #define TPM_READY_TMO	2000	/* 2sec */
     77 #define TPM_READ_TMO	2000	/* 2sec */
     78 #define TPM_BURST_TMO	2000	/* 2sec */
     79 
     80 #define TPM_CAPS_REQUIRED \
     81 	(TPM_INTF_DATA_AVAIL_INT|TPM_INTF_LOCALITY_CHANGE_INT| \
     82 	 TPM_INTF_INT_LEVEL_LOW)
     83 
     84 static inline int
     85 tpm_tmotohz(int tmo)
     86 {
     87 	struct timeval tv;
     88 
     89 	tv.tv_sec = tmo / 1000;
     90 	tv.tv_usec = 1000 * (tmo % 1000);
     91 
     92 	return tvtohz(&tv);
     93 }
     94 
     95 static int
     96 tpm_getburst(struct tpm_softc *sc)
     97 {
     98 	int burst, to, rv;
     99 
    100 	to = tpm_tmotohz(TPM_BURST_TMO);
    101 
    102 	while (to--) {
    103 		/*
    104 		 * Burst count is in bits 23:8, so read the two higher bytes.
    105 		 */
    106 		burst = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 1);
    107 		burst |= bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 2)
    108 		    << 8;
    109 
    110 		if (burst)
    111 			return burst;
    112 
    113 		rv = tsleep(sc, PCATCH, "tpm_getburst", 1);
    114 		if (rv && rv != EWOULDBLOCK) {
    115 			return 0;
    116 		}
    117 	}
    118 
    119 	return 0;
    120 }
    121 
    122 static inline uint8_t
    123 tpm_status(struct tpm_softc *sc)
    124 {
    125 	return bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS) &
    126 	    TPM_STS_STATUS_BITS;
    127 }
    128 
    129 /* -------------------------------------------------------------------------- */
    130 
    131 static bool
    132 tpm12_suspend(struct tpm_softc *sc)
    133 {
    134 	static const uint8_t command[10] = {
    135 		0x00, 0xC1,		/* TPM_TAG_RQU_COMMAND */
    136 		0x00, 0x00, 0x00, 10,	/* Length in bytes */
    137 		0x00, 0x00, 0x00, 0x98	/* TPM_ORD_SaveState */
    138 	};
    139 	struct tpm_header response;
    140 
    141 	if ((*sc->sc_intf->write)(sc, &command, sizeof(command)) != 0)
    142 		return false;
    143 	if ((*sc->sc_intf->read)(sc, &response, sizeof(response), NULL, 0) != 0)
    144 		return false;
    145 	if (TPM_BE32(response.code) != 0)
    146 		return false;
    147 
    148 	return true;
    149 }
    150 
    151 static bool
    152 tpm20_suspend(struct tpm_softc *sc)
    153 {
    154 	static const uint8_t command[12] = {
    155 		0x80, 0x01,		/* TPM_ST_NO_SESSIONS */
    156 		0x00, 0x00, 0x00, 12,	/* Length in bytes */
    157 		0x00, 0x00, 0x01, 0x45,	/* TPM_CC_Shutdown */
    158 		0x00, 0x01		/* TPM_SU_STATE */
    159 	};
    160 	struct tpm_header response;
    161 
    162 	if ((*sc->sc_intf->write)(sc, &command, sizeof(command)) != 0)
    163 		return false;
    164 	if ((*sc->sc_intf->read)(sc, &response, sizeof(response), NULL, 0) != 0)
    165 		return false;
    166 	if (TPM_BE32(response.code) != 0)
    167 		return false;
    168 
    169 	return true;
    170 }
    171 
    172 bool
    173 tpm_suspend(device_t dev, const pmf_qual_t *qual)
    174 {
    175 	struct tpm_softc *sc = device_private(dev);
    176 
    177 	switch (sc->sc_ver) {
    178 	case TPM_1_2:
    179 		return tpm12_suspend(sc);
    180 	case TPM_2_0:
    181 		return tpm20_suspend(sc);
    182 	default:
    183 		panic("%s: impossible", __func__);
    184 	}
    185 }
    186 
    187 bool
    188 tpm_resume(device_t dev, const pmf_qual_t *qual)
    189 {
    190 	/*
    191 	 * Don't do anything, the BIOS is supposed to restore the previously
    192 	 * saved state.
    193 	 */
    194 	return true;
    195 }
    196 
    197 /* -------------------------------------------------------------------------- */
    198 
    199 static int
    200 tpm_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan)
    201 {
    202 	int rv;
    203 
    204 	while (((sc->sc_status = tpm_status(sc)) & mask) != mask && to--) {
    205 		rv = tsleep(chan, PCATCH, "tpm_poll", 1);
    206 		if (rv && rv != EWOULDBLOCK) {
    207 			return rv;
    208 		}
    209 	}
    210 
    211 	return 0;
    212 }
    213 
    214 static int
    215 tpm_waitfor(struct tpm_softc *sc, uint8_t bits, int tmo, wchan_t chan)
    216 {
    217 	int retry, to, rv;
    218 	uint8_t todo;
    219 
    220 	to = tpm_tmotohz(tmo);
    221 	retry = 3;
    222 
    223 restart:
    224 	todo = bits;
    225 
    226 	/*
    227 	 * TPM_STS_VALID has priority over the others.
    228 	 */
    229 	if (todo & TPM_STS_VALID) {
    230 		if ((rv = tpm_poll(sc, TPM_STS_VALID, to+1, chan)) != 0)
    231 			return rv;
    232 		todo &= ~TPM_STS_VALID;
    233 	}
    234 
    235 	if ((rv = tpm_poll(sc, todo, to, chan)) != 0)
    236 		return rv;
    237 
    238 	if ((todo & sc->sc_status) != todo) {
    239 		if ((retry-- > 0) && (bits & TPM_STS_VALID)) {
    240 			bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
    241 			    TPM_STS_RESP_RETRY);
    242 			goto restart;
    243 		}
    244 		return EIO;
    245 	}
    246 
    247 	return 0;
    248 }
    249 
    250 /* -------------------------------------------------------------------------- */
    251 
    252 /*
    253  * TPM using the TIS 1.2 interface.
    254  */
    255 
    256 static int
    257 tpm12_request_locality(struct tpm_softc *sc, int l)
    258 {
    259 	uint32_t r;
    260 	int to, rv;
    261 
    262 	if (l != 0)
    263 		return EINVAL;
    264 
    265 	if ((bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
    266 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) ==
    267 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY))
    268 		return 0;
    269 
    270 	bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
    271 	    TPM_ACCESS_REQUEST_USE);
    272 
    273 	to = tpm_tmotohz(TPM_ACCESS_TMO);
    274 
    275 	while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
    276 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
    277 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) {
    278 		rv = tsleep(sc->sc_intf->init, PCATCH, "tpm_locality", 1);
    279 		if (rv && rv != EWOULDBLOCK) {
    280 			return rv;
    281 		}
    282 	}
    283 
    284 	if ((r & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
    285 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
    286 		return EBUSY;
    287 	}
    288 
    289 	return 0;
    290 }
    291 
    292 static int
    293 tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh)
    294 {
    295 	uint32_t cap;
    296 	uint8_t reg;
    297 	int tmo;
    298 
    299 	cap = bus_space_read_4(bt, bh, TPM_INTF_CAPABILITY);
    300 	if (cap == 0xffffffff)
    301 		return EINVAL;
    302 	if ((cap & TPM_CAPS_REQUIRED) != TPM_CAPS_REQUIRED)
    303 		return ENOTSUP;
    304 
    305 	/* Request locality 0. */
    306 	bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE);
    307 
    308 	/* Wait for it to become active. */
    309 	tmo = TPM_ACCESS_TMO; /* Milliseconds. */
    310 	while ((reg = bus_space_read_1(bt, bh, TPM_ACCESS) &
    311 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
    312 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && tmo--) {
    313 		DELAY(1000); /* 1 millisecond. */
    314 	}
    315 	if ((reg & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
    316 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
    317 		return ETIMEDOUT;
    318 	}
    319 
    320 	if (bus_space_read_4(bt, bh, TPM_ID) == 0xffffffff)
    321 		return EINVAL;
    322 
    323 	return 0;
    324 }
    325 
    326 static int
    327 tpm_tis12_init(struct tpm_softc *sc)
    328 {
    329 	int rv;
    330 
    331 	sc->sc_caps = bus_space_read_4(sc->sc_bt, sc->sc_bh,
    332 	    TPM_INTF_CAPABILITY);
    333 	sc->sc_devid = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_ID);
    334 	sc->sc_rev = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_REV);
    335 
    336 	aprint_normal_dev(sc->sc_dev, "device 0x%08x rev 0x%x\n",
    337 	    sc->sc_devid, sc->sc_rev);
    338 
    339 	if ((rv = tpm12_request_locality(sc, 0)) != 0)
    340 		return rv;
    341 
    342 	/* Abort whatever it thought it was doing. */
    343 	bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
    344 
    345 	return 0;
    346 }
    347 
    348 static int
    349 tpm_tis12_start(struct tpm_softc *sc, int rw)
    350 {
    351 	int rv;
    352 
    353 	if (rw == UIO_READ) {
    354 		rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
    355 		    TPM_READ_TMO, sc->sc_intf->read);
    356 		return rv;
    357 	}
    358 
    359 	/* Request the 0th locality. */
    360 	if ((rv = tpm12_request_locality(sc, 0)) != 0)
    361 		return rv;
    362 
    363 	sc->sc_status = tpm_status(sc);
    364 	if (sc->sc_status & TPM_STS_CMD_READY)
    365 		return 0;
    366 
    367 	/* Abort previous and restart. */
    368 	bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
    369 	rv = tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO, sc->sc_intf->write);
    370 	if (rv)
    371 		return rv;
    372 
    373 	return 0;
    374 }
    375 
    376 static int
    377 tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count,
    378     int flags)
    379 {
    380 	uint8_t *p = buf;
    381 	size_t cnt;
    382 	int rv, n;
    383 
    384 	cnt = 0;
    385 	while (len > 0) {
    386 		rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
    387 		    TPM_READ_TMO, sc->sc_intf->read);
    388 		if (rv)
    389 			return rv;
    390 
    391 		n = MIN(len, tpm_getburst(sc));
    392 		while (n > 0) {
    393 			*p++ = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_DATA);
    394 			cnt++;
    395 			len--;
    396 			n--;
    397 		}
    398 
    399 		if ((flags & TPM_PARAM_SIZE) == 0 && cnt >= 6)
    400 			break;
    401 	}
    402 
    403 	if (count)
    404 		*count = cnt;
    405 
    406 	return 0;
    407 }
    408 
    409 static int
    410 tpm_tis12_write(struct tpm_softc *sc, const void *buf, size_t len)
    411 {
    412 	const uint8_t *p = buf;
    413 	size_t cnt;
    414 	int rv, r;
    415 
    416 	if (len == 0)
    417 		return 0;
    418 	if ((rv = tpm12_request_locality(sc, 0)) != 0)
    419 		return rv;
    420 
    421 	cnt = 0;
    422 	while (cnt < len - 1) {
    423 		for (r = tpm_getburst(sc); r > 0 && cnt < len - 1; r--) {
    424 			bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_DATA, *p++);
    425 			cnt++;
    426 		}
    427 		if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc))) {
    428 			return rv;
    429 		}
    430 		sc->sc_status = tpm_status(sc);
    431 		if (!(sc->sc_status & TPM_STS_DATA_EXPECT)) {
    432 			return EIO;
    433 		}
    434 	}
    435 
    436 	bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_DATA, *p++);
    437 	cnt++;
    438 
    439 	if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc))) {
    440 		return rv;
    441 	}
    442 	if ((sc->sc_status & TPM_STS_DATA_EXPECT) != 0) {
    443 		return EIO;
    444 	}
    445 
    446 	return 0;
    447 }
    448 
    449 static int
    450 tpm_tis12_end(struct tpm_softc *sc, int rw, int err)
    451 {
    452 	int rv = 0;
    453 
    454 	if (rw == UIO_READ) {
    455 		rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_intf->read);
    456 		if (rv)
    457 			return rv;
    458 
    459 		/* Still more data? */
    460 		sc->sc_status = tpm_status(sc);
    461 		if (!err && (sc->sc_status & TPM_STS_DATA_AVAIL)) {
    462 			rv = EIO;
    463 		}
    464 
    465 		bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
    466 		    TPM_STS_CMD_READY);
    467 
    468 		/* Release the 0th locality. */
    469 		bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
    470 		    TPM_ACCESS_ACTIVE_LOCALITY);
    471 	} else {
    472 		/* Hungry for more? */
    473 		sc->sc_status = tpm_status(sc);
    474 		if (!err && (sc->sc_status & TPM_STS_DATA_EXPECT)) {
    475 			rv = EIO;
    476 		}
    477 
    478 		bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
    479 		    err ? TPM_STS_CMD_READY : TPM_STS_GO);
    480 	}
    481 
    482 	return rv;
    483 }
    484 
    485 const struct tpm_intf tpm_intf_tis12 = {
    486 	.version = TIS_1_2,
    487 	.probe = tpm_tis12_probe,
    488 	.init = tpm_tis12_init,
    489 	.start = tpm_tis12_start,
    490 	.read = tpm_tis12_read,
    491 	.write = tpm_tis12_write,
    492 	.end = tpm_tis12_end
    493 };
    494 
    495 /* -------------------------------------------------------------------------- */
    496 
    497 static dev_type_open(tpmopen);
    498 static dev_type_close(tpmclose);
    499 static dev_type_read(tpmread);
    500 static dev_type_write(tpmwrite);
    501 static dev_type_ioctl(tpmioctl);
    502 
    503 const struct cdevsw tpm_cdevsw = {
    504 	.d_open = tpmopen,
    505 	.d_close = tpmclose,
    506 	.d_read = tpmread,
    507 	.d_write = tpmwrite,
    508 	.d_ioctl = tpmioctl,
    509 	.d_stop = nostop,
    510 	.d_tty = notty,
    511 	.d_poll = nopoll,
    512 	.d_mmap = nommap,
    513 	.d_kqfilter = nokqfilter,
    514 	.d_discard = nodiscard,
    515 	.d_flag = D_OTHER | D_MPSAFE,
    516 };
    517 
    518 static int
    519 tpmopen(dev_t dev, int flag, int mode, struct lwp *l)
    520 {
    521 	struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
    522 	int ret = 0;
    523 
    524 	if (sc == NULL)
    525 		return ENXIO;
    526 
    527 	mutex_enter(&sc->sc_lock);
    528 	if (sc->sc_busy) {
    529 		ret = EBUSY;
    530 	} else {
    531 		sc->sc_busy = true;
    532 	}
    533 	mutex_exit(&sc->sc_lock);
    534 
    535 	return ret;
    536 }
    537 
    538 static int
    539 tpmclose(dev_t dev, int flag, int mode, struct lwp *l)
    540 {
    541 	struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
    542 	int ret = 0;
    543 
    544 	if (sc == NULL)
    545 		return ENXIO;
    546 
    547 	mutex_enter(&sc->sc_lock);
    548 	if (!sc->sc_busy) {
    549 		ret = EINVAL;
    550 	} else {
    551 		sc->sc_busy = false;
    552 	}
    553 	mutex_exit(&sc->sc_lock);
    554 
    555 	return ret;
    556 }
    557 
    558 static int
    559 tpmread(dev_t dev, struct uio *uio, int flags)
    560 {
    561 	struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
    562 	struct tpm_header hdr;
    563 	uint8_t buf[TPM_BUFSIZ];
    564 	size_t cnt, len, n;
    565 	int rv;
    566 
    567 	if (sc == NULL)
    568 		return ENXIO;
    569 
    570 	if ((rv = (*sc->sc_intf->start)(sc, UIO_READ)))
    571 		return rv;
    572 
    573 	/* Get the header. */
    574 	if ((rv = (*sc->sc_intf->read)(sc, &hdr, sizeof(hdr), &cnt, 0))) {
    575 		goto out;
    576 	}
    577 	len = TPM_BE32(hdr.length);
    578 	if (len > uio->uio_resid || len < cnt) {
    579 		rv = EIO;
    580 		goto out;
    581 	}
    582 
    583 	/* Copy out the header. */
    584 	if ((rv = uiomove(&hdr, cnt, uio))) {
    585 		goto out;
    586 	}
    587 
    588 	/* Process the rest. */
    589 	len -= cnt;
    590 	while (len > 0) {
    591 		n = MIN(sizeof(buf), len);
    592 		if ((rv = (*sc->sc_intf->read)(sc, buf, n, NULL, TPM_PARAM_SIZE))) {
    593 			goto out;
    594 		}
    595 		if ((rv = uiomove(buf, n, uio))) {
    596 			goto out;
    597 		}
    598 		len -= n;
    599 	}
    600 
    601 out:
    602 	rv = (*sc->sc_intf->end)(sc, UIO_READ, rv);
    603 	return rv;
    604 }
    605 
    606 static int
    607 tpmwrite(dev_t dev, struct uio *uio, int flags)
    608 {
    609 	struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
    610 	uint8_t buf[TPM_BUFSIZ];
    611 	int n, rv;
    612 
    613 	if (sc == NULL)
    614 		return ENXIO;
    615 
    616 	n = MIN(sizeof(buf), uio->uio_resid);
    617 	if ((rv = uiomove(buf, n, uio))) {
    618 		goto out;
    619 	}
    620 	if ((rv = (*sc->sc_intf->start)(sc, UIO_WRITE))) {
    621 		goto out;
    622 	}
    623 	if ((rv = (*sc->sc_intf->write)(sc, buf, n))) {
    624 		goto out;
    625 	}
    626 
    627 	rv = (*sc->sc_intf->end)(sc, UIO_WRITE, rv);
    628 out:
    629 	return rv;
    630 }
    631 
    632 static int
    633 tpmioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
    634 {
    635 	struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
    636 	struct tpm_ioc_getinfo *info;
    637 
    638 	if (sc == NULL)
    639 		return ENXIO;
    640 
    641 	switch (cmd) {
    642 	case TPM_IOC_GETINFO:
    643 		info = addr;
    644 		info->api_version = TPM_API_VERSION;
    645 		info->tpm_version = sc->sc_ver;
    646 		info->itf_version = sc->sc_intf->version;
    647 		info->device_id = sc->sc_devid;
    648 		info->device_rev = sc->sc_rev;
    649 		info->device_caps = sc->sc_caps;
    650 		return 0;
    651 	default:
    652 		break;
    653 	}
    654 
    655 	return ENOTTY;
    656 }
    657