diff --git a/share/man/man4/tpm.4 b/share/man/man4/tpm.4 index aa2d56e72f58..4fa10af5cc06 100644 --- a/share/man/man4/tpm.4 +++ b/share/man/man4/tpm.4 @@ -1,20 +1,33 @@ -.\" $NetBSD: tpm.4,v 1.4 2018/02/22 01:40:49 pgoyette Exp $ +.\" $NetBSD: tpm.4,v 1.5 2019/10/08 18:43:03 maxv Exp $ .\" -.\" Copyright (c) 2010 Hans-Jörg Höxer, +.\" Copyright (c) 2019 The NetBSD Foundation, Inc. +.\" All rights reserved. .\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Maxime Villard. .\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. .\" -.Dd February 22, 2018 +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd October 6, 2019 .Dt TPM 4 .Os .Sh NAME @@ -22,40 +35,22 @@ .Nd Trusted Platform Module .Sh SYNOPSIS .Cd "tpm* at isa? iomem 0xfed40000" -.Cd "tpm* at isa? iomem 0xfed40000 irq 7" .Cd "tpm* at acpi?" .Sh DESCRIPTION The .Nm -driver provides support for various trusted platform modules (TPM) that can -store cryptographic keys. +driver provides support for various Trusted Platform Module (TPM) chips. .Pp Supported modules: .Pp .Bl -bullet -compact -offset indent .It -Atmel 97SC3203 +TPM 2.0 chips over ACPI .It -Broadcom BCM0102 -.It -Infineon IFX SLD 9630 TT 1.1 and IFX SLB 9635 TT 1.2 -.It -Intel INTC0102 -.It -Sinosun SNS SSX35 -.It -STM ST19WP18 -.It -Winbond WEC WPCT200 +TPM 1.2 chips over ISA .El .Pp -The driver can be configured to use an IRQ by providing a free ISA -interrupt vector using the keyword -.Em irq -in the kernel configuration file or using -.Xr config 1 . -If not IRQ is specified, the driver uses polling. -This is the default configuration. +Note that the supported interface version is TIS1.2 in each case. .Sh SEE ALSO .Xr config 1 , .Xr intro 4 @@ -64,6 +59,7 @@ This is the default configuration. The .Nm driver was written by +.An Maxime Villard , .An Michael Shalayeff and .An Hans-Joerg Hoexer . diff --git a/sys/dev/acpi/tpm_acpi.c b/sys/dev/acpi/tpm_acpi.c index bfbbd76526ad..08c415451c49 100644 --- a/sys/dev/acpi/tpm_acpi.c +++ b/sys/dev/acpi/tpm_acpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: tpm_acpi.c,v 1.8 2019/06/22 12:57:40 maxv Exp $ */ +/* $NetBSD: tpm_acpi.c,v 1.9 2019/10/08 18:43:02 maxv Exp $ */ /* * Copyright (c) 2012, 2019 The NetBSD Foundation, Inc. @@ -30,10 +30,9 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.8 2019/06/22 12:57:40 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.9 2019/10/08 18:43:02 maxv Exp $"); #include -#include #include #include #include @@ -45,8 +44,6 @@ __KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.8 2019/06/22 12:57:40 maxv Exp $"); #include #include -#include - #include "ioconf.h" #define _COMPONENT ACPI_RESOURCE_COMPONENT @@ -100,41 +97,41 @@ tpm_acpi_attach(device_t parent, device_t self, void *aux) struct acpi_attach_args *aa = aux; struct acpi_resources res; struct acpi_mem *mem; - struct acpi_irq *irq; bus_addr_t base; bus_addr_t size; - int rv, inum; - - sc->sc_dev = self; - sc->sc_ver = TPM_2_0; + int rv; rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", &res, &acpi_resource_parse_ops_default); if (ACPI_FAILURE(rv)) { - aprint_error_dev(sc->sc_dev, "cannot parse resources %d\n", rv); + aprint_error_dev(self, "cannot parse resources %d\n", rv); return; } mem = acpi_res_mem(&res, 0); if (mem == NULL) { - aprint_error_dev(sc->sc_dev, "cannot find mem\n"); + aprint_error_dev(self, "cannot find mem\n"); goto out; } if (mem->ar_length != TPM_SPACE_SIZE) { - aprint_error_dev(sc->sc_dev, - "wrong size mem %"PRIu64" != %u\n", + aprint_error_dev(self, "wrong size mem %"PRIu64" != %u\n", (uint64_t)mem->ar_length, TPM_SPACE_SIZE); goto out; } - base = mem->ar_base; - size = mem->ar_length; - sc->sc_bt = aa->aa_memt; + sc->sc_dev = self; + sc->sc_ver = TPM_2_0; + mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); + sc->sc_busy = false; sc->sc_init = tpm_tis12_init; sc->sc_start = tpm_tis12_start; sc->sc_read = tpm_tis12_read; sc->sc_write = tpm_tis12_write; sc->sc_end = tpm_tis12_end; + sc->sc_bt = aa->aa_memt; + + base = mem->ar_base; + size = mem->ar_length; if (bus_space_map(sc->sc_bt, base, size, 0, &sc->sc_bh)) { aprint_error_dev(sc->sc_dev, "cannot map registers\n"); @@ -146,24 +143,11 @@ tpm_acpi_attach(device_t parent, device_t self, void *aux) goto out1; } - irq = acpi_res_irq(&res, 0); - if (irq == NULL) - inum = -1; - else - inum = irq->ar_irq; - - if ((rv = (*sc->sc_init)(sc, inum)) != 0) { + if ((*sc->sc_init)(sc) != 0) { aprint_error_dev(sc->sc_dev, "cannot init device %d\n", rv); goto out1; } - if (inum != -1 && - (sc->sc_ih = isa_intr_establish(aa->aa_ic, irq->ar_irq, - IST_EDGE, IPL_TTY, tpm_intr, sc)) == NULL) { - aprint_error_dev(sc->sc_dev, "cannot establish interrupt\n"); - goto out1; - } - acpi_resource_cleanup(&res); return; diff --git a/sys/dev/ic/tpm.c b/sys/dev/ic/tpm.c index bcc113451edd..46acac40559c 100644 --- a/sys/dev/ic/tpm.c +++ b/sys/dev/ic/tpm.c @@ -1,4 +1,4 @@ -/* $NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $ */ +/* $NetBSD: tpm.c,v 1.14 2019/10/08 18:43:02 maxv Exp $ */ /* * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.14 2019/10/08 18:43:02 maxv Exp $"); #include #include @@ -67,6 +67,7 @@ __KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $"); #define TPM_BUFSIZ 1024 #define TPM_HDRSIZE 10 + #define TPM_PARAM_SIZE 0x0001 /* that's a flag */ /* Timeouts. */ @@ -79,23 +80,6 @@ __KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $"); (TPM_INTF_DATA_AVAIL_INT|TPM_INTF_LOCALITY_CHANGE_INT| \ TPM_INTF_INT_LEVEL_LOW) -static const struct { - uint32_t devid; - const char *name; - int flags; -#define TPM_DEV_NOINTS 0x0001 -} tpm_devs[] = { - { 0x000615d1, "IFX SLD 9630 TT 1.1", 0 }, - { 0x000b15d1, "IFX SLB 9635 TT 1.2", 0 }, - { 0x100214e4, "Broadcom BCM0102", TPM_DEV_NOINTS }, - { 0x00fe1050, "WEC WPCT200", 0 }, - { 0x687119fa, "SNS SSX35", 0 }, - { 0x2e4d5453, "STM ST19WP18", 0 }, - { 0x32021114, "ATML 97SC3203", TPM_DEV_NOINTS }, - { 0x10408086, "INTEL INTC0102", 0 }, - { 0, "", TPM_DEV_NOINTS }, -}; - static inline int tpm_tmotohz(int tmo) { @@ -129,7 +113,7 @@ tpm_request_locality(struct tpm_softc *sc, int l) while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) != (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) { - rv = tsleep(sc->sc_init, PRIBIO | PCATCH, "tpm_locality", 1); + rv = tsleep(sc->sc_init, PCATCH, "tpm_locality", 1); if (rv && rv != EWOULDBLOCK) { return rv; } @@ -161,7 +145,7 @@ tpm_getburst(struct tpm_softc *sc) if (burst) return burst; - rv = tsleep(sc, PRIBIO | PCATCH, "tpm_getburst", 1); + rv = tsleep(sc, PCATCH, "tpm_getburst", 1); if (rv && rv != EWOULDBLOCK) { return 0; } @@ -189,9 +173,9 @@ tpm12_suspend(device_t dev, const pmf_qual_t *qual) { struct tpm_softc *sc = device_private(dev); static const uint8_t command[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ + 0, 0xC1, /* TPM_TAG_RQU_COMMAND */ 0, 0, 0, 10, /* Length in bytes */ - 0, 0, 0, 156 /* TPM_ORD_SaveStates */ + 0, 0, 0, 0x98 /* TPM_ORD_SaveState */ }; uint8_t scratch[sizeof(command)]; @@ -209,16 +193,13 @@ tpm12_resume(device_t dev, const pmf_qual_t *qual) /* -------------------------------------------------------------------------- */ -/* - * Wait for given status bits using polling. - */ static int -tpm_waitfor_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan) +tpm_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan) { int rv; while (((sc->sc_status = tpm_status(sc)) & mask) != mask && to--) { - rv = tsleep(chan, PRIBIO | PCATCH, "tpm_poll", 1); + rv = tsleep(chan, PCATCH, "tpm_poll", 1); if (rv && rv != EWOULDBLOCK) { return rv; } @@ -227,138 +208,32 @@ tpm_waitfor_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan) return 0; } -/* - * Wait for given status bits using interrupts. - */ -static int -tpm_waitfor_int(struct tpm_softc *sc, uint8_t mask, int tmo, wchan_t chan, - int inttype) -{ - int rv, to; - - sc->sc_status = tpm_status(sc); - if ((sc->sc_status & mask) == mask) - return 0; - - /* - * Enable interrupt on tpm chip. Note that interrupts on our - * level (SPL_TTY) are disabled (see tpm{read,write} et al) and - * will not be delivered to the cpu until we call tsleep(9) below. - */ - bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE, - bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) | - inttype); - bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE, - bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) | - TPM_GLOBAL_INT_ENABLE); - - sc->sc_status = tpm_status(sc); - if ((sc->sc_status & mask) == mask) { - rv = 0; - goto out; - } - - to = tpm_tmotohz(tmo); - - /* - * tsleep(9) enables interrupts on the cpu and returns after - * wake up with interrupts disabled again. Note that interrupts - * generated by the tpm chip while being at SPL_TTY are not lost - * but held and delivered as soon as the cpu goes below SPL_TTY. - */ - rv = tsleep(chan, PRIBIO | PCATCH, "tpm_wait", to); - - sc->sc_status = tpm_status(sc); - if ((sc->sc_status & mask) == mask) - rv = 0; - -out: - /* Disable interrupts on tpm chip again. */ - bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE, - bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) & - ~TPM_GLOBAL_INT_ENABLE); - bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE, - bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) & - ~inttype); - - return rv; -} - -/* - * Wait on given status bits, use interrupts where possible, otherwise poll. - */ static int tpm_waitfor(struct tpm_softc *sc, uint8_t bits, int tmo, wchan_t chan) { int retry, to, rv; uint8_t todo; - /* - * We use interrupts for TPM_STS_DATA_AVAIL and TPM_STS_VALID (if the - * TPM chip supports them) as waiting for those can take really long. - * The other TPM_STS* are not needed very often so we do not support - * them. - */ - if (sc->sc_vector != -1) { - todo = bits; - - /* - * Wait for data ready. This interrupt only occurs when both - * TPM_STS_VALID and TPM_STS_DATA_AVAIL are asserted. Thus we - * don't have to bother with TPM_STS_VALID separately and can - * just return. - * - * This only holds for interrupts! When using polling both - * flags have to be waited for, see below. - */ - if ((bits & TPM_STS_DATA_AVAIL) && - (sc->sc_capabilities & TPM_INTF_DATA_AVAIL_INT)) - return tpm_waitfor_int(sc, bits, tmo, chan, - TPM_DATA_AVAIL_INT); - - /* Wait for status valid bit. */ - if ((bits & TPM_STS_VALID) && - (sc->sc_capabilities & TPM_INTF_STS_VALID_INT)) { - rv = tpm_waitfor_int(sc, bits, tmo, chan, - TPM_STS_VALID_INT); - if (rv) - return rv; - todo = bits & ~TPM_STS_VALID; - } - - /* - * When all flags have been taken care of, return. Otherwise - * use polling for eg TPM_STS_CMD_READY. - */ - if (todo == 0) - return 0; - } - + to = tpm_tmotohz(tmo); retry = 3; restart: - /* - * If requested, wait for TPM_STS_VALID before dealing with any other - * flag. Eg when both TPM_STS_DATA_AVAIL and TPM_STS_VALID are - * requested, wait for the latter first. - */ todo = bits; - if (bits & TPM_STS_VALID) - todo = TPM_STS_VALID; - to = tpm_tmotohz(tmo); -again: - if ((rv = tpm_waitfor_poll(sc, todo, to, chan)) != 0) - return rv; - if ((todo & sc->sc_status) == TPM_STS_VALID) { - /* Now wait for other flags. */ - todo = bits & ~TPM_STS_VALID; - to++; - goto again; + /* + * TPM_STS_VALID has priority over the others. + */ + if (todo & TPM_STS_VALID) { + if ((rv = tpm_poll(sc, TPM_STS_VALID, to+1, chan)) != 0) + return rv; + todo &= ~TPM_STS_VALID; } + if ((rv = tpm_poll(sc, todo, to, chan)) != 0) + return rv; + if ((todo & sc->sc_status) != todo) { - if (retry-- && (bits & TPM_STS_VALID)) { + if ((retry-- > 0) && (bits & TPM_STS_VALID)) { bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_RESP_RETRY); goto restart; @@ -369,31 +244,6 @@ again: return 0; } -int -tpm_intr(void *v) -{ - struct tpm_softc *sc = v; - uint32_t reg; - - reg = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS); - if (!(reg & (TPM_CMD_READY_INT | TPM_LOCALITY_CHANGE_INT | - TPM_STS_VALID_INT | TPM_DATA_AVAIL_INT))) - return 0; - - if (reg & TPM_STS_VALID_INT) - wakeup(sc); - if (reg & TPM_CMD_READY_INT) - wakeup(sc->sc_write); - if (reg & TPM_DATA_AVAIL_INT) - wakeup(sc->sc_read); - if (reg & TPM_LOCALITY_CHANGE_INT) - wakeup(sc->sc_init); - - bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS, reg); - - return 1; -} - /* -------------------------------------------------------------------------- */ /* @@ -412,8 +262,6 @@ tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh) return 0; if ((cap & TPM_CAPS_REQUIRED) != TPM_CAPS_REQUIRED) return 0; - if (!(cap & (TPM_INTF_INT_EDGE_RISING | TPM_INTF_INT_LEVEL_LOW))) - return 0; /* Request locality 0. */ bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE); @@ -436,70 +284,16 @@ tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh) return 1; } -static int -tpm_tis12_irqinit(struct tpm_softc *sc, int irq, int idx) -{ - uint32_t reg; - - if ((irq == -1) || (tpm_devs[idx].flags & TPM_DEV_NOINTS)) { - sc->sc_vector = -1; - return 0; - } - - /* Ack and disable all interrupts. */ - reg = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE); - bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE, - reg & ~TPM_GLOBAL_INT_ENABLE); - bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS, - bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS)); - - /* Program interrupt vector. */ - bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_INT_VECTOR, irq); - sc->sc_vector = irq; - - /* Program interrupt type. */ - reg &= ~(TPM_INT_EDGE_RISING|TPM_INT_EDGE_FALLING|TPM_INT_LEVEL_HIGH| - TPM_INT_LEVEL_LOW); - reg |= TPM_GLOBAL_INT_ENABLE|TPM_CMD_READY_INT|TPM_LOCALITY_CHANGE_INT| - TPM_STS_VALID_INT|TPM_DATA_AVAIL_INT; - if (sc->sc_capabilities & TPM_INTF_INT_EDGE_RISING) - reg |= TPM_INT_EDGE_RISING; - else if (sc->sc_capabilities & TPM_INTF_INT_EDGE_FALLING) - reg |= TPM_INT_EDGE_FALLING; - else if (sc->sc_capabilities & TPM_INTF_INT_LEVEL_HIGH) - reg |= TPM_INT_LEVEL_HIGH; - else - reg |= TPM_INT_LEVEL_LOW; - - bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE, reg); - - return 0; -} - int -tpm_tis12_init(struct tpm_softc *sc, int irq) +tpm_tis12_init(struct tpm_softc *sc) { - int i; - - sc->sc_capabilities = bus_space_read_4(sc->sc_bt, sc->sc_bh, + sc->sc_caps = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTF_CAPABILITY); sc->sc_devid = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_ID); sc->sc_rev = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_REV); - for (i = 0; tpm_devs[i].devid; i++) { - if (tpm_devs[i].devid == sc->sc_devid) - break; - } - - if (tpm_devs[i].devid) - aprint_normal_dev(sc->sc_dev, "%s rev 0x%x\n", - tpm_devs[i].name, sc->sc_rev); - else - aprint_normal_dev(sc->sc_dev, "device 0x%08x rev 0x%x\n", - sc->sc_devid, sc->sc_rev); - - if (tpm_tis12_irqinit(sc, irq, i)) - return 1; + aprint_normal_dev(sc->sc_dev, "device 0x%08x rev 0x%x\n", + sc->sc_devid, sc->sc_rev); if (tpm_request_locality(sc, 0)) return 1; @@ -511,11 +305,11 @@ tpm_tis12_init(struct tpm_softc *sc, int irq) } int -tpm_tis12_start(struct tpm_softc *sc, int flag) +tpm_tis12_start(struct tpm_softc *sc, int rw) { int rv; - if (flag == UIO_READ) { + if (rw == UIO_READ) { rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID, TPM_READ_TMO, sc->sc_read); return rv; @@ -544,7 +338,7 @@ tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count, { uint8_t *p = buf; size_t cnt; - int rv, n, bcnt; + int rv, n; cnt = 0; while (len > 0) { @@ -553,12 +347,12 @@ tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count, if (rv) return rv; - bcnt = tpm_getburst(sc); - n = MIN(len, bcnt); - - for (; n--; len--) { + n = MIN(len, tpm_getburst(sc)); + while (n > 0) { *p++ = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_DATA); cnt++; + len--; + n--; } if ((flags & TPM_PARAM_SIZE) == 0 && cnt >= 6) @@ -612,19 +406,18 @@ tpm_tis12_write(struct tpm_softc *sc, const void *buf, size_t len) } int -tpm_tis12_end(struct tpm_softc *sc, int flag, int err) +tpm_tis12_end(struct tpm_softc *sc, int rw, int err) { int rv = 0; - if (flag == UIO_READ) { + if (rw == UIO_READ) { rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_read); if (rv) return rv; /* Still more data? */ sc->sc_status = tpm_status(sc); - if (!err && ((sc->sc_status & TPM_STS_DATA_AVAIL) == - TPM_STS_DATA_AVAIL)) { + if (!err && (sc->sc_status & TPM_STS_DATA_AVAIL)) { rv = EIO; } @@ -668,107 +461,111 @@ const struct cdevsw tpm_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, - .d_flag = D_OTHER, + .d_flag = D_OTHER | D_MPSAFE, }; -#define TPMUNIT(a) minor(a) - static int tpmopen(dev_t dev, int flag, int mode, struct lwp *l) { - struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev)); + struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev)); + int ret = 0; if (sc == NULL) return ENXIO; - if (sc->sc_flags & TPM_OPEN) - return EBUSY; - sc->sc_flags |= TPM_OPEN; + mutex_enter(&sc->sc_lock); + if (sc->sc_busy) { + ret = EBUSY; + } else { + sc->sc_busy = true; + } + mutex_exit(&sc->sc_lock); - return 0; + return ret; } static int tpmclose(dev_t dev, int flag, int mode, struct lwp *l) { - struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev)); + struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev)); + int ret = 0; if (sc == NULL) return ENXIO; - if (!(sc->sc_flags & TPM_OPEN)) - return EINVAL; - sc->sc_flags &= ~TPM_OPEN; + mutex_enter(&sc->sc_lock); + if (!sc->sc_busy) { + ret = EINVAL; + } else { + sc->sc_busy = false; + } + mutex_exit(&sc->sc_lock); - return 0; + return ret; } static int tpmread(dev_t dev, struct uio *uio, int flags) { - struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev)); - uint8_t buf[TPM_BUFSIZ], *p; + struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev)); + uint8_t buf[TPM_BUFSIZ]; size_t cnt, len, n; - int rv, s; + int rv; if (sc == NULL) return ENXIO; - s = spltty(); if ((rv = (*sc->sc_start)(sc, UIO_READ))) goto out; + /* Get the header. */ if ((rv = (*sc->sc_read)(sc, buf, TPM_HDRSIZE, &cnt, 0))) { (*sc->sc_end)(sc, UIO_READ, rv); goto out; } - len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5]; - if (len > uio->uio_resid) { + if (len > uio->uio_resid || len < cnt) { rv = EIO; (*sc->sc_end)(sc, UIO_READ, rv); goto out; } - /* Copy out header. */ + /* Copy out the header. */ if ((rv = uiomove(buf, cnt, uio))) { (*sc->sc_end)(sc, UIO_READ, rv); goto out; } - /* Get remaining part of the answer (if anything is left). */ - for (len -= cnt, p = buf, n = sizeof(buf); len > 0; p = buf, len -= n, - n = sizeof(buf)) { - n = MIN(n, len); - if ((rv = (*sc->sc_read)(sc, p, n, NULL, TPM_PARAM_SIZE))) { + /* Process the rest. */ + len -= cnt; + while (len > 0) { + n = MIN(sizeof(buf), len); + if ((rv = (*sc->sc_read)(sc, buf, n, NULL, TPM_PARAM_SIZE))) { (*sc->sc_end)(sc, UIO_READ, rv); goto out; } - p += n; - if ((rv = uiomove(buf, p - buf, uio))) { + if ((rv = uiomove(buf, n, uio))) { (*sc->sc_end)(sc, UIO_READ, rv); goto out; } + len -= n; } rv = (*sc->sc_end)(sc, UIO_READ, rv); out: - splx(s); return rv; } static int tpmwrite(dev_t dev, struct uio *uio, int flags) { - struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev)); + struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev)); uint8_t buf[TPM_BUFSIZ]; - int n, rv, s; + int n, rv; if (sc == NULL) return ENXIO; - s = spltty(); - n = MIN(sizeof(buf), uio->uio_resid); if ((rv = uiomove(buf, n, uio))) { goto out; @@ -782,14 +579,13 @@ tpmwrite(dev_t dev, struct uio *uio, int flags) rv = (*sc->sc_end)(sc, UIO_WRITE, rv); out: - splx(s); return rv; } static int tpmioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) { - struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev)); + struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev)); struct tpm_ioc_getinfo *info; if (sc == NULL) @@ -802,7 +598,7 @@ tpmioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) info->tpm_version = sc->sc_ver; info->device_id = sc->sc_devid; info->device_rev = sc->sc_rev; - info->device_caps = sc->sc_capabilities; + info->device_caps = sc->sc_caps; return 0; default: break; diff --git a/sys/dev/ic/tpmreg.h b/sys/dev/ic/tpmreg.h index e719a5ccd2c8..c553d10b141d 100644 --- a/sys/dev/ic/tpmreg.h +++ b/sys/dev/ic/tpmreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: tpmreg.h,v 1.4 2019/06/22 12:57:41 maxv Exp $ */ +/* $NetBSD: tpmreg.h,v 1.5 2019/10/08 18:43:02 maxv Exp $ */ /* * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -78,6 +78,7 @@ #define TPM_STS_GO __BIT(5) #define TPM_STS_DATA_AVAIL __BIT(4) #define TPM_STS_DATA_EXPECT __BIT(3) +#define TPM_STS_SELFTEST_DONE __BIT(2) #define TPM_STS_RESP_RETRY __BIT(1) #define TPM_DATA 0x0024 /* 32bit register */ diff --git a/sys/dev/ic/tpmvar.h b/sys/dev/ic/tpmvar.h index c81639d605a3..79cf7c0bc8ab 100644 --- a/sys/dev/ic/tpmvar.h +++ b/sys/dev/ic/tpmvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: tpmvar.h,v 1.4 2019/06/22 12:57:41 maxv Exp $ */ +/* $NetBSD: tpmvar.h,v 1.5 2019/10/08 18:43:02 maxv Exp $ */ /* * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -29,24 +29,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/* - * Copyright (c) 2008, 2009 Michael Shalayeff - * Copyright (c) 2009, 2010 Hans-Joerg Hoexer - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - #define TPM_API_VERSION 1 enum tpm_version { @@ -56,7 +38,6 @@ enum tpm_version { struct tpm_ioc_getinfo { uint32_t api_version; - uint32_t tpm_version; uint32_t device_id; uint32_t device_rev; @@ -70,35 +51,29 @@ struct tpm_ioc_getinfo { struct tpm_softc { device_t sc_dev; enum tpm_version sc_ver; - void *sc_ih; + kmutex_t sc_lock; + bool sc_busy; - int (*sc_init)(struct tpm_softc *, int); + int (*sc_init)(struct tpm_softc *); int (*sc_start)(struct tpm_softc *, int); int (*sc_read)(struct tpm_softc *, void *, size_t, size_t *, int); int (*sc_write)(struct tpm_softc *, const void *, size_t); int (*sc_end)(struct tpm_softc *, int, int); - bus_space_tag_t sc_bt, sc_batm; - bus_space_handle_t sc_bh, sc_bahm; + bus_space_tag_t sc_bt; + bus_space_handle_t sc_bh; uint32_t sc_devid; uint32_t sc_rev; uint32_t sc_status; - uint32_t sc_capabilities; - - int sc_flags; -#define TPM_OPEN 0x0001 - - int sc_vector; + uint32_t sc_caps; }; -int tpm_intr(void *); - bool tpm12_suspend(device_t, const pmf_qual_t *); bool tpm12_resume(device_t, const pmf_qual_t *); int tpm_tis12_probe(bus_space_tag_t, bus_space_handle_t); -int tpm_tis12_init(struct tpm_softc *, int); +int tpm_tis12_init(struct tpm_softc *); int tpm_tis12_start(struct tpm_softc *, int); int tpm_tis12_read(struct tpm_softc *, void *, size_t, size_t *, int); int tpm_tis12_write(struct tpm_softc *, const void *, size_t); diff --git a/sys/dev/isa/tpm_isa.c b/sys/dev/isa/tpm_isa.c index 8f0082eb8947..af334433483a 100644 --- a/sys/dev/isa/tpm_isa.c +++ b/sys/dev/isa/tpm_isa.c @@ -1,8 +1,37 @@ -/* $NetBSD: tpm_isa.c,v 1.4 2019/06/22 12:57:41 maxv Exp $ */ +/* $NetBSD: tpm_isa.c,v 1.5 2019/10/08 18:43:03 maxv Exp $ */ + +/* + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Maxime Villard. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ /* * Copyright (c) 2008, 2009 Michael Shalayeff - * Copyright (c) 2009, 2010 Hans-Jörg Höxer + * Copyright (c) 2009, 2010 Hans-Joerg Hoexer * All rights reserved. * * Permission to use, copy, modify, and distribute this software for any @@ -19,13 +48,10 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.4 2019/06/22 12:57:41 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.5 2019/10/08 18:43:03 maxv Exp $"); #include #include -#include -#include -#include #include #include #include @@ -36,13 +62,13 @@ __KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.4 2019/06/22 12:57:41 maxv Exp $"); #include #include +#include "ioconf.h" + static int tpm_isa_match(device_t, cfdata_t, void *); static void tpm_isa_attach(device_t, device_t, void *); -CFATTACH_DECL_NEW(tpm_isa, sizeof(struct tpm_softc), - tpm_isa_match, tpm_isa_attach, NULL, NULL); - -extern struct cfdriver tpm_cd; +CFATTACH_DECL_NEW(tpm_isa, sizeof(struct tpm_softc), tpm_isa_match, + tpm_isa_attach, NULL, NULL); static int tpm_isa_match(device_t parent, cfdata_t match, void *aux) @@ -60,8 +86,8 @@ tpm_isa_match(device_t parent, cfdata_t match, void *aux) return 0; /* XXX: integer locator sign extension */ - if (bus_space_map(bt, (unsigned int)ia->ia_iomem[0].ir_addr, TPM_SPACE_SIZE, - 0, &bh)) + if (bus_space_map(bt, (unsigned int)ia->ia_iomem[0].ir_addr, + TPM_SPACE_SIZE, 0, &bh)) return 0; if ((rv = tpm_tis12_probe(bt, bh))) { @@ -80,46 +106,33 @@ tpm_isa_attach(device_t parent, device_t self, void *aux) { struct tpm_softc *sc = device_private(self); struct isa_attach_args *ia = aux; - bus_addr_t iobase; + bus_addr_t base; bus_size_t size; - int rv; sc->sc_dev = self; sc->sc_ver = TPM_1_2; - - sc->sc_bt = ia->ia_memt; - iobase = (unsigned int)ia->ia_iomem[0].ir_addr; - size = TPM_SPACE_SIZE; + mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); + sc->sc_busy = false; sc->sc_init = tpm_tis12_init; sc->sc_start = tpm_tis12_start; sc->sc_read = tpm_tis12_read; sc->sc_write = tpm_tis12_write; sc->sc_end = tpm_tis12_end; + sc->sc_bt = ia->ia_memt; - if (bus_space_map(sc->sc_bt, iobase, size, 0, &sc->sc_bh)) { + base = (unsigned int)ia->ia_iomem[0].ir_addr; + size = TPM_SPACE_SIZE; + + if (bus_space_map(sc->sc_bt, base, size, 0, &sc->sc_bh)) { aprint_error_dev(sc->sc_dev, "cannot map registers\n"); return; } - if ((rv = (*sc->sc_init)(sc, ia->ia_irq[0].ir_irq)) != 0) { + if ((*sc->sc_init)(sc) != 0) { bus_space_unmap(sc->sc_bt, sc->sc_bh, size); return; } - /* - * Only setup interrupt handler when we have a vector and the - * chip is TIS 1.2 compliant. - */ - if (sc->sc_init == tpm_tis12_init && - ia->ia_irq[0].ir_irq != ISA_UNKNOWN_IRQ && - (sc->sc_ih = isa_intr_establish_xname(ia->ia_ic, - ia->ia_irq[0].ir_irq, IST_EDGE, IPL_TTY, tpm_intr, sc, - device_xname(sc->sc_dev))) == NULL) { - bus_space_unmap(sc->sc_bt, sc->sc_bh, TPM_SPACE_SIZE); - aprint_error_dev(sc->sc_dev, "cannot establish interrupt\n"); - return; - } - if (!pmf_device_register(sc->sc_dev, tpm12_suspend, tpm12_resume)) - aprint_error_dev(sc->sc_dev, "cannot set power mgmt handler\n"); + aprint_error_dev(sc->sc_dev, "couldn't establish power handler\n"); }