[U-Boot] [PATCH v2 15/28] dm: tpm: Add a uclass for Trusted Platform Modules
Christophe Ricard
christophe.ricard at gmail.com
Mon Aug 24 22:21:03 CEST 2015
Hi Simon,
This one looks good to me as well.
Acked-by: Christophe Ricard<christophe-h.ricard at st.com>
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 <sjg at chromium.org>
> ---
>
> 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 <sjg at chromium.org>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <tpm.h>
> +#include <linux/unaligned/be_byteshift.h>
> +#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 <fdtdec.h>
> #include <linux/compiler.h>
> #include <i2c.h>
> +#include <tis.h>
> #include <tpm.h>
> #include <asm-generic/errno.h>
> #include <linux/types.h>
> #include <linux/unaligned/be_byteshift.h>
>
> #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 <common.h>
> #include <asm/io.h>
> +#include <tis.h>
> #include <tpm.h>
>
> #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 <common.h>
>
> /* 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.
> *
More information about the U-Boot
mailing list