Module Name: src
Committed By: martin
Date: Wed Oct 16 09:52:38 UTC 2019
Modified Files:
src/share/man/man4 [netbsd-9]: tpm.4
src/sys/dev/acpi [netbsd-9]: tpm_acpi.c
src/sys/dev/ic [netbsd-9]: tpm.c tpmreg.h tpmvar.h
src/sys/dev/isa [netbsd-9]: tpm_isa.c
Log Message:
Pull up following revision(s) (requested by maxv in ticket #336):
sys/dev/isa/tpm_isa.c: revision 1.6
sys/dev/ic/tpm.c: revision 1.16
sys/dev/isa/tpm_isa.c: revision 1.7
sys/dev/acpi/tpm_acpi.c: revision 1.10
sys/dev/acpi/tpm_acpi.c: revision 1.11
sys/dev/ic/tpmreg.h: revision 1.5
sys/dev/ic/tpmreg.h: revision 1.6
sys/dev/acpi/tpm_acpi.c: revision 1.9
sys/dev/ic/tpmvar.h: revision 1.5
sys/dev/ic/tpmvar.h: revision 1.6
sys/dev/ic/tpmvar.h: revision 1.7
sys/dev/ic/tpm.c: revision 1.14
share/man/man4/tpm.4: revision 1.5
sys/dev/isa/tpm_isa.c: revision 1.5
sys/dev/ic/tpm.c: revision 1.15
Improvements in tpm(4):
- Remove interrupt support, do polling only, avoids unnecessary trouble.
- Simplify a few things.
- Fix the suspend function, the SaveState command is 0x98, not 0x9C.
- Make the driver MP-safe.
- Sync the man page with reality.
-
Add suspend support for TPM 2.0 chips. Check the TPM response also for 1.2
chips. Unfortunately I cannot really test this change since ACPI suspend
does not work on any of my laptops.
-
Provide a better abstraction for the TPM interface. Report it in the ioctl.
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.4.6.1 src/share/man/man4/tpm.4
cvs rdiff -u -r1.8 -r1.8.2.1 src/sys/dev/acpi/tpm_acpi.c
cvs rdiff -u -r1.13 -r1.13.2.1 src/sys/dev/ic/tpm.c
cvs rdiff -u -r1.4 -r1.4.2.1 src/sys/dev/ic/tpmreg.h src/sys/dev/ic/tpmvar.h
cvs rdiff -u -r1.4 -r1.4.2.1 src/sys/dev/isa/tpm_isa.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/share/man/man4/tpm.4
diff -u src/share/man/man4/tpm.4:1.4 src/share/man/man4/tpm.4:1.4.6.1
--- src/share/man/man4/tpm.4:1.4 Thu Feb 22 01:40:49 2018
+++ src/share/man/man4/tpm.4 Wed Oct 16 09:52:38 2019
@@ -1,20 +1,33 @@
-.\" $NetBSD: tpm.4,v 1.4 2018/02/22 01:40:49 pgoyette Exp $
+.\" $NetBSD: tpm.4,v 1.4.6.1 2019/10/16 09:52:38 martin Exp $
.\"
-.\" Copyright (c) 2010 Hans-Jörg Höxer, <[email protected]>
+.\" 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
-.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
+TPM 2.0 chips over ACPI
.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 .
Index: src/sys/dev/acpi/tpm_acpi.c
diff -u src/sys/dev/acpi/tpm_acpi.c:1.8 src/sys/dev/acpi/tpm_acpi.c:1.8.2.1
--- src/sys/dev/acpi/tpm_acpi.c:1.8 Sat Jun 22 12:57:40 2019
+++ src/sys/dev/acpi/tpm_acpi.c Wed Oct 16 09:52:38 2019
@@ -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.8.2.1 2019/10/16 09:52:38 martin Exp $ */
/*
* Copyright (c) 2012, 2019 The NetBSD Foundation, Inc.
@@ -30,10 +30,9 @@
*/
#include <sys/cdefs.h>
-__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.8.2.1 2019/10/16 09:52:38 martin Exp $");
#include <sys/param.h>
-#include <sys/device.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/bus.h>
@@ -45,8 +44,6 @@ __KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v
#include <dev/acpi/acpireg.h>
#include <dev/acpi/acpivar.h>
-#include <dev/isa/isavar.h>
-
#include "ioconf.h"
#define _COMPONENT ACPI_RESOURCE_COMPONENT
@@ -100,70 +97,52 @@ tpm_acpi_attach(device_t parent, device_
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_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_dev = self;
+ sc->sc_ver = TPM_2_0;
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+ sc->sc_busy = false;
+ sc->sc_intf = &tpm_intf_tis12;
+ sc->sc_bt = aa->aa_memt;
if (bus_space_map(sc->sc_bt, base, size, 0, &sc->sc_bh)) {
aprint_error_dev(sc->sc_dev, "cannot map registers\n");
goto out;
}
- if (!tpm_tis12_probe(sc->sc_bt, sc->sc_bh)) {
- aprint_error_dev(sc->sc_dev, "TIS1.2 probe failed\n");
+ if ((rv = (*sc->sc_intf->probe)(sc->sc_bt, sc->sc_bh)) != 0) {
+ aprint_error_dev(sc->sc_dev, "probe failed, rv=%d\n", rv);
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) {
- 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");
+ if ((rv = (*sc->sc_intf->init)(sc)) != 0) {
+ aprint_error_dev(sc->sc_dev, "cannot init device, rv=%d\n", rv);
goto out1;
}
+ if (!pmf_device_register(self, tpm_suspend, tpm_resume))
+ aprint_error_dev(self, "couldn't establish power handler\n");
acpi_resource_cleanup(&res);
return;
Index: src/sys/dev/ic/tpm.c
diff -u src/sys/dev/ic/tpm.c:1.13 src/sys/dev/ic/tpm.c:1.13.2.1
--- src/sys/dev/ic/tpm.c:1.13 Sat Jun 22 12:57:41 2019
+++ src/sys/dev/ic/tpm.c Wed Oct 16 09:52:38 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $ */
+/* $NetBSD: tpm.c,v 1.13.2.1 2019/10/16 09:52:38 martin Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__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.13.2.1 2019/10/16 09:52:38 martin Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -65,8 +65,10 @@ __KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13
#include "ioconf.h"
+CTASSERT(sizeof(struct tpm_header) == 10);
+
#define TPM_BUFSIZ 1024
-#define TPM_HDRSIZE 10
+
#define TPM_PARAM_SIZE 0x0001 /* that's a flag */
/* Timeouts. */
@@ -79,23 +81,6 @@ __KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13
(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)
{
@@ -108,42 +93,6 @@ tpm_tmotohz(int tmo)
}
static int
-tpm_request_locality(struct tpm_softc *sc, int l)
-{
- uint32_t r;
- int to, rv;
-
- if (l != 0)
- return EINVAL;
-
- if ((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))
- return 0;
-
- bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
- TPM_ACCESS_REQUEST_USE);
-
- to = tpm_tmotohz(TPM_ACCESS_TMO);
-
- 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);
- if (rv && rv != EWOULDBLOCK) {
- return rv;
- }
- }
-
- if ((r & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
- (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
- return EBUSY;
- }
-
- return 0;
-}
-
-static int
tpm_getburst(struct tpm_softc *sc)
{
int burst, to, rv;
@@ -161,7 +110,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;
}
@@ -179,46 +128,81 @@ tpm_status(struct tpm_softc *sc)
/* -------------------------------------------------------------------------- */
-/*
- * Save TPM state on suspend. On resume we don't do anything, since the BIOS
- * is supposed to restore the previously saved state.
- */
+static bool
+tpm12_suspend(struct tpm_softc *sc)
+{
+ static const uint8_t command[10] = {
+ 0x00, 0xC1, /* TPM_TAG_RQU_COMMAND */
+ 0x00, 0x00, 0x00, 10, /* Length in bytes */
+ 0x00, 0x00, 0x00, 0x98 /* TPM_ORD_SaveState */
+ };
+ struct tpm_header response;
-bool
-tpm12_suspend(device_t dev, const pmf_qual_t *qual)
+ if ((*sc->sc_intf->write)(sc, &command, sizeof(command)) != 0)
+ return false;
+ if ((*sc->sc_intf->read)(sc, &response, sizeof(response), NULL, 0) != 0)
+ return false;
+ if (TPM_BE32(response.code) != 0)
+ return false;
+
+ return true;
+}
+
+static bool
+tpm20_suspend(struct tpm_softc *sc)
{
- struct tpm_softc *sc = device_private(dev);
- static const uint8_t command[] = {
- 0, 193, /* TPM_TAG_RQU_COMMAND */
- 0, 0, 0, 10, /* Length in bytes */
- 0, 0, 0, 156 /* TPM_ORD_SaveStates */
+ static const uint8_t command[12] = {
+ 0x80, 0x01, /* TPM_ST_NO_SESSIONS */
+ 0x00, 0x00, 0x00, 12, /* Length in bytes */
+ 0x00, 0x00, 0x01, 0x45, /* TPM_CC_Shutdown */
+ 0x00, 0x01 /* TPM_SU_STATE */
};
- uint8_t scratch[sizeof(command)];
+ struct tpm_header response;
- (*sc->sc_write)(sc, &command, sizeof(command));
- (*sc->sc_read)(sc, &scratch, sizeof(scratch), NULL, 0);
+ if ((*sc->sc_intf->write)(sc, &command, sizeof(command)) != 0)
+ return false;
+ if ((*sc->sc_intf->read)(sc, &response, sizeof(response), NULL, 0) != 0)
+ return false;
+ if (TPM_BE32(response.code) != 0)
+ return false;
return true;
}
bool
-tpm12_resume(device_t dev, const pmf_qual_t *qual)
+tpm_suspend(device_t dev, const pmf_qual_t *qual)
{
+ struct tpm_softc *sc = device_private(dev);
+
+ switch (sc->sc_ver) {
+ case TPM_1_2:
+ return tpm12_suspend(sc);
+ case TPM_2_0:
+ return tpm20_suspend(sc);
+ default:
+ panic("%s: impossible", __func__);
+ }
+}
+
+bool
+tpm_resume(device_t dev, const pmf_qual_t *qual)
+{
+ /*
+ * Don't do anything, the BIOS is supposed to restore the previously
+ * saved state.
+ */
return true;
}
/* -------------------------------------------------------------------------- */
-/*
- * 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 +211,32 @@ tpm_waitfor_poll(struct tpm_softc *sc, u
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,38 +247,49 @@ again:
return 0;
}
-int
-tpm_intr(void *v)
+/* -------------------------------------------------------------------------- */
+
+/*
+ * TPM using the TIS 1.2 interface.
+ */
+
+static int
+tpm12_request_locality(struct tpm_softc *sc, int l)
{
- struct tpm_softc *sc = v;
- uint32_t reg;
+ uint32_t r;
+ int to, rv;
+
+ if (l != 0)
+ return EINVAL;
- 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)))
+ if ((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))
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_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
+ TPM_ACCESS_REQUEST_USE);
- bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS, reg);
+ to = tpm_tmotohz(TPM_ACCESS_TMO);
- return 1;
-}
+ 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_intf->init, PCATCH, "tpm_locality", 1);
+ if (rv && rv != EWOULDBLOCK) {
+ return rv;
+ }
+ }
-/* -------------------------------------------------------------------------- */
+ if ((r & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
+ (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
+ return EBUSY;
+ }
-/*
- * TPM using TIS 1.2 interface.
- */
+ return 0;
+}
-int
+static int
tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh)
{
uint32_t cap;
@@ -409,11 +298,9 @@ tpm_tis12_probe(bus_space_tag_t bt, bus_
cap = bus_space_read_4(bt, bh, TPM_INTF_CAPABILITY);
if (cap == 0xffffffff)
- return 0;
+ return EINVAL;
if ((cap & TPM_CAPS_REQUIRED) != TPM_CAPS_REQUIRED)
- return 0;
- if (!(cap & (TPM_INTF_INT_EDGE_RISING | TPM_INTF_INT_LEVEL_LOW)))
- return 0;
+ return ENOTSUP;
/* Request locality 0. */
bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE);
@@ -427,82 +314,30 @@ tpm_tis12_probe(bus_space_tag_t bt, bus_
}
if ((reg & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
(TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
- return 0;
+ return ETIMEDOUT;
}
if (bus_space_read_4(bt, bh, TPM_ID) == 0xffffffff)
- return 0;
-
- 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 EINVAL;
return 0;
}
-int
-tpm_tis12_init(struct tpm_softc *sc, int irq)
+static int
+tpm_tis12_init(struct tpm_softc *sc)
{
- int i;
+ int rv;
- 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;
+ if ((rv = tpm12_request_locality(sc, 0)) != 0)
+ return rv;
/* Abort whatever it thought it was doing. */
bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
@@ -510,19 +345,19 @@ tpm_tis12_init(struct tpm_softc *sc, int
return 0;
}
-int
-tpm_tis12_start(struct tpm_softc *sc, int flag)
+static int
+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);
+ TPM_READ_TMO, sc->sc_intf->read);
return rv;
}
/* Request the 0th locality. */
- if ((rv = tpm_request_locality(sc, 0)) != 0)
+ if ((rv = tpm12_request_locality(sc, 0)) != 0)
return rv;
sc->sc_status = tpm_status(sc);
@@ -531,34 +366,34 @@ tpm_tis12_start(struct tpm_softc *sc, in
/* Abort previous and restart. */
bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
- rv = tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO, sc->sc_write);
+ rv = tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO, sc->sc_intf->write);
if (rv)
return rv;
return 0;
}
-int
+static int
tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count,
int flags)
{
uint8_t *p = buf;
size_t cnt;
- int rv, n, bcnt;
+ int rv, n;
cnt = 0;
while (len > 0) {
rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- TPM_READ_TMO, sc->sc_read);
+ TPM_READ_TMO, sc->sc_intf->read);
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)
@@ -571,7 +406,7 @@ tpm_tis12_read(struct tpm_softc *sc, voi
return 0;
}
-int
+static int
tpm_tis12_write(struct tpm_softc *sc, const void *buf, size_t len)
{
const uint8_t *p = buf;
@@ -580,7 +415,7 @@ tpm_tis12_write(struct tpm_softc *sc, co
if (len == 0)
return 0;
- if ((rv = tpm_request_locality(sc, 0)) != 0)
+ if ((rv = tpm12_request_locality(sc, 0)) != 0)
return rv;
cnt = 0;
@@ -611,20 +446,19 @@ tpm_tis12_write(struct tpm_softc *sc, co
return 0;
}
-int
-tpm_tis12_end(struct tpm_softc *sc, int flag, int err)
+static int
+tpm_tis12_end(struct tpm_softc *sc, int rw, int err)
{
int rv = 0;
- if (flag == UIO_READ) {
- rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_read);
+ if (rw == UIO_READ) {
+ rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_intf->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;
}
@@ -648,6 +482,16 @@ tpm_tis12_end(struct tpm_softc *sc, int
return rv;
}
+const struct tpm_intf tpm_intf_tis12 = {
+ .version = TIS_1_2,
+ .probe = tpm_tis12_probe,
+ .init = tpm_tis12_init,
+ .start = tpm_tis12_start,
+ .read = tpm_tis12_read,
+ .write = tpm_tis12_write,
+ .end = tpm_tis12_end
+};
+
/* -------------------------------------------------------------------------- */
static dev_type_open(tpmopen);
@@ -668,128 +512,127 @@ 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));
+ struct tpm_header hdr;
+ 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;
+ if ((rv = (*sc->sc_intf->start)(sc, UIO_READ)))
+ return rv;
- if ((rv = (*sc->sc_read)(sc, buf, TPM_HDRSIZE, &cnt, 0))) {
- (*sc->sc_end)(sc, UIO_READ, rv);
+ /* Get the header. */
+ if ((rv = (*sc->sc_intf->read)(sc, &hdr, sizeof(hdr), &cnt, 0))) {
goto out;
}
-
- len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5];
- if (len > uio->uio_resid) {
+ len = TPM_BE32(hdr.length);
+ if (len > uio->uio_resid || len < cnt) {
rv = EIO;
- (*sc->sc_end)(sc, UIO_READ, rv);
goto out;
}
- /* Copy out header. */
- if ((rv = uiomove(buf, cnt, uio))) {
- (*sc->sc_end)(sc, UIO_READ, rv);
+ /* Copy out the header. */
+ if ((rv = uiomove(&hdr, cnt, uio))) {
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))) {
- (*sc->sc_end)(sc, UIO_READ, rv);
+ /* Process the rest. */
+ len -= cnt;
+ while (len > 0) {
+ n = MIN(sizeof(buf), len);
+ if ((rv = (*sc->sc_intf->read)(sc, buf, n, NULL, TPM_PARAM_SIZE))) {
goto out;
}
- p += n;
- if ((rv = uiomove(buf, p - buf, uio))) {
- (*sc->sc_end)(sc, UIO_READ, rv);
+ if ((rv = uiomove(buf, n, uio))) {
goto out;
}
+ len -= n;
}
- rv = (*sc->sc_end)(sc, UIO_READ, rv);
out:
- splx(s);
+ rv = (*sc->sc_intf->end)(sc, UIO_READ, rv);
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;
}
- if ((rv = (*sc->sc_start)(sc, UIO_WRITE))) {
+ if ((rv = (*sc->sc_intf->start)(sc, UIO_WRITE))) {
goto out;
}
- if ((rv = (*sc->sc_write)(sc, buf, n))) {
+ if ((rv = (*sc->sc_intf->write)(sc, buf, n))) {
goto out;
}
- rv = (*sc->sc_end)(sc, UIO_WRITE, rv);
+ rv = (*sc->sc_intf->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)
@@ -800,9 +643,10 @@ tpmioctl(dev_t dev, u_long cmd, void *ad
info = addr;
info->api_version = TPM_API_VERSION;
info->tpm_version = sc->sc_ver;
+ info->itf_version = sc->sc_intf->version;
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;
Index: src/sys/dev/ic/tpmreg.h
diff -u src/sys/dev/ic/tpmreg.h:1.4 src/sys/dev/ic/tpmreg.h:1.4.2.1
--- src/sys/dev/ic/tpmreg.h:1.4 Sat Jun 22 12:57:41 2019
+++ src/sys/dev/ic/tpmreg.h Wed Oct 16 09:52:38 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: tpmreg.h,v 1.4 2019/06/22 12:57:41 maxv Exp $ */
+/* $NetBSD: tpmreg.h,v 1.4.2.1 2019/10/16 09:52:38 martin Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -29,6 +29,22 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#define TPM_BE16(a) bswap16(a)
+#define TPM_BE32(a) bswap32(a)
+#else
+#define TPM_BE16(a) (a)
+#define TPM_BE32(a) (a)
+#endif
+
+struct tpm_header {
+ uint16_t tag;
+ uint32_t length;
+ uint32_t code;
+} __packed;
+
+/* -------------------------------------------------------------------------- */
+
/*
* TPM Interface Specification 1.2 (TIS12).
*/
@@ -78,6 +94,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 */
Index: src/sys/dev/ic/tpmvar.h
diff -u src/sys/dev/ic/tpmvar.h:1.4 src/sys/dev/ic/tpmvar.h:1.4.2.1
--- src/sys/dev/ic/tpmvar.h:1.4 Sat Jun 22 12:57:41 2019
+++ src/sys/dev/ic/tpmvar.h Wed Oct 16 09:52:38 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: tpmvar.h,v 1.4 2019/06/22 12:57:41 maxv Exp $ */
+/* $NetBSD: tpmvar.h,v 1.4.2.1 2019/10/16 09:52:38 martin 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 {
@@ -54,10 +36,15 @@ enum tpm_version {
TPM_2_0
};
+enum itf_version {
+ TIS_1_2,
+ CRB
+};
+
struct tpm_ioc_getinfo {
uint32_t api_version;
-
uint32_t tpm_version;
+ uint32_t itf_version;
uint32_t device_id;
uint32_t device_rev;
uint32_t device_caps;
@@ -67,41 +54,37 @@ struct tpm_ioc_getinfo {
#ifdef _KERNEL
+struct tpm_softc;
+
+struct tpm_intf {
+ enum itf_version version;
+ int (*probe)(bus_space_tag_t, bus_space_handle_t);
+ int (*init)(struct tpm_softc *);
+ int (*start)(struct tpm_softc *, int);
+ int (*read)(struct tpm_softc *, void *, size_t, size_t *, int);
+ int (*write)(struct tpm_softc *, const void *, size_t);
+ int (*end)(struct tpm_softc *, int, int);
+};
+
+extern const struct tpm_intf tpm_intf_tis12;
+
struct tpm_softc {
device_t sc_dev;
enum tpm_version sc_ver;
- void *sc_ih;
-
- int (*sc_init)(struct tpm_softc *, int);
- 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);
+ kmutex_t sc_lock;
+ bool sc_busy;
- bus_space_tag_t sc_bt, sc_batm;
- bus_space_handle_t sc_bh, sc_bahm;
+ const struct tpm_intf *sc_intf;
+ 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_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);
-int tpm_tis12_end(struct tpm_softc *, int, int);
+bool tpm_suspend(device_t, const pmf_qual_t *);
+bool tpm_resume(device_t, const pmf_qual_t *);
#endif
Index: src/sys/dev/isa/tpm_isa.c
diff -u src/sys/dev/isa/tpm_isa.c:1.4 src/sys/dev/isa/tpm_isa.c:1.4.2.1
--- src/sys/dev/isa/tpm_isa.c:1.4 Sat Jun 22 12:57:41 2019
+++ src/sys/dev/isa/tpm_isa.c Wed Oct 16 09:52:38 2019
@@ -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.4.2.1 2019/10/16 09:52:38 martin 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 <sys/cdefs.h>
-__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.4.2.1 2019/10/16 09:52:38 martin Exp $");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/proc.h>
#include <sys/device.h>
#include <sys/bus.h>
#include <sys/pmf.h>
@@ -36,13 +62,13 @@ __KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
+#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,11 +86,11 @@ tpm_isa_match(device_t parent, cfdata_t
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))) {
+ if ((rv = (*tpm_intf_tis12.probe)(bt, bh)) == 0) {
ia->ia_nio = 0;
ia->ia_io[0].ir_size = 0;
ia->ia_iomem[0].ir_size = TPM_SPACE_SIZE;
@@ -72,7 +98,7 @@ tpm_isa_match(device_t parent, cfdata_t
ia->ia_ndrq = 0;
bus_space_unmap(bt, bh, TPM_SPACE_SIZE);
- return rv;
+ return (rv == 0) ? 1 : 0;
}
static void
@@ -80,46 +106,30 @@ tpm_isa_attach(device_t parent, device_t
{
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;
+ base = (unsigned int)ia->ia_iomem[0].ir_addr;
+ size = TPM_SPACE_SIZE;
+
sc->sc_dev = self;
sc->sc_ver = TPM_1_2;
-
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+ sc->sc_busy = false;
+ sc->sc_intf = &tpm_intf_tis12;
sc->sc_bt = ia->ia_memt;
- iobase = (unsigned int)ia->ia_iomem[0].ir_addr;
- size = TPM_SPACE_SIZE;
- 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;
-
- if (bus_space_map(sc->sc_bt, iobase, size, 0, &sc->sc_bh)) {
+ 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 ((rv = (*sc->sc_intf->init)(sc)) != 0) {
+ aprint_error_dev(sc->sc_dev, "cannot init device, rv=%d\n", rv);
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");
+ if (!pmf_device_register(self, tpm_suspend, tpm_resume))
+ aprint_error_dev(self, "couldn't establish power handler\n");
}