Wed Oct 9 14:03:58 2019 UTC ()
Provide a better abstraction for the TPM interface. Report it in the ioctl.


(maxv)
diff -r1.10 -r1.11 src/sys/dev/acpi/tpm_acpi.c
diff -r1.15 -r1.16 src/sys/dev/ic/tpm.c
diff -r1.6 -r1.7 src/sys/dev/ic/tpmvar.h
diff -r1.6 -r1.7 src/sys/dev/isa/tpm_isa.c

cvs diff -r1.10 -r1.11 src/sys/dev/acpi/tpm_acpi.c (expand / switch to context diff)
--- src/sys/dev/acpi/tpm_acpi.c 2019/10/09 07:30:58 1.10
+++ src/sys/dev/acpi/tpm_acpi.c 2019/10/09 14:03:57 1.11
@@ -1,4 +1,4 @@
-/* $NetBSD: tpm_acpi.c,v 1.10 2019/10/09 07:30:58 maxv Exp $ */
+/* $NetBSD: tpm_acpi.c,v 1.11 2019/10/09 14:03:57 maxv Exp $ */
 
 /*
  * Copyright (c) 2012, 2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.10 2019/10/09 07:30:58 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.11 2019/10/09 14:03:57 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -118,33 +118,26 @@
 		    (uint64_t)mem->ar_length, TPM_SPACE_SIZE);
 		goto out;
 	}
+	base = mem->ar_base;
+	size = mem->ar_length;
 
 	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_intf = &tpm_intf_tis12;
 	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");
 		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;
 	}
-
-	if ((*sc->sc_init)(sc) != 0) {
-		aprint_error_dev(sc->sc_dev, "cannot init device %d\n", rv);
+	if ((rv = (*sc->sc_intf->init)(sc)) != 0) {
+		aprint_error_dev(sc->sc_dev, "cannot init device, rv=%d\n", rv);
 		goto out1;
 	}
 

cvs diff -r1.15 -r1.16 src/sys/dev/ic/tpm.c (expand / switch to context diff)
--- src/sys/dev/ic/tpm.c 2019/10/09 07:30:58 1.15
+++ src/sys/dev/ic/tpm.c 2019/10/09 14:03:58 1.16
@@ -1,4 +1,4 @@
-/*	$NetBSD: tpm.c,v 1.15 2019/10/09 07:30:58 maxv Exp $	*/
+/*	$NetBSD: tpm.c,v 1.16 2019/10/09 14:03:58 maxv Exp $	*/
 
 /*
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.15 2019/10/09 07:30:58 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.16 2019/10/09 14:03:58 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -93,42 +93,6 @@
 }
 
 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, 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;
@@ -174,9 +138,9 @@
 	};
 	struct tpm_header response;
 
-	if ((*sc->sc_write)(sc, &command, sizeof(command)) != 0)
+	if ((*sc->sc_intf->write)(sc, &command, sizeof(command)) != 0)
 		return false;
-	if ((*sc->sc_read)(sc, &response, sizeof(response), NULL, 0) != 0)
+	if ((*sc->sc_intf->read)(sc, &response, sizeof(response), NULL, 0) != 0)
 		return false;
 	if (TPM_BE32(response.code) != 0)
 		return false;
@@ -195,9 +159,9 @@
 	};
 	struct tpm_header response;
 
-	if ((*sc->sc_write)(sc, &command, sizeof(command)) != 0)
+	if ((*sc->sc_intf->write)(sc, &command, sizeof(command)) != 0)
 		return false;
-	if ((*sc->sc_read)(sc, &response, sizeof(response), NULL, 0) != 0)
+	if ((*sc->sc_intf->read)(sc, &response, sizeof(response), NULL, 0) != 0)
 		return false;
 	if (TPM_BE32(response.code) != 0)
 		return false;
@@ -286,10 +250,46 @@
 /* -------------------------------------------------------------------------- */
 
 /*
- * TPM using TIS 1.2 interface.
+ * TPM using the TIS 1.2 interface.
  */
 
-int
+static int
+tpm12_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_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;
+	}
+
+	return 0;
+}
+
+static int
 tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh)
 {
 	uint32_t cap;
@@ -298,9 +298,9 @@
 
 	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;
+		return ENOTSUP;
 
 	/* Request locality 0. */
 	bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE);
@@ -314,18 +314,20 @@
 	}
 	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 EINVAL;
 
-	return 1;
+	return 0;
 }
 
-int
+static int
 tpm_tis12_init(struct tpm_softc *sc)
 {
+	int rv;
+
 	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);
@@ -334,8 +336,8 @@
 	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);
@@ -343,19 +345,19 @@
 	return 0;
 }
 
-int
+static int
 tpm_tis12_start(struct tpm_softc *sc, int rw)
 {
 	int rv;
 
 	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);
@@ -364,14 +366,14 @@
 
 	/* 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)
 {
@@ -382,7 +384,7 @@
 	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;
 
@@ -404,7 +406,7 @@
 	return 0;
 }
 
-int
+static int
 tpm_tis12_write(struct tpm_softc *sc, const void *buf, size_t len)
 {
 	const uint8_t *p = buf;
@@ -413,7 +415,7 @@
 
 	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;
@@ -444,13 +446,13 @@
 	return 0;
 }
 
-int
+static int
 tpm_tis12_end(struct tpm_softc *sc, int rw, int err)
 {
 	int rv = 0;
 
 	if (rw == UIO_READ) {
-		rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_read);
+		rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_intf->read);
 		if (rv)
 			return rv;
 
@@ -480,6 +482,16 @@
 	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);
@@ -555,24 +567,21 @@
 	if (sc == NULL)
 		return ENXIO;
 
-	if ((rv = (*sc->sc_start)(sc, UIO_READ)))
-		goto out;
+	if ((rv = (*sc->sc_intf->start)(sc, UIO_READ)))
+		return rv;
 
 	/* Get the header. */
-	if ((rv = (*sc->sc_read)(sc, &hdr, sizeof(hdr), &cnt, 0))) {
-		(*sc->sc_end)(sc, UIO_READ, rv);
+	if ((rv = (*sc->sc_intf->read)(sc, &hdr, sizeof(hdr), &cnt, 0))) {
 		goto out;
 	}
 	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 the header. */
 	if ((rv = uiomove(&hdr, cnt, uio))) {
-		(*sc->sc_end)(sc, UIO_READ, rv);
 		goto out;
 	}
 
@@ -580,19 +589,17 @@
 	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);
+		if ((rv = (*sc->sc_intf->read)(sc, buf, n, NULL, TPM_PARAM_SIZE))) {
 			goto out;
 		}
 		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:
+	rv = (*sc->sc_intf->end)(sc, UIO_READ, rv);
 	return rv;
 }
 
@@ -610,14 +617,14 @@
 	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:
 	return rv;
 }
@@ -636,6 +643,7 @@
 		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_caps;

cvs diff -r1.6 -r1.7 src/sys/dev/ic/tpmvar.h (expand / switch to context diff)
--- src/sys/dev/ic/tpmvar.h 2019/10/09 07:30:58 1.6
+++ src/sys/dev/ic/tpmvar.h 2019/10/09 14:03:58 1.7
@@ -1,4 +1,4 @@
-/*	$NetBSD: tpmvar.h,v 1.6 2019/10/09 07:30:58 maxv Exp $	*/
+/*	$NetBSD: tpmvar.h,v 1.7 2019/10/09 14:03:58 maxv Exp $	*/
 
 /*
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -36,9 +36,15 @@
 	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;
@@ -48,18 +54,27 @@
 
 #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;
 	kmutex_t sc_lock;
 	bool sc_busy;
 
-	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);
-
+	const struct tpm_intf *sc_intf;
 	bus_space_tag_t sc_bt;
 	bus_space_handle_t sc_bh;
 
@@ -71,12 +86,5 @@
 
 bool tpm_suspend(device_t, const pmf_qual_t *);
 bool tpm_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 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);
 
 #endif

cvs diff -r1.6 -r1.7 src/sys/dev/isa/tpm_isa.c (expand / switch to context diff)
--- src/sys/dev/isa/tpm_isa.c 2019/10/09 07:30:58 1.6
+++ src/sys/dev/isa/tpm_isa.c 2019/10/09 14:03:58 1.7
@@ -1,4 +1,4 @@
-/*	$NetBSD: tpm_isa.c,v 1.6 2019/10/09 07:30:58 maxv Exp $	*/
+/*	$NetBSD: tpm_isa.c,v 1.7 2019/10/09 14:03:58 maxv Exp $	*/
 
 /*
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.6 2019/10/09 07:30:58 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.7 2019/10/09 14:03:58 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -90,7 +90,7 @@
 	    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;
@@ -98,7 +98,7 @@
 	ia->ia_ndrq = 0;
 
 	bus_space_unmap(bt, bh, TPM_SPACE_SIZE);
-	return rv;
+	return (rv == 0) ? 1 : 0;
 }
 
 static void
@@ -108,27 +108,24 @@
 	struct isa_attach_args *ia = aux;
 	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_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_intf = &tpm_intf_tis12;
 	sc->sc_bt = ia->ia_memt;
-
-	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 ((*sc->sc_init)(sc) != 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;
 	}