From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christophe Ricard Date: Mon, 24 Aug 2015 22:21:03 +0200 Subject: [U-Boot] [PATCH v2 15/28] dm: tpm: Add a uclass for Trusted Platform Modules In-Reply-To: <1440289904-31280-16-git-send-email-sjg@chromium.org> References: <1440289904-31280-1-git-send-email-sjg@chromium.org> <1440289904-31280-16-git-send-email-sjg@chromium.org> Message-ID: <55DB7CAF.6000600@gmail.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Simon, This one looks good to me as well. Acked-by: Christophe Ricard Best Regards Christophe On 23/08/2015 02:31, Simon Glass wrote: > Add a new uclass for TPMs which uses almost the same TIS (TPM Interface > Specification) as is currently implemented. Since init() is handled by the > normal driver model probe() method, we don't need to implement that. Also > rename the transfer method to xfer() which is a less clumbsy name. > > Once all drivers and users are converted to driver model we can remove the > old code. > > Signed-off-by: Simon Glass > --- > > Changes in v2: > - Enhance uclass to support timeouts with new send()/recv() methods > - Move the timeout definitions into a new tpm_internal.h header > - Use tpm_ prefix instead of tis_ for TPM functions > > drivers/tpm/Kconfig | 9 ++ > drivers/tpm/Makefile | 2 + > drivers/tpm/tpm-uclass.c | 133 +++++++++++++++++++++ > drivers/tpm/tpm_internal.h | 287 +++++++++++++++++++++++++++++++++++++++++++++ > drivers/tpm/tpm_tis_i2c.c | 2 + > drivers/tpm/tpm_tis_i2c.h | 283 -------------------------------------------- > drivers/tpm/tpm_tis_lpc.c | 4 +- > include/dm/uclass-id.h | 1 + > include/tis.h | 3 + > include/tpm.h | 192 ++++++++++++++++++++++++++++++ > 10 files changed, 630 insertions(+), 286 deletions(-) > create mode 100644 drivers/tpm/tpm-uclass.c > create mode 100644 drivers/tpm/tpm_internal.h > > diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig > index 9101fc2..6bc8fdd 100644 > --- a/drivers/tpm/Kconfig > +++ b/drivers/tpm/Kconfig > @@ -4,6 +4,15 @@ > > menu "TPM support" > > +config DM_TPM > + bool "Enable driver model for Trusted Platform Module drivers" > + depends on DM && TPM > + help > + Enable driver model for TPMs. The TIS interface (tis_open(), > + tis_sendrecv(), etc.) is then implemented by the TPM uclass. Note > + that even with driver model only a single TPM is currently > + supported, since the tpm library assumes this. > + > config TPM_TIS_SANDBOX > bool "Enable sandbox TPM driver" > depends on SANDBOX > diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile > index 597966c..0d328f8 100644 > --- a/drivers/tpm/Makefile > +++ b/drivers/tpm/Makefile > @@ -3,6 +3,8 @@ > # SPDX-License-Identifier: GPL-2.0+ > # > > +obj-$(CONFIG_DM_TPM) += tpm-uclass.o > + > obj-$(CONFIG_TPM_ATMEL_TWI) += tpm_atmel_twi.o > obj-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o > obj-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o > diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c > new file mode 100644 > index 0000000..b6e1fc5 > --- /dev/null > +++ b/drivers/tpm/tpm-uclass.c > @@ -0,0 +1,133 @@ > +/* > + * Copyright (c) 2015 Google, Inc > + * Written by Simon Glass > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include "tpm_internal.h" > + > +int tpm_open(struct udevice *dev) > +{ > + struct tpm_ops *ops = tpm_get_ops(dev); > + > + if (!ops->open) > + return -ENOSYS; > + > + return ops->open(dev); > +} > + > +int tpm_close(struct udevice *dev) > +{ > + struct tpm_ops *ops = tpm_get_ops(dev); > + > + if (!ops->close) > + return -ENOSYS; > + > + return ops->close(dev); > +} > + > +int tpm_get_desc(struct udevice *dev, char *buf, int size) > +{ > + struct tpm_ops *ops = tpm_get_ops(dev); > + > + if (!ops->get_desc) > + return -ENOSYS; > + > + return ops->get_desc(dev, buf, size); > +} > + > +/* Returns max number of milliseconds to wait */ > +static ulong tpm_tis_i2c_calc_ordinal_duration(struct tpm_chip_priv *priv, > + u32 ordinal) > +{ > + int duration_idx = TPM_UNDEFINED; > + int duration = 0; > + > + if (ordinal < TPM_MAX_ORDINAL) { > + duration_idx = tpm_ordinal_duration[ordinal]; > + } else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < > + TPM_MAX_PROTECTED_ORDINAL) { > + duration_idx = tpm_protected_ordinal_duration[ > + ordinal & TPM_PROTECTED_ORDINAL_MASK]; > + } > + > + if (duration_idx != TPM_UNDEFINED) > + duration = priv->duration_ms[duration_idx]; > + > + if (duration <= 0) > + return 2 * 60 * 1000; /* Two minutes timeout */ > + else > + return duration; > +} > + > +int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size, > + uint8_t *recvbuf, size_t *recv_size) > +{ > + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); > + struct tpm_ops *ops = tpm_get_ops(dev); > + ulong start, stop; > + uint count, ordinal; > + int ret, ret2; > + > + if (ops->xfer) > + return ops->xfer(dev, sendbuf, send_size, recvbuf, recv_size); > + > + if (!ops->send || !ops->recv) > + return -ENOSYS; > + > + /* switch endianess: big->little */ > + count = get_unaligned_be32(sendbuf + TPM_CMD_COUNT_BYTE); > + ordinal = get_unaligned_be32(sendbuf + TPM_CMD_ORDINAL_BYTE); > + > + if (count == 0) { > + debug("no data\n"); > + return -ENODATA; > + } > + if (count > send_size) { > + debug("invalid count value %x %zx\n", count, send_size); > + return -E2BIG; > + } > + > + debug("%s: Calling send\n", __func__); > + ret = ops->send(dev, sendbuf, send_size); > + if (ret < 0) > + return ret; > + > + start = get_timer(0); > + stop = tpm_tis_i2c_calc_ordinal_duration(priv, ordinal); > + do { > + ret = ops->recv(dev, priv->buf, sizeof(priv->buf)); > + if (ret >= 0) { > + if (ret > *recv_size) > + return -ENOSPC; > + memcpy(recvbuf, priv->buf, ret); > + *recv_size = ret; > + ret = 0; > + break; > + } else if (ret != -EAGAIN) { > + return ret; > + } > + > + mdelay(priv->retry_time_ms); > + if (get_timer(start) > stop) { > + ret = -ETIMEDOUT; > + break; > + } > + } while (ret); > + > + ret2 = ops->cleanup ? ops->cleanup(dev) : 0; > + > + return ret2 ? ret2 : ret; > +} > + > +UCLASS_DRIVER(tpm) = { > + .id = UCLASS_TPM, > + .name = "tpm", > + .flags = DM_UC_FLAG_SEQ_ALIAS, > + .per_device_auto_alloc_size = sizeof(struct tpm_chip_priv), > +}; > diff --git a/drivers/tpm/tpm_internal.h b/drivers/tpm/tpm_internal.h > new file mode 100644 > index 0000000..cd29dba > --- /dev/null > +++ b/drivers/tpm/tpm_internal.h > @@ -0,0 +1,287 @@ > +/* > + * Copyright (c) 2015 Google, Inc > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef __tpm_internal_h > +#define __tpm_internal_h > + > +enum { > + TPM_MAX_ORDINAL = 243, > + TPM_MAX_PROTECTED_ORDINAL = 12, > + TPM_PROTECTED_ORDINAL_MASK = 0xff, > + TPM_CMD_COUNT_BYTE = 2, > + TPM_CMD_ORDINAL_BYTE = 6, > +}; > + > +/* > + * Array with one entry per ordinal defining the maximum amount > + * of time the chip could take to return the result. The ordinal > + * designation of short, medium or long is defined in a table in > + * TCG Specification TPM Main Part 2 TPM Structures Section 17. The > + * values of the SHORT, MEDIUM, and LONG durations are retrieved > + * from the chip during initialization with a call to tpm_get_timeouts. > + */ > +static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = { > + TPM_UNDEFINED, /* 0 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 5 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 10 */ > + TPM_SHORT, > +}; > + > +static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { > + TPM_UNDEFINED, /* 0 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 5 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 10 */ > + TPM_SHORT, > + TPM_MEDIUM, > + TPM_LONG, > + TPM_LONG, > + TPM_MEDIUM, /* 15 */ > + TPM_SHORT, > + TPM_SHORT, > + TPM_MEDIUM, > + TPM_LONG, > + TPM_SHORT, /* 20 */ > + TPM_SHORT, > + TPM_MEDIUM, > + TPM_MEDIUM, > + TPM_MEDIUM, > + TPM_SHORT, /* 25 */ > + TPM_SHORT, > + TPM_MEDIUM, > + TPM_SHORT, > + TPM_SHORT, > + TPM_MEDIUM, /* 30 */ > + TPM_LONG, > + TPM_MEDIUM, > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, /* 35 */ > + TPM_MEDIUM, > + TPM_MEDIUM, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_MEDIUM, /* 40 */ > + TPM_LONG, > + TPM_MEDIUM, > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, /* 45 */ > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, > + TPM_LONG, > + TPM_MEDIUM, /* 50 */ > + TPM_MEDIUM, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 55 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_MEDIUM, /* 60 */ > + TPM_MEDIUM, > + TPM_MEDIUM, > + TPM_SHORT, > + TPM_SHORT, > + TPM_MEDIUM, /* 65 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 70 */ > + TPM_SHORT, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 75 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_LONG, /* 80 */ > + TPM_UNDEFINED, > + TPM_MEDIUM, > + TPM_LONG, > + TPM_SHORT, > + TPM_UNDEFINED, /* 85 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 90 */ > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, > + TPM_UNDEFINED, /* 95 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_MEDIUM, /* 100 */ > + TPM_SHORT, > + TPM_SHORT, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 105 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 110 */ > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, /* 115 */ > + TPM_SHORT, > + TPM_SHORT, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_LONG, /* 120 */ > + TPM_LONG, > + TPM_MEDIUM, > + TPM_UNDEFINED, > + TPM_SHORT, > + TPM_SHORT, /* 125 */ > + TPM_SHORT, > + TPM_LONG, > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, /* 130 */ > + TPM_MEDIUM, > + TPM_UNDEFINED, > + TPM_SHORT, > + TPM_MEDIUM, > + TPM_UNDEFINED, /* 135 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 140 */ > + TPM_SHORT, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 145 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 150 */ > + TPM_MEDIUM, > + TPM_MEDIUM, > + TPM_SHORT, > + TPM_SHORT, > + TPM_UNDEFINED, /* 155 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 160 */ > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 165 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_LONG, /* 170 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 175 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_MEDIUM, /* 180 */ > + TPM_SHORT, > + TPM_MEDIUM, > + TPM_MEDIUM, > + TPM_MEDIUM, > + TPM_MEDIUM, /* 185 */ > + TPM_SHORT, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 190 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 195 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 200 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, > + TPM_SHORT, /* 205 */ > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, > + TPM_MEDIUM, /* 210 */ > + TPM_UNDEFINED, > + TPM_MEDIUM, > + TPM_MEDIUM, > + TPM_MEDIUM, > + TPM_UNDEFINED, /* 215 */ > + TPM_MEDIUM, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, > + TPM_SHORT, /* 220 */ > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, > + TPM_SHORT, > + TPM_UNDEFINED, /* 225 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 230 */ > + TPM_LONG, > + TPM_MEDIUM, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, /* 235 */ > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_UNDEFINED, > + TPM_SHORT, /* 240 */ > + TPM_UNDEFINED, > + TPM_MEDIUM, > +}; > + > +#endif > diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c > index 4b2ef94..645f702 100644 > --- a/drivers/tpm/tpm_tis_i2c.c > +++ b/drivers/tpm/tpm_tis_i2c.c > @@ -25,12 +25,14 @@ > #include > #include > #include > +#include > #include > #include > #include > #include > > #include "tpm_tis_i2c.h" > +#include "tpm_internal.h" > > DECLARE_GLOBAL_DATA_PTR; > > diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_i2c.h > index ecdaf0c..02cc2eb 100644 > --- a/drivers/tpm/tpm_tis_i2c.h > +++ b/drivers/tpm/tpm_tis_i2c.h > @@ -155,293 +155,10 @@ enum tis_status { > #define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) > #define TPM_DID_VID(l) (0x0006 | ((l) << 4)) > > -enum tpm_duration { > - TPM_SHORT = 0, > - TPM_MEDIUM = 1, > - TPM_LONG = 2, > - TPM_UNDEFINED, > -}; > - > /* Extended error numbers from linux (see errno.h) */ > #define ECANCELED 125 /* Operation Canceled */ > > /* Timer frequency. Corresponds to msec timer resolution */ > #define HZ 1000 > > -#define TPM_MAX_ORDINAL 243 > -#define TPM_MAX_PROTECTED_ORDINAL 12 > -#define TPM_PROTECTED_ORDINAL_MASK 0xFF > - > -#define TPM_CMD_COUNT_BYTE 2 > -#define TPM_CMD_ORDINAL_BYTE 6 > - > -/* > - * Array with one entry per ordinal defining the maximum amount > - * of time the chip could take to return the result. The ordinal > - * designation of short, medium or long is defined in a table in > - * TCG Specification TPM Main Part 2 TPM Structures Section 17. The > - * values of the SHORT, MEDIUM, and LONG durations are retrieved > - * from the chip during initialization with a call to tpm_get_timeouts. > - */ > -static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = { > - TPM_UNDEFINED, /* 0 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 5 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 10 */ > - TPM_SHORT, > -}; > - > -static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { > - TPM_UNDEFINED, /* 0 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 5 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 10 */ > - TPM_SHORT, > - TPM_MEDIUM, > - TPM_LONG, > - TPM_LONG, > - TPM_MEDIUM, /* 15 */ > - TPM_SHORT, > - TPM_SHORT, > - TPM_MEDIUM, > - TPM_LONG, > - TPM_SHORT, /* 20 */ > - TPM_SHORT, > - TPM_MEDIUM, > - TPM_MEDIUM, > - TPM_MEDIUM, > - TPM_SHORT, /* 25 */ > - TPM_SHORT, > - TPM_MEDIUM, > - TPM_SHORT, > - TPM_SHORT, > - TPM_MEDIUM, /* 30 */ > - TPM_LONG, > - TPM_MEDIUM, > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, /* 35 */ > - TPM_MEDIUM, > - TPM_MEDIUM, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_MEDIUM, /* 40 */ > - TPM_LONG, > - TPM_MEDIUM, > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, /* 45 */ > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, > - TPM_LONG, > - TPM_MEDIUM, /* 50 */ > - TPM_MEDIUM, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 55 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_MEDIUM, /* 60 */ > - TPM_MEDIUM, > - TPM_MEDIUM, > - TPM_SHORT, > - TPM_SHORT, > - TPM_MEDIUM, /* 65 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 70 */ > - TPM_SHORT, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 75 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_LONG, /* 80 */ > - TPM_UNDEFINED, > - TPM_MEDIUM, > - TPM_LONG, > - TPM_SHORT, > - TPM_UNDEFINED, /* 85 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 90 */ > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, > - TPM_UNDEFINED, /* 95 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_MEDIUM, /* 100 */ > - TPM_SHORT, > - TPM_SHORT, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 105 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 110 */ > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, /* 115 */ > - TPM_SHORT, > - TPM_SHORT, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_LONG, /* 120 */ > - TPM_LONG, > - TPM_MEDIUM, > - TPM_UNDEFINED, > - TPM_SHORT, > - TPM_SHORT, /* 125 */ > - TPM_SHORT, > - TPM_LONG, > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, /* 130 */ > - TPM_MEDIUM, > - TPM_UNDEFINED, > - TPM_SHORT, > - TPM_MEDIUM, > - TPM_UNDEFINED, /* 135 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 140 */ > - TPM_SHORT, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 145 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 150 */ > - TPM_MEDIUM, > - TPM_MEDIUM, > - TPM_SHORT, > - TPM_SHORT, > - TPM_UNDEFINED, /* 155 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 160 */ > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 165 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_LONG, /* 170 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 175 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_MEDIUM, /* 180 */ > - TPM_SHORT, > - TPM_MEDIUM, > - TPM_MEDIUM, > - TPM_MEDIUM, > - TPM_MEDIUM, /* 185 */ > - TPM_SHORT, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 190 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 195 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 200 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, > - TPM_SHORT, /* 205 */ > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, > - TPM_MEDIUM, /* 210 */ > - TPM_UNDEFINED, > - TPM_MEDIUM, > - TPM_MEDIUM, > - TPM_MEDIUM, > - TPM_UNDEFINED, /* 215 */ > - TPM_MEDIUM, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, > - TPM_SHORT, /* 220 */ > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, > - TPM_SHORT, > - TPM_UNDEFINED, /* 225 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 230 */ > - TPM_LONG, > - TPM_MEDIUM, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, /* 235 */ > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_UNDEFINED, > - TPM_SHORT, /* 240 */ > - TPM_UNDEFINED, > - TPM_MEDIUM, > -}; > - > #endif > diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c > index d09f8ce..3109c50 100644 > --- a/drivers/tpm/tpm_tis_lpc.c > +++ b/drivers/tpm/tpm_tis_lpc.c > @@ -15,6 +15,7 @@ > > #include > #include > +#include > #include > > #define PREFIX "lpc_tpm: " > @@ -426,9 +427,6 @@ int tis_open(void) > { > u8 locality = 0; /* we use locality zero for everything. */ > > - if (tis_close()) > - return TPM_DRIVER_ERR; > - > /* now request access to locality. */ > tpm_write_word(TIS_ACCESS_REQUEST_USE, &lpc_tpm_dev[locality].access); > > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h > index c744044..3eff895 100644 > --- a/include/dm/uclass-id.h > +++ b/include/dm/uclass-id.h > @@ -54,6 +54,7 @@ enum uclass_id { > UCLASS_SPI_GENERIC, /* Generic SPI flash target */ > UCLASS_SYSCON, /* System configuration device */ > UCLASS_THERMAL, /* Thermal sensor */ > + UCLASS_TPM, /* Trusted Platform Module TIS interface */ > UCLASS_USB, /* USB bus */ > UCLASS_USB_DEV_GENERIC, /* USB generic device */ > UCLASS_USB_HUB, /* USB hub */ > diff --git a/include/tis.h b/include/tis.h > index 40a1f86..1985d9e 100644 > --- a/include/tis.h > +++ b/include/tis.h > @@ -7,6 +7,8 @@ > #ifndef __TIS_H > #define __TIS_H > > +#ifndef CONFIG_DM_TPM > + > #include > > /* Low-level interface to access TPM */ > @@ -53,5 +55,6 @@ int tis_close(void); > */ > int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf, > size_t *recv_len); > +#endif > > #endif /* __TIS_H */ > diff --git a/include/tpm.h b/include/tpm.h > index 88aeba2..e4472d3 100644 > --- a/include/tpm.h > +++ b/include/tpm.h > @@ -15,6 +15,17 @@ > * Specification for definitions of TPM commands. > */ > > +#define TPM_HEADER_SIZE 10 > + > +enum tpm_duration { > + TPM_SHORT = 0, > + TPM_MEDIUM = 1, > + TPM_LONG = 2, > + TPM_UNDEFINED, > + > + TPM_DURATION_COUNT, > +}; > + > enum tpm_startup_type { > TPM_ST_CLEAR = 0x0001, > TPM_ST_STATE = 0x0002, > @@ -152,6 +163,187 @@ enum tpm_return_code { > TPM_DEFEND_LOCK_RUNNING = TPM_BASE + TPM_NON_FATAL + 3, > }; > > +#ifdef CONFIG_DM_TPM > + > +/* Max buffer size supported by our tpm */ > +#define TPM_DEV_BUFSIZE 1260 > + > +/** > + * struct tpm_chip_priv - Information about a TPM, stored by the uclass > + * > + * These values must be set up by the device's probe() method before > + * communcation is attempted. If the device has an xfer() method, this is > + * not needed. There is no need to set up @buf. > + * > + * @duration_ms: Length of each duration type in milliseconds > + * @retry_time_ms: Time to wait before retrying receive > + */ > +struct tpm_chip_priv { > + uint duration_ms[TPM_DURATION_COUNT]; > + uint retry_time_ms; > + u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)]; /* Max buffer size + addr */ > +}; > + > +/** > + * struct tpm_ops - low-level TPM operations > + * > + * These are designed to avoid loops and delays in the driver itself. These > + * should be handled in the uclass. > + * > + * In gneral you should implement everything except xfer(). Where you need > + * complete control of the transfer, then xfer() can be provided and will > + * override the other methods. > + * > + * This interface is for low-level TPM access. It does not understand the > + * concept of localities or the various TPM messages. That interface is > + * defined in the functions later on in this file, but they all translate > + * to bytes which are sent and received. > + */ > +struct tpm_ops { > + /** > + * open() - Request access to locality 0 for the caller > + * > + * After all commands have been completed the caller should call > + * close(). > + * > + * @dev: Device to close > + * @return 0 ok OK, -ve on error > + */ > + int (*open)(struct udevice *dev); > + > + /** > + * close() - Close the current session > + * > + * Releasing the locked locality. Returns 0 on success, -ve 1 on > + * failure (in case lock removal did not succeed). > + * > + * @dev: Device to close > + * @return 0 ok OK, -ve on error > + */ > + int (*close)(struct udevice *dev); > + > + /** > + * get_desc() - Get a text description of the TPM > + * > + * @dev: Device to check > + * @buf: Buffer to put the string > + * @size: Maximum size of buffer > + * @return length of string, or -ENOSPC it no space > + */ > + int (*get_desc)(struct udevice *dev, char *buf, int size); > + > + /** > + * send() - send data to the TPM > + * > + * @dev: Device to talk to > + * @sendbuf: Buffer of the data to send > + * @send_size: Size of the data to send > + * > + * Returns 0 on success or -ve on failure. > + */ > + int (*send)(struct udevice *dev, const uint8_t *sendbuf, > + size_t send_size); > + > + /** > + * recv() - receive a response from the TPM > + * > + * @dev: Device to talk to > + * @recvbuf: Buffer to save the response to > + * @max_size: Maximum number of bytes to receive > + * > + * Returns number of bytes received on success, -EAGAIN if the TPM > + * response is not ready, -EINTR if cancelled, or other -ve value on > + * failure. > + */ > + int (*recv)(struct udevice *dev, uint8_t *recvbuf, size_t max_size); > + > + /** > + * cleanup() - clean up after an operation in progress > + * > + * This is called if receiving times out. The TPM may need to abort > + * the current transaction if it did not complete, and make itself > + * ready for another. > + * > + * @dev: Device to talk to > + */ > + int (*cleanup)(struct udevice *dev); > + > + /** > + * xfer() - send data to the TPM and get response > + * > + * This method is optional. If it exists it is used in preference > + * to send(), recv() and cleanup(). It should handle all aspects of > + * TPM communication for a single transfer. > + * > + * @dev: Device to talk to > + * @sendbuf: Buffer of the data to send > + * @send_size: Size of the data to send > + * @recvbuf: Buffer to save the response to > + * @recv_size: Pointer to the size of the response buffer > + * > + * Returns 0 on success (and places the number of response bytes at > + * recv_size) or -ve on failure. > + */ > + int (*xfer)(struct udevice *dev, const uint8_t *sendbuf, > + size_t send_size, uint8_t *recvbuf, size_t *recv_size); > +}; > + > +#define tpm_get_ops(dev) ((struct tpm_ops *)device_get_ops(dev)) > + > +/** > + * tpm_open() - Request access to locality 0 for the caller > + * > + * After all commands have been completed the caller is supposed to > + * call tpm_close(). > + * > + * Returns 0 on success, -ve on failure. > + */ > +int tpm_open(struct udevice *dev); > + > +/** > + * tpm_close() - Close the current session > + * > + * Releasing the locked locality. Returns 0 on success, -ve 1 on > + * failure (in case lock removal did not succeed). > + */ > +int tpm_close(struct udevice *dev); > + > +/** > + * tpm_get_desc() - Get a text description of the TPM > + * > + * @dev: Device to check > + * @buf: Buffer to put the string > + * @size: Maximum size of buffer > + * @return length of string, or -ENOSPC it no space > + */ > +int tpm_get_desc(struct udevice *dev, char *buf, int size); > + > +/** > + * tpm_xfer() - send data to the TPM and get response > + * > + * This first uses the device's send() method to send the bytes. Then it calls > + * recv() to get the reply. If recv() returns -EAGAIN then it will delay a > + * short time and then call recv() again. > + * > + * Regardless of whether recv() completes successfully, it will then call > + * cleanup() to finish the transaction. > + * > + * Note that the outgoing data is inspected to determine command type > + * (ordinal) and a timeout is used for that command type. > + * > + * @sendbuf - buffer of the data to send > + * @send_size size of the data to send > + * @recvbuf - memory to save the response to > + * @recv_len - pointer to the size of the response buffer > + * > + * Returns 0 on success (and places the number of response bytes at > + * recv_len) or -ve on failure. > + */ > +int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size, > + uint8_t *recvbuf, size_t *recv_size); > + > +#endif /* CONFIG_DM_TPM */ > + > /** > * Initialize TPM device. It must be called before any TPM commands. > *