[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