Module Name: src Committed By: maxv Date: Wed Oct 9 14:03:58 UTC 2019
Modified Files: src/sys/dev/acpi: tpm_acpi.c src/sys/dev/ic: tpm.c tpmvar.h src/sys/dev/isa: tpm_isa.c Log Message: Provide a better abstraction for the TPM interface. Report it in the ioctl. To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.11 src/sys/dev/acpi/tpm_acpi.c cvs rdiff -u -r1.15 -r1.16 src/sys/dev/ic/tpm.c cvs rdiff -u -r1.6 -r1.7 src/sys/dev/ic/tpmvar.h cvs rdiff -u -r1.6 -r1.7 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/sys/dev/acpi/tpm_acpi.c diff -u src/sys/dev/acpi/tpm_acpi.c:1.10 src/sys/dev/acpi/tpm_acpi.c:1.11 --- src/sys/dev/acpi/tpm_acpi.c:1.10 Wed Oct 9 07:30:58 2019 +++ src/sys/dev/acpi/tpm_acpi.c Wed Oct 9 14:03:57 2019 @@ -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 @@ tpm_acpi_attach(device_t parent, device_ (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; } Index: src/sys/dev/ic/tpm.c diff -u src/sys/dev/ic/tpm.c:1.15 src/sys/dev/ic/tpm.c:1.16 --- src/sys/dev/ic/tpm.c:1.15 Wed Oct 9 07:30:58 2019 +++ src/sys/dev/ic/tpm.c Wed Oct 9 14:03:58 2019 @@ -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 @@ 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, 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 @@ tpm12_suspend(struct tpm_softc *sc) }; 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 @@ tpm20_suspend(struct tpm_softc *sc) }; 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 @@ restart: /* -------------------------------------------------------------------------- */ /* - * 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 @@ 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; + return ENOTSUP; /* Request locality 0. */ bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE); @@ -314,18 +314,20 @@ 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 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 @@ tpm_tis12_init(struct tpm_softc *sc) 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 @@ tpm_tis12_init(struct tpm_softc *sc) 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 @@ 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) { @@ -382,7 +384,7 @@ tpm_tis12_read(struct tpm_softc *sc, voi 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 @@ 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; @@ -413,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; @@ -444,13 +446,13 @@ tpm_tis12_write(struct tpm_softc *sc, co 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 @@ 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); @@ -555,24 +567,21 @@ tpmread(dev_t dev, struct uio *uio, int 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 @@ tpmread(dev_t dev, struct uio *uio, int 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 @@ tpmwrite(dev_t dev, struct uio *uio, int 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 @@ 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_caps; Index: src/sys/dev/ic/tpmvar.h diff -u src/sys/dev/ic/tpmvar.h:1.6 src/sys/dev/ic/tpmvar.h:1.7 --- src/sys/dev/ic/tpmvar.h:1.6 Wed Oct 9 07:30:58 2019 +++ src/sys/dev/ic/tpmvar.h Wed Oct 9 14:03:58 2019 @@ -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 @@ 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; @@ -48,18 +54,27 @@ 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; 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; @@ -72,11 +87,4 @@ struct tpm_softc { 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 Index: src/sys/dev/isa/tpm_isa.c diff -u src/sys/dev/isa/tpm_isa.c:1.6 src/sys/dev/isa/tpm_isa.c:1.7 --- src/sys/dev/isa/tpm_isa.c:1.6 Wed Oct 9 07:30:58 2019 +++ src/sys/dev/isa/tpm_isa.c Wed Oct 9 14:03:58 2019 @@ -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_isa_match(device_t parent, cfdata_t 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 @@ 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 @@ -108,27 +108,24 @@ tpm_isa_attach(device_t parent, device_t 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; }