Re: git: c2e9c5bbf022 - main - tpm: Refactor TIS and add a SPI attachment
Date: Mon, 24 Jun 2024 20:11:28 UTC
On Mon, 24 Jun 2024 12:41:57 -0700 Gleb Smirnoff <glebius@freebsd.org> wrote: > Hi Justin, > > sorry for late notice, but we just discovered that after this commit > tpm(4) on ACPI no longer attaches. From what I see ther probe method > isn't even called. Hi Gleb, That's very odd. The probe method hasn't changed, nor has the tpm_acpi attachment (still acpi), so I'm really confused why it wouldn't be called now. Is there any debugging you can do to further narrow it down? I haven't seen any issues reported internally at Juniper on x86 hardware. I just verified everything should get built properly. - Justin > > On Fri, May 03, 2024 at 08:32:43PM +0000, Justin Hibbits wrote: > J> The branch main has been updated by jhibbits: > J> > J> URL: > J> https://cgit.FreeBSD.org/src/commit/?id=c2e9c5bbf02294376988f3e7eba82b8e078cdf30 > J> > J> commit c2e9c5bbf02294376988f3e7eba82b8e078cdf30 > J> Author: Justin Hibbits <jhibbits@FreeBSD.org> > J> AuthorDate: 2023-11-13 16:33:44 +0000 > J> Commit: Justin Hibbits <jhibbits@FreeBSD.org> > J> CommitDate: 2024-05-03 20:26:11 +0000 > J> > J> tpm: Refactor TIS and add a SPI attachment > J> > J> Summary: > J> Though mostly used in x86 devices, TPM can be used on others, > J> with a direct SPI attachment. Refactor the TPM 2.0 driver set to > J> use an attachment interface, and implement a SPI bus interface. > J> > J> Test Plan: > J> Tested on a Raspberry Pi 4, with a GeeekPi TPM2.0 module > J> (SLB9670 TPM) using security/tpm2-tools tpm2_getcaps for very > J> light testing against the spibus attachment. > J> > J> Reviewed by: kd > J> Obtained from: Juniper Networks, Inc. > J> Differential Revision: https://reviews.freebsd.org/D45069 > J> --- > J> sys/conf/files | 7 ++ > J> sys/conf/files.amd64 | 2 - > J> sys/dev/tpm/tpm20.c | 6 +- > J> sys/dev/tpm/tpm20.h | 53 ++++------ > J> sys/dev/tpm/tpm_bus.c | 99 ++++++++++++++++++ > J> sys/dev/tpm/tpm_crb.c | 66 ++++++------ > J> sys/dev/tpm/tpm_if.m | 76 ++++++++++++++ > J> sys/dev/tpm/tpm_spibus.c | 166 > J> ++++++++++++++++++++++++++++++ sys/dev/tpm/tpm_tis_acpi.c > J> | 86 ++++++++++++++++ sys/dev/tpm/{tpm_tis.c => > J> tpm_tis_core.c} | 118 ++++++++------------- > J> sys/dev/tpm/tpm_tis_spibus.c | 91 ++++++++++++++++ > J> sys/modules/Makefile | 3 +- > J> sys/modules/tpm/Makefile | 21 +++- 13 files > J> changed, 640 insertions(+), 154 deletions(-) > J> > J> diff --git a/sys/conf/files b/sys/conf/files > J> index f68567aa9023..4d7f28ceaaf1 100644 > J> --- a/sys/conf/files > J> +++ b/sys/conf/files > J> @@ -3194,6 +3194,13 @@ dev/syscons/warp/warp_saver.c > J> optional warp_saver dev/tcp_log/tcp_log_dev.c optional > J> tcp_blackbox inet | tcp_blackbox inet6 dev/tdfx/tdfx_pci.c > J> optional tdfx pci dev/ti/if_ti.c > J> optional ti pci +dev/tpm/tpm20.c > J> optional tpm +dev/tpm/tpm_bus.c optional tpm > J> acpi +dev/tpm/tpm_if.m optional tpm > J> +dev/tpm/tpm_spibus.c optional tpm spibus fdt > J> +dev/tpm/tpm_tis_acpi.c optional tpm acpi > J> +dev/tpm/tpm_tis_core.c optional tpm > J> +dev/tpm/tpm_tis_spibus.c optional tpm spibus fdt > J> dev/tws/tws.c optional tws > J> dev/tws/tws_cam.c optional tws > J> dev/tws/tws_hdm.c optional tws > J> diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 > J> index 6322837c887b..18dec5ed47b0 100644 > J> --- a/sys/conf/files.amd64 > J> +++ b/sys/conf/files.amd64 > J> @@ -372,9 +372,7 @@ dev/smartpqi/smartpqi_sis.c optional > J> smartpqi dev/smartpqi/smartpqi_tag.c optional > J> smartpqi dev/sume/if_sume.c optional sume > J> dev/syscons/apm/apm_saver.c optional apm_saver apm > J> -dev/tpm/tpm20.c optional tpm > J> dev/tpm/tpm_crb.c optional tpm acpi > J> -dev/tpm/tpm_tis.c optional tpm acpi > J> dev/tpm/tpm_acpi.c optional tpm acpi > J> dev/tpm/tpm_isa.c optional tpm isa > J> dev/p2sb/p2sb.c optional p2sb pci > J> diff --git a/sys/dev/tpm/tpm20.c b/sys/dev/tpm/tpm20.c > J> index da090bc068c9..3399e17f53aa 100644 > J> --- a/sys/dev/tpm/tpm20.c > J> +++ b/sys/dev/tpm/tpm20.c > J> @@ -127,7 +127,7 @@ tpm20_write(struct cdev *dev, struct uio *uio, > J> int flags) return (result); > J> } > J> > J> - result = sc->transmit(sc, byte_count); > J> + result = TPM_TRANSMIT(sc->dev, byte_count); > J> > J> if (result == 0) { > J> callout_reset(&sc->discard_buffer_callout, > J> @@ -267,7 +267,7 @@ tpm20_harvest(void *arg, int unused) > J> cv_wait(&sc->buf_cv, &sc->dev_lock); > J> > J> memcpy(sc->buf, cmd, sizeof(cmd)); > J> - result = sc->transmit(sc, sizeof(cmd)); > J> + result = TPM_TRANSMIT(sc->dev, sizeof(cmd)); > J> if (result != 0) { > J> sx_xunlock(&sc->dev_lock); > J> return; > J> @@ -319,7 +319,7 @@ tpm20_save_state(device_t dev, bool suspend) > J> sx_xlock(&sc->dev_lock); > J> > J> memcpy(sc->buf, save_cmd, sizeof(save_cmd)); > J> - sc->transmit(sc, sizeof(save_cmd)); > J> + TPM_TRANSMIT(sc->dev, sizeof(save_cmd)); > J> > J> sx_xunlock(&sc->dev_lock); > J> > J> diff --git a/sys/dev/tpm/tpm20.h b/sys/dev/tpm/tpm20.h > J> index 14f89de3e84e..683cd7549bd4 100644 > J> --- a/sys/dev/tpm/tpm20.h > J> +++ b/sys/dev/tpm/tpm20.h > J> @@ -28,6 +28,7 @@ > J> #ifndef _TPM20_H_ > J> #define _TPM20_H_ > J> > J> +#include "opt_acpi.h" > J> #include <sys/cdefs.h> > J> #include <sys/endian.h> > J> #include <sys/param.h> > J> @@ -39,6 +40,7 @@ > J> #include <sys/bus.h> > J> #include <sys/callout.h> > J> #include <sys/conf.h> > J> +#include <sys/lock.h> > J> #include <sys/module.h> > J> #include <sys/rman.h> > J> #include <sys/sx.h> > J> @@ -49,12 +51,14 @@ > J> #include <machine/md_var.h> > J> #include <machine/resource.h> > J> > J> +#ifdef DEV_ACPI > J> #include <contrib/dev/acpica/include/acpi.h> > J> #include <contrib/dev/acpica/include/accommon.h> > J> #include <dev/acpica/acpivar.h> > J> -#include "opt_acpi.h" > J> +#endif > J> > J> #include "opt_tpm.h" > J> +#include "tpm_if.h" > J> > J> #define BIT(x) (1 << (x)) > J> > J> @@ -136,55 +140,36 @@ int32_t tpm20_get_timeout(uint32_t command); > J> int tpm20_init(struct tpm_sc *sc); > J> void tpm20_release(struct tpm_sc *sc); > J> > J> -/* Small helper routines for io ops */ > J> -static inline uint8_t > J> -RD1(struct tpm_sc *sc, bus_size_t off) > J> -{ > J> - > J> - return (bus_read_1(sc->mem_res, off)); > J> -} > J> -static inline uint32_t > J> -RD4(struct tpm_sc *sc, bus_size_t off) > J> -{ > J> - > J> - return (bus_read_4(sc->mem_res, off)); > J> -} > J> -#ifdef __amd64__ > J> -static inline uint64_t > J> -RD8(struct tpm_sc *sc, bus_size_t off) > J> -{ > J> +/* Mode driver types */ > J> +DECLARE_CLASS(tpmtis_driver); > J> +int tpmtis_attach(device_t dev); > J> > J> - return (bus_read_8(sc->mem_res, off)); > J> -} > J> -#endif > J> -static inline void > J> -WR1(struct tpm_sc *sc, bus_size_t off, uint8_t val) > J> -{ > J> +DECLARE_CLASS(tpmcrb_driver); > J> > J> - bus_write_1(sc->mem_res, off, val); > J> -} > J> -static inline void > J> -WR4(struct tpm_sc *sc, bus_size_t off, uint32_t val) > J> -{ > J> +/* Bus driver types */ > J> +DECLARE_CLASS(tpm_bus_driver); > J> +DECLARE_CLASS(tpm_spi_driver); > J> > J> - bus_write_4(sc->mem_res, off, val); > J> -} > J> +/* Small helper routines for io ops */ > J> static inline void > J> AND4(struct tpm_sc *sc, bus_size_t off, uint32_t val) > J> { > J> + uint32_t v = TPM_READ_4(sc->dev, off); > J> > J> - WR4(sc, off, RD4(sc, off) & val); > J> + TPM_WRITE_4(sc->dev, off, v & val); > J> } > J> static inline void > J> OR1(struct tpm_sc *sc, bus_size_t off, uint8_t val) > J> { > J> + uint8_t v = TPM_READ_1(sc->dev, off); > J> > J> - WR1(sc, off, RD1(sc, off) | val); > J> + TPM_WRITE_1(sc->dev, off, v | val); > J> } > J> static inline void > J> OR4(struct tpm_sc *sc, bus_size_t off, uint32_t val) > J> { > J> + uint32_t v = TPM_READ_1(sc->dev, off); > J> > J> - WR4(sc, off, RD4(sc, off) | val); > J> + TPM_WRITE_4(sc->dev, off, v | val); > J> } > J> #endif /* _TPM20_H_ */ > J> diff --git a/sys/dev/tpm/tpm_bus.c b/sys/dev/tpm/tpm_bus.c > J> new file mode 100644 > J> index 000000000000..f0d3c26c33f1 > J> --- /dev/null > J> +++ b/sys/dev/tpm/tpm_bus.c > J> @@ -0,0 +1,99 @@ > J> +/*- > J> + * Copyright (c) 2023 Juniper Networks, Inc. > J> + * All rights reserved. > J> + * > J> + * Redistribution and use in source and binary forms, with or > J> without > J> + * modification, are permitted provided that the following > J> conditions > J> + * are met: > J> + * 1. Redistributions of source code must retain the above > J> copyright > J> + * notice, this list of conditions and the following > J> disclaimer. > J> + * 2. Redistributions in binary form must reproduce the above > J> copyright > J> + * notice, this list of conditions and the following > J> disclaimer in the > J> + * documentation and/or other materials provided with the > J> distribution. > J> + * > J> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY > J> EXPRESS OR > J> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED > J> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > J> PURPOSE ARE > J> + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY > J> DIRECT, > J> + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > J> DAMAGES > J> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE > J> GOODS OR > J> + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > J> INTERRUPTION) > J> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > J> CONTRACT, > J> + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > J> ARISING IN > J> + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE > J> + * POSSIBILITY OF SUCH DAMAGE. > J> + */ > J> + > J> +#include <sys/cdefs.h> > J> +#include <sys/types.h> > J> +#include <sys/bus.h> > J> +#include "tpm_if.h" > J> +#include "tpm20.h" > J> + > J> +/* Override accessors */ > J> +static uint8_t > J> +tpm_read_1(device_t dev, bus_size_t off) > J> +{ > J> + struct tpm_sc *sc = device_get_softc(dev); > J> + > J> + return (bus_read_1(sc->mem_res, off)); > J> +} > J> + > J> +static uint32_t > J> +tpm_read_4(device_t dev, bus_size_t off) > J> +{ > J> + struct tpm_sc *sc = device_get_softc(dev); > J> + > J> + return (bus_read_4(sc->mem_res, off)); > J> +} > J> + > J> +/* > J> + * Only i386 is missing bus_space_read_8. > J> + */ > J> +#ifndef __i386__ > J> +static uint64_t > J> +tpm_read_8(device_t dev, bus_size_t off) > J> +{ > J> + struct tpm_sc *sc = device_get_softc(dev); > J> + > J> + return (bus_read_8(sc->mem_res, off)); > J> +} > J> +#endif > J> + > J> +static void > J> +tpm_write_1(device_t dev, bus_size_t off, uint8_t val) > J> +{ > J> + struct tpm_sc *sc = device_get_softc(dev); > J> + > J> + bus_write_1(sc->mem_res, off, val); > J> +} > J> + > J> +static void > J> +tpm_write_4(device_t dev, bus_size_t off, uint32_t val) > J> +{ > J> + struct tpm_sc *sc = device_get_softc(dev); > J> + > J> + bus_write_4(sc->mem_res, off, val); > J> +} > J> + > J> +static void > J> +tpm_write_barrier(device_t dev, bus_addr_t off, bus_size_t length) > J> +{ > J> + struct tpm_sc *sc = device_get_softc(dev); > J> + > J> + bus_barrier(sc->mem_res, off, length, > J> BUS_SPACE_BARRIER_WRITE); +} > J> + > J> +static device_method_t tpm_bus_methods[] = { > J> + DEVMETHOD(tpm_read_1, tpm_read_1), > J> + DEVMETHOD(tpm_read_4, tpm_read_4), > J> +#ifndef __i386__ > J> + DEVMETHOD(tpm_read_8, tpm_read_8), > J> +#endif > J> + DEVMETHOD(tpm_write_1, tpm_write_1), > J> + DEVMETHOD(tpm_write_4, tpm_write_4), > J> + DEVMETHOD(tpm_write_barrier, tpm_write_barrier), > J> + DEVMETHOD_END > J> +}; > J> + > J> +DEFINE_CLASS_0(tpm_lbc, tpm_bus_driver, tpm_bus_methods, > J> sizeof(struct tpm_sc)); diff --git a/sys/dev/tpm/tpm_crb.c > J> b/sys/dev/tpm/tpm_crb.c index bb4df82e613b..b9ddcf0dd3e1 100644 > J> --- a/sys/dev/tpm/tpm_crb.c > J> +++ b/sys/dev/tpm/tpm_crb.c > J> @@ -83,7 +83,7 @@ struct tpmcrb_sc { > J> size_t rsp_buf_size; > J> }; > J> > J> -int tpmcrb_transmit(struct tpm_sc *sc, size_t size); > J> +int tpmcrb_transmit(device_t dev, size_t size); > J> > J> static int tpmcrb_acpi_probe(device_t dev); > J> static int tpmcrb_attach(device_t dev); > J> @@ -185,15 +185,15 @@ tpmcrb_attach(device_t dev) > J> * stored in a single 8 byte one. > J> */ > J> #ifdef __amd64__ > J> - crb_sc->rsp_off = RD8(sc, TPM_CRB_CTRL_RSP_ADDR); > J> + crb_sc->rsp_off = TPM_READ_8(sc->dev, > J> TPM_CRB_CTRL_RSP_ADDR); #else > J> - crb_sc->rsp_off = RD4(sc, TPM_CRB_CTRL_RSP_ADDR); > J> - crb_sc->rsp_off |= ((uint64_t) RD4(sc, > J> TPM_CRB_CTRL_RSP_HADDR) << 32); > J> + crb_sc->rsp_off = TPM_READ_4(sc->dev, > J> TPM_CRB_CTRL_RSP_ADDR); > J> + crb_sc->rsp_off |= ((uint64_t) TPM_READ_4(sc->dev, > J> TPM_CRB_CTRL_RSP_HADDR) << 32); #endif > J> - crb_sc->cmd_off = RD4(sc, TPM_CRB_CTRL_CMD_LADDR); > J> - crb_sc->cmd_off |= ((uint64_t) RD4(sc, > J> TPM_CRB_CTRL_CMD_HADDR) << 32); > J> - crb_sc->cmd_buf_size = RD4(sc, TPM_CRB_CTRL_CMD_SIZE); > J> - crb_sc->rsp_buf_size = RD4(sc, TPM_CRB_CTRL_RSP_SIZE); > J> + crb_sc->cmd_off = TPM_READ_4(sc->dev, > J> TPM_CRB_CTRL_CMD_LADDR); > J> + crb_sc->cmd_off |= ((uint64_t) TPM_READ_4(sc->dev, > J> TPM_CRB_CTRL_CMD_HADDR) << 32); > J> + crb_sc->cmd_buf_size = TPM_READ_4(sc->dev, > J> TPM_CRB_CTRL_CMD_SIZE); > J> + crb_sc->rsp_buf_size = TPM_READ_4(sc->dev, > J> TPM_CRB_CTRL_RSP_SIZE); > J> tpmcrb_relinquish_locality(sc); > J> > J> @@ -218,8 +218,6 @@ tpmcrb_attach(device_t dev) > J> } > J> } > J> > J> - sc->transmit = tpmcrb_transmit; > J> - > J> result = tpm20_init(sc); > J> if (result != 0) > J> tpmcrb_detach(dev); > J> @@ -248,11 +246,11 @@ tpm_wait_for_u32(struct tpm_sc *sc, > J> bus_size_t off, uint32_t mask, uint32_t val, { > J> > J> /* Check for condition */ > J> - if ((RD4(sc, off) & mask) == val) > J> + if ((TPM_READ_4(sc->dev, off) & mask) == val) > J> return (true); > J> > J> while (timeout > 0) { > J> - if ((RD4(sc, off) & mask) == val) > J> + if ((TPM_READ_4(sc->dev, off) & mask) == val) > J> return (true); > J> > J> pause("TPM in polling mode", 1); > J> @@ -291,7 +289,7 @@ tpmcrb_cancel_cmd(struct tpm_sc *sc) > J> { > J> uint32_t mask = ~0; > J> > J> - WR4(sc, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CMD); > J> + TPM_WRITE_4(sc->dev, TPM_CRB_CTRL_CANCEL, > J> TPM_CRB_CTRL_CANCEL_CMD); if (!tpm_wait_for_u32(sc, > J> TPM_CRB_CTRL_START, mask, ~mask, TPM_TIMEOUT_B)) { > J> device_printf(sc->dev, > J> @@ -299,48 +297,50 @@ tpmcrb_cancel_cmd(struct tpm_sc *sc) > J> return (false); > J> } > J> > J> - WR4(sc, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR); > J> + TPM_WRITE_4(sc->dev, TPM_CRB_CTRL_CANCEL, > J> TPM_CRB_CTRL_CANCEL_CLEAR); return (true); > J> } > J> > J> int > J> -tpmcrb_transmit(struct tpm_sc *sc, size_t length) > J> +tpmcrb_transmit(device_t dev, size_t length) > J> { > J> struct tpmcrb_sc *crb_sc; > J> + struct tpm_sc *sc; > J> uint32_t mask, curr_cmd; > J> int timeout, bytes_available; > J> > J> - crb_sc = (struct tpmcrb_sc *)sc; > J> + crb_sc = device_get_softc(dev); > J> + sc = &crb_sc->base; > J> > J> sx_assert(&sc->dev_lock, SA_XLOCKED); > J> > J> if (length > crb_sc->cmd_buf_size) { > J> - device_printf(sc->dev, > J> + device_printf(dev, > J> "Requested transfer is bigger than buffer > J> size\n"); return (E2BIG); > J> } > J> > J> - if (RD4(sc, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_ERR_BIT) > J> { > J> - device_printf(sc->dev, > J> + if (TPM_READ_4(dev, TPM_CRB_CTRL_STS) & > J> TPM_CRB_CTRL_STS_ERR_BIT) { > J> + device_printf(dev, > J> "Device has Error bit set\n"); > J> return (EIO); > J> } > J> if (!tpmcrb_request_locality(sc, 0)) { > J> - device_printf(sc->dev, > J> + device_printf(dev, > J> "Failed to obtain locality\n"); > J> return (EIO); > J> } > J> /* Clear cancellation bit */ > J> - WR4(sc, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR); > J> + TPM_WRITE_4(dev, TPM_CRB_CTRL_CANCEL, > J> TPM_CRB_CTRL_CANCEL_CLEAR); > J> /* Switch device to idle state if necessary */ > J> - if (!(RD4(sc, TPM_CRB_CTRL_STS) & > J> TPM_CRB_CTRL_STS_IDLE_BIT)) { > J> + if (!(TPM_READ_4(dev, TPM_CRB_CTRL_STS) & > J> TPM_CRB_CTRL_STS_IDLE_BIT)) { OR4(sc, TPM_CRB_CTRL_REQ, > J> TPM_CRB_CTRL_REQ_GO_IDLE); > J> mask = TPM_CRB_CTRL_STS_IDLE_BIT; > J> if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, > J> mask, mask, TPM_TIMEOUT_C)) { > J> - device_printf(sc->dev, > J> + device_printf(dev, > J> "Failed to transition to idle > J> state\n"); return (EIO); > J> } > J> @@ -351,7 +351,7 @@ tpmcrb_transmit(struct tpm_sc *sc, size_t > J> length) mask = TPM_CRB_CTRL_REQ_GO_READY; > J> if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, > J> mask, !mask, TPM_TIMEOUT_C)) { > J> - device_printf(sc->dev, > J> + device_printf(dev, > J> "Failed to transition to ready state\n"); > J> return (EIO); > J> } > J> @@ -366,16 +366,14 @@ tpmcrb_transmit(struct tpm_sc *sc, size_t > J> length) /* Send command and tell device to process it. */ > J> bus_write_region_stream_1(sc->mem_res, crb_sc->cmd_off, > J> sc->buf, length); > J> - bus_barrier(sc->mem_res, crb_sc->cmd_off, > J> - length, BUS_SPACE_BARRIER_WRITE); > J> + TPM_WRITE_BARRIER(dev, crb_sc->cmd_off, length); > J> > J> - WR4(sc, TPM_CRB_CTRL_START, TPM_CRB_CTRL_START_CMD); > J> - bus_barrier(sc->mem_res, TPM_CRB_CTRL_START, > J> - 4, BUS_SPACE_BARRIER_WRITE); > J> + TPM_WRITE_4(dev, TPM_CRB_CTRL_START, > J> TPM_CRB_CTRL_START_CMD); > J> + TPM_WRITE_BARRIER(dev, TPM_CRB_CTRL_START, 4); > J> > J> mask = ~0; > J> if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_START, mask, > J> ~mask, timeout)) { > J> - device_printf(sc->dev, > J> + device_printf(dev, > J> "Timeout while waiting for device to process > J> cmd\n"); if (!tpmcrb_cancel_cmd(sc)) > J> return (EIO); > J> @@ -387,7 +385,7 @@ tpmcrb_transmit(struct tpm_sc *sc, size_t > J> length) bytes_available = be32toh(*(uint32_t *) (&sc->buf[2])); > J> > J> if (bytes_available > TPM_BUFSIZE || bytes_available < > J> TPM_HEADER_SIZE) { > J> - device_printf(sc->dev, > J> + device_printf(dev, > J> "Incorrect response size: %d\n", > J> bytes_available); > J> return (EIO); > J> @@ -411,11 +409,11 @@ static device_method_t > J> tpmcrb_methods[] = { DEVMETHOD(device_detach, > J> tpmcrb_detach), DEVMETHOD(device_shutdown, tpm20_shutdown), > J> DEVMETHOD(device_suspend, tpm20_suspend), > J> + DEVMETHOD(tpm_transmit, tpmcrb_transmit), > J> {0, 0} > J> }; > J> > J> -static driver_t tpmcrb_driver = { > J> - "tpmcrb", tpmcrb_methods, sizeof(struct tpmcrb_sc), > J> -}; > J> +DEFINE_CLASS_1(tpmcrb, tpmcrb_driver, tpmcrb_methods, > J> sizeof(struct tpmcrb_sc), > J> + tpm_bus_driver); > J> > J> DRIVER_MODULE(tpmcrb, acpi, tpmcrb_driver, 0, 0); > J> diff --git a/sys/dev/tpm/tpm_if.m b/sys/dev/tpm/tpm_if.m > J> new file mode 100644 > J> index 000000000000..2b6afe22f3e8 > J> --- /dev/null > J> +++ b/sys/dev/tpm/tpm_if.m > J> @@ -0,0 +1,76 @@ > J> +#- > J> +# Copyright (c) 2023 Juniper Networks, Inc. > J> +# All Rights Reserved > J> +# > J> +# Redistribution and use in source and binary forms, with or > J> without +# modification, are permitted provided that the following > J> conditions +# are met: > J> +# 1. Redistributions of source code must retain the above > J> copyright +# notice, this list of conditions and the following > J> disclaimer. +# 2. Redistributions in binary form must reproduce > J> the above copyright +# notice, this list of conditions and the > J> following disclaimer in the +# documentation and/or other > J> materials provided with the distribution. +# > J> +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS > J> IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > J> LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND > J> FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT > J> SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, > J> INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# > J> DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE > J> GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > J> INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > J> WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING > J> NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF > J> THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH > J> DAMAGE. +# +# > J> + > J> +#include <sys/bus.h> > J> +#include <dev/tpm/tpm20.h> > J> + > J> +INTERFACE tpm; > J> + > J> +# > J> +# Transfer data to the TPM data buffer > J> +# > J> +METHOD int transmit { > J> + device_t dev; > J> + size_t length; > J> +}; > J> + > J> + > J> +METHOD uint64_t read_8 { > J> + device_t dev; > J> + bus_addr_t addr; > J> +} > J> + > J> +# > J> +# Read 4 bytes (host endian) from a TPM register > J> +# > J> +METHOD uint32_t read_4 { > J> + device_t dev; > J> + bus_addr_t addr; > J> +}; > J> + > J> +METHOD uint8_t read_1 { > J> + device_t dev; > J> + bus_addr_t addr; > J> +}; > J> + > J> +METHOD void write_4 { > J> + device_t dev; > J> + bus_addr_t addr; > J> + uint32_t value; > J> +}; > J> + > J> +METHOD void write_1 { > J> + device_t dev; > J> + bus_addr_t addr; > J> + uint8_t value; > J> +}; > J> + > J> +METHOD void write_barrier { > J> + device_t dev; > J> + bus_addr_t off; > J> + bus_size_t length; > J> +} > J> diff --git a/sys/dev/tpm/tpm_spibus.c b/sys/dev/tpm/tpm_spibus.c > J> new file mode 100644 > J> index 000000000000..f83ff42d77b1 > J> --- /dev/null > J> +++ b/sys/dev/tpm/tpm_spibus.c > J> @@ -0,0 +1,166 @@ > J> +/*- > J> + * Copyright (c) 2023 Juniper Networks, Inc. > J> + * All rights reserved. > J> + * > J> + * Redistribution and use in source and binary forms, with or > J> without > J> + * modification, are permitted provided that the following > J> conditions > J> + * are met: > J> + * 1. Redistributions of source code must retain the above > J> copyright > J> + * notice, this list of conditions and the following > J> disclaimer. > J> + * 2. Redistributions in binary form must reproduce the above > J> copyright > J> + * notice, this list of conditions and the following > J> disclaimer in the > J> + * documentation and/or other materials provided with the > J> distribution. > J> + * > J> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY > J> EXPRESS OR > J> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED > J> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > J> PURPOSE ARE > J> + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY > J> DIRECT, > J> + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > J> DAMAGES > J> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE > J> GOODS OR > J> + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > J> INTERRUPTION) > J> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > J> CONTRACT, > J> + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > J> ARISING IN > J> + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE > J> + * POSSIBILITY OF SUCH DAMAGE. > J> + */ > J> + > J> +#include <sys/cdefs.h> > J> +#include <sys/types.h> > J> +#include <sys/bus.h> > J> + > J> +#include <dev/spibus/spi.h> > J> +#include "spibus_if.h" > J> +#include "tpm_if.h" > J> +#include "tpm20.h" > J> + > J> +#define TPM_BASE_ADDR 0xD40000 > J> +#define TPM_SPI_HEADER_SIZE 4 > J> +#define TPM_WAIT_STATES 50 > J> + > J> +static void > J> +tpm_insert_wait(device_t dev) > J> +{ > J> + device_t parent = device_get_parent(dev); > J> + int wait = TPM_WAIT_STATES; > J> + struct spi_command spic = SPI_COMMAND_INITIALIZER; > J> + > J> + uint8_t txb = 0; > J> + uint8_t rxb = 0; > J> + > J> + spic.tx_cmd = &txb; > J> + spic.rx_cmd = &rxb; > J> + spic.tx_cmd_sz = 1; > J> + spic.rx_cmd_sz = 1; > J> + spic.flags = SPI_FLAG_KEEP_CS; > J> + do { > J> + SPIBUS_TRANSFER(parent, dev, &spic); > J> + } while (--wait > 0 && (rxb & 0x1) == 0); > J> +} > J> + > J> +static inline int > J> +tpm_spi_read_n(device_t dev, bus_size_t off, void *buf, size_t > J> size) +{ > J> + struct spi_command spic = SPI_COMMAND_INITIALIZER; > J> + uint8_t tx[4] = {0}; > J> + uint8_t rx[4] = {0}; > J> + int err; > J> + > J> + if (size > sizeof(rx)) > J> + return (EINVAL); > J> + off += TPM_BASE_ADDR; > J> + tx[0] = 0x80 | (size - 1); /* Write (size) bytes */ > J> + tx[1] = (off >> 16) & 0xff; > J> + tx[2] = (off >> 8) & 0xff; > J> + tx[3] = off & 0xff; > J> + > J> + spic.tx_cmd = tx; > J> + spic.tx_cmd_sz = sizeof(tx); > J> + spic.rx_cmd = rx; > J> + spic.rx_cmd_sz = sizeof(tx); > J> + spic.flags = SPI_FLAG_KEEP_CS; > J> + > J> + err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &spic); > J> + > J> + if (!(rx[3] & 0x1)) { > J> + tpm_insert_wait(dev); > J> + } > J> + memset(tx, 0, sizeof(tx)); > J> + spic.tx_cmd_sz = spic.rx_cmd_sz = size; > J> + spic.flags = 0; > J> + err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &spic); > J> + memcpy(buf, &rx[0], size); > J> + > J> + return (err); > J> +} > J> + > J> +static inline int > J> +tpm_spi_write_n(device_t dev, bus_size_t off, void *buf, size_t > J> size) +{ > J> + struct spi_command spic = SPI_COMMAND_INITIALIZER; > J> + uint8_t tx[8] = {0}; > J> + uint8_t rx[8] = {0}; > J> + int err; > J> + > J> + off += TPM_BASE_ADDR; > J> + tx[0] = 0x00 | (size - 1); /* Write (size) bytes */ > J> + tx[1] = (off >> 16) & 0xff; > J> + tx[2] = (off >> 8) & 0xff; > J> + tx[3] = off & 0xff; > J> + > J> + memcpy(&tx[4], buf, size); > J> + > J> + spic.tx_cmd = tx; > J> + spic.tx_cmd_sz = size + TPM_SPI_HEADER_SIZE; > J> + spic.rx_cmd = rx; > J> + spic.rx_cmd_sz = size + TPM_SPI_HEADER_SIZE; > J> + > J> + err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &spic); > J> + > J> + return (err); > J> +} > J> + > J> +/* Override accessors */ > J> +static inline uint8_t > J> +spi_read_1(device_t dev, bus_size_t off) > J> +{ > J> + uint8_t rx_byte; > J> + > J> + tpm_spi_read_n(dev, off, &rx_byte, 1); > J> + > J> + return (rx_byte); > J> +} > J> + > J> +static inline uint32_t > J> +spi_read_4(device_t dev, bus_size_t off) > J> +{ > J> + uint32_t rx_word = 0; > J> + > J> + tpm_spi_read_n(dev, off, &rx_word, 4); > J> + rx_word = le32toh(rx_word); > J> + > J> + return (rx_word); > J> +} > J> + > J> +static inline void > J> +spi_write_1(device_t dev, bus_size_t off, uint8_t val) > J> +{ > J> + tpm_spi_write_n(dev, off, &val, 1); > J> +} > J> + > J> +static inline void > J> +spi_write_4(device_t dev, bus_size_t off, uint32_t val) > J> +{ > J> + uint32_t tmp = htole32(val); > J> + tpm_spi_write_n(dev, off, &tmp, 4); > J> +} > J> + > J> +static device_method_t tpm_spibus_methods[] = { > J> + DEVMETHOD(tpm_read_4, spi_read_4), > J> + DEVMETHOD(tpm_read_1, spi_read_1), > J> + DEVMETHOD(tpm_write_4, spi_write_4), > J> + DEVMETHOD(tpm_write_1, spi_write_1), > J> + DEVMETHOD_END > J> +}; > J> + > J> +DEFINE_CLASS_0(tpm_spi, tpm_spi_driver, tpm_spibus_methods, > J> + sizeof(struct tpm_sc)); > J> diff --git a/sys/dev/tpm/tpm_tis_acpi.c > J> b/sys/dev/tpm/tpm_tis_acpi.c new file mode 100644 > J> index 000000000000..32c73e5f2483 > J> --- /dev/null > J> +++ b/sys/dev/tpm/tpm_tis_acpi.c > J> @@ -0,0 +1,86 @@ > J> +/*- > J> + * Copyright (c) 2018 Stormshield. > J> + * Copyright (c) 2018 Semihalf. > J> + * Copyright (c) 2023 Juniper Networks, Inc. > J> + * All rights reserved. > J> + * > J> + * Redistribution and use in source and binary forms, with or > J> without > J> + * modification, are permitted provided that the following > J> conditions > J> + * are met: > J> + * 1. Redistributions of source code must retain the above > J> copyright > J> + * notice, this list of conditions and the following > J> disclaimer. > J> + * 2. Redistributions in binary form must reproduce the above > J> copyright > J> + * notice, this list of conditions and the following > J> disclaimer in the > J> + * documentation and/or other materials provided with the > J> distribution. > J> + * > J> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY > J> EXPRESS OR > J> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED > J> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > J> PURPOSE ARE > J> + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY > J> DIRECT, > J> + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > J> DAMAGES > J> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE > J> GOODS OR > J> + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > J> INTERRUPTION) > J> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > J> CONTRACT, > J> + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > J> ARISING IN > J> + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE > J> + * POSSIBILITY OF SUCH DAMAGE. > J> + */ > J> + > J> +#include <sys/cdefs.h> > J> +#include "tpm20.h" > J> +#include "tpm_if.h" > J> + > J> +static int tpmtis_acpi_probe(device_t dev); > J> + > J> +char *tpmtis_ids[] = {"MSFT0101", NULL}; > J> + > J> +static int > J> +tpmtis_acpi_probe(device_t dev) > J> +{ > J> + int err; > J> + ACPI_TABLE_TPM23 *tbl; > J> + ACPI_STATUS status; > J> + > J> + err = ACPI_ID_PROBE(device_get_parent(dev), dev, > J> tpmtis_ids, NULL); > J> + if (err > 0) > J> + return (err); > J> + /*Find TPM2 Header*/ > J> + status = AcpiGetTable(ACPI_SIG_TPM2, 1, > J> (ACPI_TABLE_HEADER **) &tbl); > J> + if(ACPI_FAILURE(status) || > J> + tbl->StartMethod != TPM2_START_METHOD_TIS) > J> + err = ENXIO; > J> + > J> + device_set_desc(dev, "Trusted Platform Module 2.0, FIFO > J> mode"); > J> + return (err); > J> +} > J> + > J> +static int > J> +tpmtis_acpi_attach(device_t dev) > J> +{ > J> + struct tpm_sc *sc = device_get_softc(dev); > J> + > J> + sc->mem_rid = 0; > J> + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, > J> &sc->mem_rid, > J> + RF_ACTIVE); > J> + if (sc->mem_res == NULL) { > J> + return (ENXIO); > J> + } > J> + > J> + /* > J> + * If tpmtis_attach() fails, tpmtis_detach() will > J> automatically free > J> + * sc->mem_res (not-NULL). > J> + */ > J> + return (tpmtis_attach(dev)); > J> +} > J> + > J> +/* ACPI Driver */ > J> +static device_method_t tpmtis_methods[] = { > J> + DEVMETHOD(device_attach, tpmtis_acpi_attach), > J> + DEVMETHOD(device_probe, tpmtis_acpi_probe), > J> + DEVMETHOD_END > J> +}; > J> + > J> +DEFINE_CLASS_2(tpmtis, tpmtis_acpi_driver, tpmtis_methods, > J> + sizeof(struct tpm_sc), tpmtis_driver, tpm_bus_driver); > J> + > J> +DRIVER_MODULE(tpmtis, acpi, tpmtis_driver, 0, 0); > J> diff --git a/sys/dev/tpm/tpm_tis.c b/sys/dev/tpm/tpm_tis_core.c > J> similarity index 82% > J> rename from sys/dev/tpm/tpm_tis.c > J> rename to sys/dev/tpm/tpm_tis_core.c > J> index b97d7ab3f8e8..230eb12d2acd 100644 > J> --- a/sys/dev/tpm/tpm_tis.c > J> +++ b/sys/dev/tpm/tpm_tis_core.c > J> @@ -27,6 +27,7 @@ > J> > J> #include <sys/cdefs.h> > J> #include "tpm20.h" > J> +#include "tpm_if.h" > J> > J> /* > J> * TIS register space as defined in > J> @@ -72,10 +73,8 @@ > J> #define TPM_STS_BURST_MASK 0xFFFF00 > J> #define TPM_STS_BURST_OFFSET 0x8 > J> > J> -static int tpmtis_transmit(struct tpm_sc *sc, size_t length); > J> +static int tpmtis_transmit(device_t dev, size_t length); > J> > J> -static int tpmtis_acpi_probe(device_t dev); > J> -static int tpmtis_attach(device_t dev); > J> static int tpmtis_detach(device_t dev); > J> > J> static void tpmtis_intr_handler(void *arg); > J> @@ -93,29 +92,7 @@ static bool tpm_wait_for_u32(struct tpm_sc *sc, > J> bus_size_t off, > J> static uint16_t tpmtis_wait_for_burst(struct tpm_sc *sc); > J> > J> -char *tpmtis_ids[] = {"MSFT0101", NULL}; > J> - > J> -static int > J> -tpmtis_acpi_probe(device_t dev) > J> -{ > J> - int err; > J> - ACPI_TABLE_TPM23 *tbl; > J> - ACPI_STATUS status; > J> - > J> - err = ACPI_ID_PROBE(device_get_parent(dev), dev, > J> tpmtis_ids, NULL); > J> - if (err > 0) > J> - return (err); > J> - /*Find TPM2 Header*/ > J> - status = AcpiGetTable(ACPI_SIG_TPM2, 1, > J> (ACPI_TABLE_HEADER **) &tbl); > J> - if(ACPI_FAILURE(status) || > J> - tbl->StartMethod != TPM2_START_METHOD_TIS) > J> - err = ENXIO; > J> - > J> - device_set_desc(dev, "Trusted Platform Module 2.0, FIFO > J> mode"); > J> - return (err); > J> -} > J> - > J> -static int > J> +int > J> tpmtis_attach(device_t dev) > J> { > J> struct tpm_sc *sc; > J> @@ -123,20 +100,11 @@ tpmtis_attach(device_t dev) > J> > J> sc = device_get_softc(dev); > J> sc->dev = dev; > J> - sc->transmit = tpmtis_transmit; > J> sc->intr_type = -1; > J> > J> sx_init(&sc->dev_lock, "TPM driver lock"); > J> sc->buf = malloc(TPM_BUFSIZE, M_TPM20, M_WAITOK); > J> > J> - sc->mem_rid = 0; > J> - sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, > J> &sc->mem_rid, > J> - RF_ACTIVE); > J> - if (sc->mem_res == NULL) { > J> - tpmtis_detach(dev); > J> - return (ENXIO); > J> - } > J> - > J> sc->irq_rid = 0; > J> sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, > J> &sc->irq_rid, RF_ACTIVE | RF_SHAREABLE); > J> @@ -198,7 +166,7 @@ tpmtis_test_intr(struct tpm_sc *sc) > J> > J> sx_xlock(&sc->dev_lock); > J> memcpy(sc->buf, cmd, sizeof(cmd)); > J> - tpmtis_transmit(sc, sizeof(cmd)); > J> + tpmtis_transmit(sc->dev, sizeof(cmd)); > J> sc->pending_data_length = 0; > J> sx_xunlock(&sc->dev_lock); > J> } > J> @@ -222,19 +190,19 @@ tpmtis_setup_intr(struct tpm_sc *sc) > J> if(!tpmtis_request_locality(sc, 0)) > J> sc->interrupts = false; > J> > J> - WR1(sc, TPM_INT_VECTOR, irq); > J> + TPM_WRITE_1(sc->dev, TPM_INT_VECTOR, irq); > J> > J> /* Clear all pending interrupts. */ > J> - reg = RD4(sc, TPM_INT_STS); > J> - WR4(sc, TPM_INT_STS, reg); > J> + reg = TPM_READ_4(sc->dev, TPM_INT_STS); > J> + TPM_WRITE_4(sc->dev, TPM_INT_STS, reg); > J> > J> - reg = RD4(sc, TPM_INT_ENABLE); > J> + reg = TPM_READ_4(sc->dev, TPM_INT_ENABLE); > J> reg |= TPM_INT_ENABLE_GLOBAL_ENABLE | > J> TPM_INT_ENABLE_DATA_AVAIL | > J> TPM_INT_ENABLE_LOC_CHANGE | > J> TPM_INT_ENABLE_CMD_RDY | > J> TPM_INT_ENABLE_STS_VALID; > J> - WR4(sc, TPM_INT_ENABLE, reg); > J> + TPM_WRITE_4(sc->dev, TPM_INT_ENABLE, reg); > J> > J> tpmtis_relinquish_locality(sc); > J> tpmtis_test_intr(sc); > J> @@ -247,9 +215,9 @@ tpmtis_intr_handler(void *arg) > J> uint32_t status; > J> > J> sc = (struct tpm_sc *)arg; > J> - status = RD4(sc, TPM_INT_STS); > J> + status = TPM_READ_4(sc->dev, TPM_INT_STS); > J> > J> - WR4(sc, TPM_INT_STS, status); > J> + TPM_WRITE_4(sc->dev, TPM_INT_STS, status); > J> > J> /* Check for stray interrupts. */ > J> if (sc->intr_type == -1 || (sc->intr_type & status) == 0) > J> @@ -265,7 +233,7 @@ tpm_wait_for_u32(struct tpm_sc *sc, bus_size_t > J> off, uint32_t mask, uint32_t val, { > J> > J> /* Check for condition */ > J> - if ((RD4(sc, off) & mask) == val) > J> + if ((TPM_READ_4(sc->dev, off) & mask) == val) > J> return (true); > J> > J> /* If interrupts are enabled sleep for timeout duration */ > J> @@ -273,12 +241,12 @@ tpm_wait_for_u32(struct tpm_sc *sc, > J> bus_size_t off, uint32_t mask, uint32_t val, tsleep(sc, PWAIT, > J> "TPM WITH INTERRUPTS", timeout / tick); > J> sc->intr_type = -1; > J> - return ((RD4(sc, off) & mask) == val); > J> + return ((TPM_READ_4(sc->dev, off) & mask) == val); > J> } > J> > J> *** 335 LINES SKIPPED *** >