[U-Boot] [PATCH v2 00/28] dm: Convert TPM drivers to driver model

This series adds driver model support for Trusted Platform Modules (TPMs). These have a very simple interface and are configured via the device tree.
Two bus types are supported at present: I2C and LPC (Intel Low-Pin-Count).
Most drivers and users are converted over to driver model. The exception is the Atmel TPM and its users.
The I2C driver has been cleaned up and simplified. It was ported from Linux and was pretty hard to follow. This series includes patches to unify the code, remove duplicated data structures and drop unnecessary indirection.
Also this series enables the TPM on all Chromebooks supported by upstream U-Boot (snow, spring, nyan-big, pit, pi, link, panther) since some did not have it fully enabled.
As before, the 'tpm' command can be used to implement TPM functionality. In addition a 'tpmtest' command provides some basic TPM tests taken from Chrome OS U-Boot. These are fairly rudimentary but are useful if you know what you are doing.
Changes in v2: - Add a 'TPM' menu in Kconfig - Add new patch with a 'tpmtest' command - Add new patch with functions to access flags and permissions - Add tpm device tree node for panther also - Correct error checking code in tpm_sendrecv_command() - Correct error-checking code in report_return_code() - Enable 'tpmtest' command for nyan - Enhance uclass to support timeouts with new send()/recv() methods - Implement the get_desc() method - Include tpm.h header file instead of tis.h - Move the timeout definitions into a new tpm_internal.h header - Update cover letter to mention panther and the tpmtest command. - Update driver for the new uclass interface - Update driver for v2 TPM uclass which supports timeouts - Use tpm_ prefix instead of tis_ for TPM functions
Simon Glass (28): tpm: Remove old pre-driver-model I2C code tpm: Drop two unused options tpm: Add Kconfig options for TPMs tpm: Convert board config TPM options to Kconfig tpm: Convert drivers to use SPDX tpm: Move the I2C TPM code into one file tpm: tpm_tis_i2c: Drop unnecessary methods tpm: tpm_tis_i2c: Drop struct tpm_vendor_specific tpm: tpm_tis_i2c: Merge struct tpm_dev into tpm_chip tpm: tpm_tis_i2c: Merge struct tpm into tpm_chip tpm: tpm_tis_i2c: Move definitions into the header file tpm: tpm_tis_i2c: Simplify init code tpm: tpm_tis_i2c: Use a consistent tpm_tis_i2c_ prefix tpm: tpm_tis_i2c: Tidy up delays dm: tpm: Add a uclass for Trusted Platform Modules dm: tpm: Convert the TPM command and library to driver model dm: i2c: Add a command to adjust the offset length tpm: Report tpm errors on the command line dm: tpm: sandbox: Convert TPM driver to driver model tpm: Check that parse_byte_string() has data to parse exynos: x86: dts: Add tpm nodes to the device tree for Chrome OS devices dm: tpm: Convert I2C driver to driver model dm: tpm: Convert LPC driver to driver model tpm: Add a 'tpm info' command tpm: Add functions to access flags and permissions dm: tpm: Add a 'tpmtest' command tpm: Enable 'tpmtest' command for Chrome OS boards with TPMs tegra: nyan: Enable TPM command and driver
README | 6 - arch/arm/dts/exynos5250-snow.dts | 9 + arch/arm/dts/exynos5250-spring.dts | 8 + arch/arm/dts/exynos5420-peach-pit.dts | 6 +- arch/arm/dts/exynos5800-peach-pi.dts | 6 +- arch/sandbox/dts/sandbox.dts | 4 + arch/x86/dts/chromebook_link.dts | 5 + arch/x86/dts/chromebox_panther.dts | 5 + common/Kconfig | 22 + common/Makefile | 1 + common/cmd_i2c.c | 33 + common/cmd_tpm.c | 100 ++- common/cmd_tpm_test.c | 565 +++++++++++++++++ configs/chromebook_link_defconfig | 5 + configs/chromebox_panther_defconfig | 5 + .../controlcenterd_36BIT_SDCARD_DEVELOP_defconfig | 4 + configs/controlcenterd_36BIT_SDCARD_defconfig | 4 + .../controlcenterd_TRAILBLAZER_DEVELOP_defconfig | 4 + configs/controlcenterd_TRAILBLAZER_defconfig | 4 + configs/coreboot-x86_defconfig | 5 + configs/nyan-big_defconfig | 5 + configs/peach-pi_defconfig | 5 + configs/peach-pit_defconfig | 5 + configs/sandbox_defconfig | 4 + configs/snow_defconfig | 5 + configs/spring_defconfig | 5 + drivers/tpm/Kconfig | 69 ++ drivers/tpm/Makefile | 4 +- drivers/tpm/tpm-uclass.c | 133 ++++ drivers/tpm/tpm.c | 694 --------------------- drivers/tpm/tpm_atmel_twi.c | 15 +- drivers/tpm/tpm_internal.h | 287 +++++++++ drivers/tpm/tpm_tis_i2c.c | 572 ++++++++--------- drivers/tpm/{tpm_private.h => tpm_tis_i2c.h} | 88 +-- drivers/tpm/tpm_tis_lpc.c | 290 ++++----- drivers/tpm/tpm_tis_sandbox.c | 57 +- include/configs/controlcenterd.h | 7 - include/configs/efi-x86.h | 2 - include/configs/exynos5-common.h | 7 - include/configs/x86-common.h | 2 - include/dm/uclass-id.h | 1 + include/fdtdec.h | 2 - include/tis.h | 3 + include/tpm.h | 243 +++++++- lib/Kconfig | 10 + lib/fdtdec.c | 2 - lib/tpm.c | 82 ++- 47 files changed, 2102 insertions(+), 1298 deletions(-) create mode 100644 common/cmd_tpm_test.c create mode 100644 drivers/tpm/tpm-uclass.c delete mode 100644 drivers/tpm/tpm.c create mode 100644 drivers/tpm/tpm_internal.h rename drivers/tpm/{tpm_private.h => tpm_tis_i2c.h} (54%)

This is not used anymore by any board so drop it.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com ---
Changes in v2: None
drivers/tpm/tpm.c | 108 ++-------------------------------------------- drivers/tpm/tpm_private.h | 4 +- drivers/tpm/tpm_tis_i2c.c | 74 +------------------------------ 3 files changed, 7 insertions(+), 179 deletions(-)
diff --git a/drivers/tpm/tpm.c b/drivers/tpm/tpm.c index a650892..24997f6 100644 --- a/drivers/tpm/tpm.c +++ b/drivers/tpm/tpm.c @@ -49,13 +49,7 @@ DECLARE_GLOBAL_DATA_PTR;
/* TPM configuration */ struct tpm { -#ifdef CONFIG_DM_I2C struct udevice *dev; -#else - int i2c_bus; - int slave_addr; - int old_bus; -#endif char inited; } tpm;
@@ -441,7 +435,6 @@ out: return rc; }
-#ifdef CONFIG_DM_I2C static int tpm_open_dev(struct udevice *dev) { int rc; @@ -449,24 +442,12 @@ static int tpm_open_dev(struct udevice *dev) debug("%s: start\n", __func__); if (g_chip.is_open) return -EBUSY; - rc = tpm_vendor_init_dev(dev); + rc = tpm_vendor_init(dev); if (rc < 0) g_chip.is_open = 0; return rc; } -#else -static int tpm_open(uint32_t dev_addr) -{ - int rc;
- if (g_chip.is_open) - return -EBUSY; - rc = tpm_vendor_init(dev_addr); - if (rc < 0) - g_chip.is_open = 0; - return rc; -} -#endif static void tpm_close(void) { if (g_chip.is_open) { @@ -475,42 +456,6 @@ static void tpm_close(void) } }
-static int tpm_select(void) -{ -#ifndef CONFIG_DM_I2C - int ret; - - tpm.old_bus = i2c_get_bus_num(); - if (tpm.old_bus != tpm.i2c_bus) { - ret = i2c_set_bus_num(tpm.i2c_bus); - if (ret) { - debug("%s: Fail to set i2c bus %d\n", __func__, - tpm.i2c_bus); - return -1; - } - } -#endif - return 0; -} - -static int tpm_deselect(void) -{ -#ifndef CONFIG_DM_I2C - int ret; - - if (tpm.old_bus != i2c_get_bus_num()) { - ret = i2c_set_bus_num(tpm.old_bus); - if (ret) { - debug("%s: Fail to restore i2c bus %d\n", - __func__, tpm.old_bus); - return -1; - } - } - tpm.old_bus = -1; -#endif - return 0; -} - /** * Decode TPM configuration. * @@ -520,8 +465,11 @@ static int tpm_deselect(void) static int tpm_decode_config(struct tpm *dev) { const void *blob = gd->fdt_blob; + struct udevice *bus; + int chip_addr; int parent; int node; + int ret;
node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); if (node < 0) { @@ -537,10 +485,6 @@ static int tpm_decode_config(struct tpm *dev) debug("%s: Cannot find node parent\n", __func__); return -1; } -#ifdef CONFIG_DM_I2C - struct udevice *bus; - int chip_addr; - int ret;
/* * TODO(sjg@chromium.org): Remove this when driver model supports @@ -569,15 +513,6 @@ static int tpm_decode_config(struct tpm *dev) fdt_get_name(blob, node, NULL), ret); return ret; } -#else - int i2c_bus; - - i2c_bus = i2c_get_bus_num_fdt(parent); - if (i2c_bus < 0) - return -1; - dev->i2c_bus = i2c_bus; - dev->slave_addr = fdtdec_get_addr(blob, node, "reg"); -#endif
return 0; } @@ -602,22 +537,6 @@ int tis_init(void) if (tpm_decode_config(&tpm)) return -1;
- if (tpm_select()) - return -1; - -#ifndef CONFIG_DM_I2C - /* - * Probe TPM twice; the first probing might fail because TPM is asleep, - * and the probing can wake up TPM. - */ - if (i2c_probe(tpm.slave_addr) && i2c_probe(tpm.slave_addr)) { - debug("%s: fail to probe i2c addr 0x%x\n", __func__, - tpm.slave_addr); - return -1; - } -#endif - - tpm_deselect(); debug("%s: done\n", __func__);
tpm.inited = 1; @@ -632,16 +551,7 @@ int tis_open(void) if (!tpm.inited) return -1;
- if (tpm_select()) - return -1; - -#ifdef CONFIG_DM_I2C rc = tpm_open_dev(tpm.dev); -#else - rc = tpm_open(tpm.slave_addr); -#endif - - tpm_deselect();
return rc; } @@ -651,13 +561,8 @@ int tis_close(void) if (!tpm.inited) return -1;
- if (tpm_select()) - return -1; - tpm_close();
- tpm_deselect(); - return 0; }
@@ -675,13 +580,8 @@ int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
memcpy(buf, sendbuf, sbuf_size);
- if (tpm_select()) - return -1; - len = tpm_transmit(buf, sbuf_size);
- tpm_deselect(); - if (len < 10) { *rbuf_len = 0; return -1; diff --git a/drivers/tpm/tpm_private.h b/drivers/tpm/tpm_private.h index 8894c98..daaf8b8 100644 --- a/drivers/tpm/tpm_private.h +++ b/drivers/tpm/tpm_private.h @@ -129,10 +129,8 @@ struct tpm_cmd_t {
struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *);
-int tpm_vendor_init(uint32_t dev_addr); - struct udevice; -int tpm_vendor_init_dev(struct udevice *dev); +int tpm_vendor_init(struct udevice *dev);
void tpm_vendor_cleanup(struct tpm_chip *chip);
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index cc740e9..b6eaef1 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -50,9 +50,6 @@
DECLARE_GLOBAL_DATA_PTR;
-/* Address of the TPM on the I2C bus */ -#define TPM_I2C_ADDR 0x20 - /* Max buffer size supported by our tpm */ #define TPM_DEV_BUFSIZE 1260
@@ -73,13 +70,6 @@ DECLARE_GLOBAL_DATA_PTR;
#define TPM_HEADER_SIZE 10
-/* - * Expected value for DIDVID register - * - * The only device the system knows about at this moment is Infineon slb9635. - */ -#define TPM_TIS_I2C_DID_VID 0x000b15d1L - enum tis_access { TPM_ACCESS_VALID = 0x80, TPM_ACCESS_ACTIVE_LOCALITY = 0x20, @@ -123,21 +113,11 @@ static const char * const chip_name[] = {
/* Structure to store I2C TPM specific stuff */ struct tpm_dev { -#ifdef CONFIG_DM_I2C struct udevice *dev; -#else - uint addr; -#endif u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)]; /* Max buffer size + addr */ enum i2c_chip_type chip_type; };
-static struct tpm_dev tpm_dev = { -#ifndef CONFIG_DM_I2C - .addr = TPM_I2C_ADDR -#endif -}; - static struct tpm_dev tpm_dev;
/* @@ -163,12 +143,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) if ((tpm_dev.chip_type == SLB9635) || (tpm_dev.chip_type == UNKNOWN)) { /* slb9635 protocol should work in both cases */ for (count = 0; count < MAX_COUNT; count++) { -#ifdef CONFIG_DM_I2C rc = dm_i2c_write(tpm_dev.dev, 0, (uchar *)&addrbuf, 1); -#else - rc = i2c_write(tpm_dev.addr, 0, 0, - (uchar *)&addrbuf, 1); -#endif if (rc == 0) break; /* Success, break to skip sleep */ udelay(SLEEP_DURATION); @@ -182,11 +157,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) */ for (count = 0; count < MAX_COUNT; count++) { udelay(SLEEP_DURATION); -#ifdef CONFIG_DM_I2C rc = dm_i2c_read(tpm_dev.dev, 0, buffer, len); -#else - rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len); -#endif if (rc == 0) break; /* success, break to skip sleep */ } @@ -199,11 +170,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) * be safe on the safe side. */ for (count = 0; count < MAX_COUNT; count++) { -#ifdef CONFIG_DM_I2C rc = dm_i2c_read(tpm_dev.dev, addr, buffer, len); -#else - rc = i2c_read(tpm_dev.addr, addr, 1, buffer, len); -#endif if (rc == 0) break; /* break here to skip sleep */ udelay(SLEEP_DURATION); @@ -224,20 +191,8 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, int rc = 0; int count;
- /* Prepare send buffer */ -#ifndef CONFIG_DM_I2C - tpm_dev.buf[0] = addr; - memcpy(&(tpm_dev.buf[1]), buffer, len); - buffer = tpm_dev.buf; - len++; -#endif - for (count = 0; count < max_count; count++) { -#ifdef CONFIG_DM_I2C rc = dm_i2c_write(tpm_dev.dev, addr, buffer, len); -#else - rc = i2c_write(tpm_dev.addr, 0, 0, buffer, len); -#endif if (rc == 0) break; /* Success, break to skip sleep */ udelay(sleep_time); @@ -597,12 +552,13 @@ static enum i2c_chip_type tpm_vendor_chip_type(void) return UNKNOWN; }
-static int tpm_vendor_init_common(void) +int tpm_vendor_init(struct udevice *dev) { struct tpm_chip *chip; u32 vendor; u32 expected_did_vid;
+ tpm_dev.dev = dev; tpm_dev.chip_type = tpm_vendor_chip_type();
chip = tpm_register_hardware(&tpm_tis_i2c); @@ -651,32 +607,6 @@ static int tpm_vendor_init_common(void) return 0; }
-#ifdef CONFIG_DM_I2C -/* Initialisation of i2c tpm */ -int tpm_vendor_init_dev(struct udevice *dev) -{ - tpm_dev.dev = dev; - return tpm_vendor_init_common(); -} -#else -/* Initialisation of i2c tpm */ -int tpm_vendor_init(uint32_t dev_addr) -{ - uint old_addr; - int rc = 0; - - old_addr = tpm_dev.addr; - if (dev_addr != 0) - tpm_dev.addr = dev_addr; - - rc = tpm_vendor_init_common(); - if (rc) - tpm_dev.addr = old_addr; - - return rc; -} -#endif - void tpm_vendor_cleanup(struct tpm_chip *chip) { release_locality(chip, chip->vendor.locality, 1);

Hello Simon,
Am 23.08.2015 um 02:31 schrieb Simon Glass:
This is not used anymore by any board so drop it.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2: None
drivers/tpm/tpm.c | 108 ++-------------------------------------------- drivers/tpm/tpm_private.h | 4 +- drivers/tpm/tpm_tis_i2c.c | 74 +------------------------------ 3 files changed, 7 insertions(+), 179 deletions(-)
Thanks for your work! Nitpick ...
$ grep -lr CONFIG_TPM_TIS_I2C include/configs/ include/configs/exynos5-common.h
So I miss the removal of this define there and maybe remove it in drivers/tpm/Makefile ...
Beside of this ...
Reviewed-by: Heiko Schocher hs@denx.de
bye, Heiko
diff --git a/drivers/tpm/tpm.c b/drivers/tpm/tpm.c index a650892..24997f6 100644 --- a/drivers/tpm/tpm.c +++ b/drivers/tpm/tpm.c @@ -49,13 +49,7 @@ DECLARE_GLOBAL_DATA_PTR;
/* TPM configuration */ struct tpm { -#ifdef CONFIG_DM_I2C struct udevice *dev; -#else
- int i2c_bus;
- int slave_addr;
- int old_bus;
-#endif char inited; } tpm;
@@ -441,7 +435,6 @@ out: return rc; }
-#ifdef CONFIG_DM_I2C static int tpm_open_dev(struct udevice *dev) { int rc; @@ -449,24 +442,12 @@ static int tpm_open_dev(struct udevice *dev) debug("%s: start\n", __func__); if (g_chip.is_open) return -EBUSY;
- rc = tpm_vendor_init_dev(dev);
- rc = tpm_vendor_init(dev); if (rc < 0) g_chip.is_open = 0; return rc; }
-#else -static int tpm_open(uint32_t dev_addr) -{
int rc;
if (g_chip.is_open)
return -EBUSY;
rc = tpm_vendor_init(dev_addr);
if (rc < 0)
g_chip.is_open = 0;
return rc;
-} -#endif static void tpm_close(void) { if (g_chip.is_open) { @@ -475,42 +456,6 @@ static void tpm_close(void) } }
-static int tpm_select(void) -{ -#ifndef CONFIG_DM_I2C
- int ret;
- tpm.old_bus = i2c_get_bus_num();
- if (tpm.old_bus != tpm.i2c_bus) {
ret = i2c_set_bus_num(tpm.i2c_bus);
if (ret) {
debug("%s: Fail to set i2c bus %d\n", __func__,
tpm.i2c_bus);
return -1;
}
- }
-#endif
- return 0;
-}
-static int tpm_deselect(void) -{ -#ifndef CONFIG_DM_I2C
- int ret;
- if (tpm.old_bus != i2c_get_bus_num()) {
ret = i2c_set_bus_num(tpm.old_bus);
if (ret) {
debug("%s: Fail to restore i2c bus %d\n",
__func__, tpm.old_bus);
return -1;
}
- }
- tpm.old_bus = -1;
-#endif
- return 0;
-}
- /**
- Decode TPM configuration.
@@ -520,8 +465,11 @@ static int tpm_deselect(void) static int tpm_decode_config(struct tpm *dev) { const void *blob = gd->fdt_blob;
struct udevice *bus;
int chip_addr; int parent; int node;
int ret;
node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); if (node < 0) {
@@ -537,10 +485,6 @@ static int tpm_decode_config(struct tpm *dev) debug("%s: Cannot find node parent\n", __func__); return -1; } -#ifdef CONFIG_DM_I2C
struct udevice *bus;
int chip_addr;
int ret;
/*
- TODO(sjg@chromium.org): Remove this when driver model supports
@@ -569,15 +513,6 @@ static int tpm_decode_config(struct tpm *dev) fdt_get_name(blob, node, NULL), ret); return ret; } -#else
- int i2c_bus;
- i2c_bus = i2c_get_bus_num_fdt(parent);
- if (i2c_bus < 0)
return -1;
- dev->i2c_bus = i2c_bus;
- dev->slave_addr = fdtdec_get_addr(blob, node, "reg");
-#endif
return 0; } @@ -602,22 +537,6 @@ int tis_init(void) if (tpm_decode_config(&tpm)) return -1;
- if (tpm_select())
return -1;
-#ifndef CONFIG_DM_I2C
- /*
* Probe TPM twice; the first probing might fail because TPM is asleep,
* and the probing can wake up TPM.
*/
- if (i2c_probe(tpm.slave_addr) && i2c_probe(tpm.slave_addr)) {
debug("%s: fail to probe i2c addr 0x%x\n", __func__,
tpm.slave_addr);
return -1;
- }
-#endif
tpm_deselect(); debug("%s: done\n", __func__);
tpm.inited = 1;
@@ -632,16 +551,7 @@ int tis_open(void) if (!tpm.inited) return -1;
- if (tpm_select())
return -1;
-#ifdef CONFIG_DM_I2C rc = tpm_open_dev(tpm.dev); -#else
- rc = tpm_open(tpm.slave_addr);
-#endif
tpm_deselect();
return rc; }
@@ -651,13 +561,8 @@ int tis_close(void) if (!tpm.inited) return -1;
if (tpm_select())
return -1;
tpm_close();
tpm_deselect();
return 0; }
@@ -675,13 +580,8 @@ int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
memcpy(buf, sendbuf, sbuf_size);
if (tpm_select())
return -1;
len = tpm_transmit(buf, sbuf_size);
tpm_deselect();
if (len < 10) { *rbuf_len = 0; return -1;
diff --git a/drivers/tpm/tpm_private.h b/drivers/tpm/tpm_private.h index 8894c98..daaf8b8 100644 --- a/drivers/tpm/tpm_private.h +++ b/drivers/tpm/tpm_private.h @@ -129,10 +129,8 @@ struct tpm_cmd_t {
struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *);
-int tpm_vendor_init(uint32_t dev_addr);
- struct udevice;
-int tpm_vendor_init_dev(struct udevice *dev); +int tpm_vendor_init(struct udevice *dev);
void tpm_vendor_cleanup(struct tpm_chip *chip);
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index cc740e9..b6eaef1 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -50,9 +50,6 @@
DECLARE_GLOBAL_DATA_PTR;
-/* Address of the TPM on the I2C bus */ -#define TPM_I2C_ADDR 0x20
- /* Max buffer size supported by our tpm */ #define TPM_DEV_BUFSIZE 1260
@@ -73,13 +70,6 @@ DECLARE_GLOBAL_DATA_PTR;
#define TPM_HEADER_SIZE 10
-/*
- Expected value for DIDVID register
- The only device the system knows about at this moment is Infineon slb9635.
- */
-#define TPM_TIS_I2C_DID_VID 0x000b15d1L
- enum tis_access { TPM_ACCESS_VALID = 0x80, TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
@@ -123,21 +113,11 @@ static const char * const chip_name[] = {
/* Structure to store I2C TPM specific stuff */ struct tpm_dev { -#ifdef CONFIG_DM_I2C struct udevice *dev; -#else
- uint addr;
-#endif u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)]; /* Max buffer size + addr */ enum i2c_chip_type chip_type; };
-static struct tpm_dev tpm_dev = { -#ifndef CONFIG_DM_I2C
- .addr = TPM_I2C_ADDR
-#endif -};
static struct tpm_dev tpm_dev;
/*
@@ -163,12 +143,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) if ((tpm_dev.chip_type == SLB9635) || (tpm_dev.chip_type == UNKNOWN)) { /* slb9635 protocol should work in both cases */ for (count = 0; count < MAX_COUNT; count++) { -#ifdef CONFIG_DM_I2C rc = dm_i2c_write(tpm_dev.dev, 0, (uchar *)&addrbuf, 1); -#else
rc = i2c_write(tpm_dev.addr, 0, 0,
(uchar *)&addrbuf, 1);
-#endif if (rc == 0) break; /* Success, break to skip sleep */ udelay(SLEEP_DURATION); @@ -182,11 +157,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) */ for (count = 0; count < MAX_COUNT; count++) { udelay(SLEEP_DURATION); -#ifdef CONFIG_DM_I2C rc = dm_i2c_read(tpm_dev.dev, 0, buffer, len); -#else
rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len);
-#endif if (rc == 0) break; /* success, break to skip sleep */ } @@ -199,11 +170,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) * be safe on the safe side. */ for (count = 0; count < MAX_COUNT; count++) { -#ifdef CONFIG_DM_I2C rc = dm_i2c_read(tpm_dev.dev, addr, buffer, len); -#else
rc = i2c_read(tpm_dev.addr, addr, 1, buffer, len);
-#endif if (rc == 0) break; /* break here to skip sleep */ udelay(SLEEP_DURATION); @@ -224,20 +191,8 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, int rc = 0; int count;
- /* Prepare send buffer */
-#ifndef CONFIG_DM_I2C
- tpm_dev.buf[0] = addr;
- memcpy(&(tpm_dev.buf[1]), buffer, len);
- buffer = tpm_dev.buf;
- len++;
-#endif
- for (count = 0; count < max_count; count++) {
-#ifdef CONFIG_DM_I2C rc = dm_i2c_write(tpm_dev.dev, addr, buffer, len); -#else
rc = i2c_write(tpm_dev.addr, 0, 0, buffer, len);
-#endif if (rc == 0) break; /* Success, break to skip sleep */ udelay(sleep_time); @@ -597,12 +552,13 @@ static enum i2c_chip_type tpm_vendor_chip_type(void) return UNKNOWN; }
-static int tpm_vendor_init_common(void) +int tpm_vendor_init(struct udevice *dev) { struct tpm_chip *chip; u32 vendor; u32 expected_did_vid;
tpm_dev.dev = dev; tpm_dev.chip_type = tpm_vendor_chip_type();
chip = tpm_register_hardware(&tpm_tis_i2c);
@@ -651,32 +607,6 @@ static int tpm_vendor_init_common(void) return 0; }
-#ifdef CONFIG_DM_I2C -/* Initialisation of i2c tpm */ -int tpm_vendor_init_dev(struct udevice *dev) -{
- tpm_dev.dev = dev;
- return tpm_vendor_init_common();
-} -#else -/* Initialisation of i2c tpm */ -int tpm_vendor_init(uint32_t dev_addr) -{
- uint old_addr;
- int rc = 0;
- old_addr = tpm_dev.addr;
- if (dev_addr != 0)
tpm_dev.addr = dev_addr;
- rc = tpm_vendor_init_common();
- if (rc)
tpm_dev.addr = old_addr;
- return rc;
-} -#endif
- void tpm_vendor_cleanup(struct tpm_chip *chip) { release_locality(chip, chip->vendor.locality, 1);

Hi Heiko,
On 23 August 2015 at 22:50, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 23.08.2015 um 02:31 schrieb Simon Glass:
This is not used anymore by any board so drop it.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2: None
drivers/tpm/tpm.c | 108 ++-------------------------------------------- drivers/tpm/tpm_private.h | 4 +- drivers/tpm/tpm_tis_i2c.c | 74 +------------------------------ 3 files changed, 7 insertions(+), 179 deletions(-)
Thanks for your work! Nitpick ...
$ grep -lr CONFIG_TPM_TIS_I2C include/configs/ include/configs/exynos5-common.h
So I miss the removal of this define there and maybe remove it in drivers/tpm/Makefile ...
Beside of this ...
Reviewed-by: Heiko Schocher hs@denx.de
The driver still exists though - I am just removing part of the code. Or do I misunderstand what you are getting at?
[snip]
Regards, Simon

Hello Simon,
Am 24.08.2015 um 06:52 schrieb Simon Glass:
Hi Heiko,
On 23 August 2015 at 22:50, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 23.08.2015 um 02:31 schrieb Simon Glass:
This is not used anymore by any board so drop it.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2: None
drivers/tpm/tpm.c | 108 ++-------------------------------------------- drivers/tpm/tpm_private.h | 4 +- drivers/tpm/tpm_tis_i2c.c | 74 +------------------------------ 3 files changed, 7 insertions(+), 179 deletions(-)
Thanks for your work! Nitpick ...
$ grep -lr CONFIG_TPM_TIS_I2C include/configs/ include/configs/exynos5-common.h
So I miss the removal of this define there and maybe remove it in drivers/tpm/Makefile ...
Beside of this ...
Reviewed-by: Heiko Schocher hs@denx.de
The driver still exists though - I am just removing part of the code. Or do I misunderstand what you are getting at?
Huh... seems to early ... I thought you remove the complete driver, Sorry ... all is fine.
I looked through your patchserie, seems fine to me, so, you can add my Reviewed-by: Heiko Schocher hs@denx.de for the hole series.
Thanks!
bye, Heiko

Hi Heiko,
On 23 August 2015 at 23:15, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 24.08.2015 um 06:52 schrieb Simon Glass:
Hi Heiko,
On 23 August 2015 at 22:50, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 23.08.2015 um 02:31 schrieb Simon Glass:
This is not used anymore by any board so drop it.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2: None
drivers/tpm/tpm.c | 108 ++-------------------------------------------- drivers/tpm/tpm_private.h | 4 +- drivers/tpm/tpm_tis_i2c.c | 74 +------------------------------ 3 files changed, 7 insertions(+), 179 deletions(-)
Thanks for your work! Nitpick ...
$ grep -lr CONFIG_TPM_TIS_I2C include/configs/ include/configs/exynos5-common.h
So I miss the removal of this define there and maybe remove it in drivers/tpm/Makefile ...
Beside of this ...
Reviewed-by: Heiko Schocher hs@denx.de
The driver still exists though - I am just removing part of the code. Or do I misunderstand what you are getting at?
Huh... seems to early ... I thought you remove the complete driver, Sorry ... all is fine.
I looked through your patchserie, seems fine to me, so, you can add my Reviewed-by: Heiko Schocher hs@denx.de for the hole series.
OK done, thanks for taking a look. Christophe has some additions to come but this is a good base. I'm going to apply this series to u-boot-dm and get it in now. The I2C driver needs to be renamed to infineon, will deal with that later.
Applied to u-boot-dm.

The address of the I2C TPM is now defined in the device tree so there is no need for the CONFIG options.
Remove them from the README and board config to avoid confusion.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com ---
Changes in v2: None
README | 6 ------ include/configs/exynos5-common.h | 2 -- 2 files changed, 8 deletions(-)
diff --git a/README b/README index a52ff46..1acc355 100644 --- a/README +++ b/README @@ -1494,12 +1494,6 @@ The following options need to be configured: Support for i2c bus TPM devices. Only one device per system is supported at this time.
- CONFIG_TPM_TIS_I2C_BUS_NUMBER - Define the the i2c bus number for the TPM device - - CONFIG_TPM_TIS_I2C_SLAVE_ADDRESS - Define the TPM's address on the i2c bus - CONFIG_TPM_TIS_I2C_BURST_LIMITATION Define the burst count bytes upper limit
diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index e710f41..fb5ee0d 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -58,8 +58,6 @@ #define CONFIG_TPM #define CONFIG_CMD_TPM #define CONFIG_TPM_TIS_I2C -#define CONFIG_TPM_TIS_I2C_BUS_NUMBER 3 -#define CONFIG_TPM_TIS_I2C_SLAVE_ADDR 0x20
/* MMC SPL */ #define COPY_BL2_FNPTR_ADDR 0x02020030

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
The address of the I2C TPM is now defined in the device tree so there is no need for the CONFIG options.
Remove them from the README and board config to avoid confusion.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2: None
README | 6 ------ include/configs/exynos5-common.h | 2 -- 2 files changed, 8 deletions(-)
Applied to u-boot-dm.

Add new Kconfig options for TPMs in preparation for moving boards to use Kconfig for TPM configuration.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add a 'TPM' menu in Kconfig
common/Kconfig | 12 +++++++++++ drivers/tpm/Kconfig | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/Kconfig | 10 +++++++++ 3 files changed, 82 insertions(+)
diff --git a/common/Kconfig b/common/Kconfig index 88dc016..bacc4e0 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -625,4 +625,16 @@ config CMD_REGULATOR
endmenu
+menu "Security commands" +config CMD_TPM + bool "Enable the 'tpm' command" + depends on TPM + help + This provides a means to talk to a TPM from the command line. A wide + range of commands if provided - see 'tpm help' for details. The + command requires a suitable TPM on your board and the correct driver + must be enabled. + +endmenu + endmenu diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig index f408b8a..9101fc2 100644 --- a/drivers/tpm/Kconfig +++ b/drivers/tpm/Kconfig @@ -1,7 +1,67 @@ +# +# TPM subsystem configuration +# + +menu "TPM support" + config TPM_TIS_SANDBOX bool "Enable sandbox TPM driver" + depends on SANDBOX help This driver emulates a TPM, providing access to base functions such as reading and writing TPM private data. This is enough to support Chrome OS verified boot. Extend functionality is not implemented. + +config TPM_ATMEL_TWI + bool "Enable Atmel TWI TPM device driver" + depends on TPM + help + This driver supports an Atmel TPM device connected on the I2C bus. + The usual tpm operations and the 'tpm' command can be used to talk + to the device using the standard TPM Interface Specification (TIS) + protocol + +config TPM_TIS_I2C + bool "Enable support for Infineon SLB9635/45 TPMs on I2C" + depends on TPM && DM_I2C + help + This driver supports Infineon TPM devices connected on the I2C bus. + The usual tpm operations and the 'tpm' command can be used to talk + to the device using the standard TPM Interface Specification (TIS) + protocol + +config TPM_TIS_I2C_BURST_LIMITATION + bool "Enable I2C burst length limitation" + depends on TPM_TIS_I2C + help + Some broken TPMs have a limitation on the number of bytes they can + receive in one message. Enable this option to allow you to set this + option. The can allow a broken TPM to be used by splitting messages + into separate pieces. + +config TPM_TIS_I2C_BURST_LIMITATION_LEN + int "Length" + depends on TPM_TIS_I2C_BURST_LIMITATION + help + Use this to set the burst limitation length + +config TPM_TIS_LPC + bool "Enable support for Infineon SLB9635/45 TPMs on LPC" + depends on TPM && X86 + help + This driver supports Infineon TPM devices connected on the I2C bus. + The usual tpm operations and the 'tpm' command can be used to talk + to the device using the standard TPM Interface Specification (TIS) + protocol + +config TPM_AUTH_SESSIONS + bool "Enable TPM authentication session support" + depends on TPM + help + Enable support for authorised (AUTH1) commands as specified in the + TCG Main Specification 1.2. OIAP-authorised versions of the commands + TPM_LoadKey2 and TPM_GetPubKey are provided. Both features are + available using the 'tpm' command, too. + +endmenu diff --git a/lib/Kconfig b/lib/Kconfig index 884218a..0673072 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -54,6 +54,16 @@ source lib/dhry/Kconfig
source lib/rsa/Kconfig
+config TPM + bool "Trusted Platform Module (TPM) Support" + help + This enables support for TPMs which can be used to provide security + features for your board. The TPM can be connected via LPC or I2C + and a sandbox TPM is provided for testing purposes. Use the 'tpm' + command to interactive the TPM. Driver model support is provided + for the low-level TPM interface, but only one TPM is supported at + a time by the TPM library. + menu "Hashing Support"
config SHA1

Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
Add new Kconfig options for TPMs in preparation for moving boards to use Kconfig for TPM configuration.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
Add a 'TPM' menu in Kconfig
common/Kconfig | 12 +++++++++++ drivers/tpm/Kconfig | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/Kconfig | 10 +++++++++ 3 files changed, 82 insertions(+)
diff --git a/common/Kconfig b/common/Kconfig index 88dc016..bacc4e0 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -625,4 +625,16 @@ config CMD_REGULATOR
endmenu
+menu "Security commands" +config CMD_TPM
- bool "Enable the 'tpm' command"
- depends on TPM
- help
This provides a means to talk to a TPM from the command line. A wide
range of commands if provided - see 'tpm help' for details. The
command requires a suitable TPM on your board and the correct driver
must be enabled.
+endmenu
- endmenu
diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig index f408b8a..9101fc2 100644 --- a/drivers/tpm/Kconfig +++ b/drivers/tpm/Kconfig @@ -1,7 +1,67 @@ +# +# TPM subsystem configuration +#
+menu "TPM support"
- config TPM_TIS_SANDBOX bool "Enable sandbox TPM driver"
- depends on SANDBOX help This driver emulates a TPM, providing access to base functions such as reading and writing TPM private data. This is enough to support Chrome OS verified boot. Extend functionality is not implemented.
+config TPM_ATMEL_TWI
- bool "Enable Atmel TWI TPM device driver"
- depends on TPM
- help
This driver supports an Atmel TPM device connected on the I2C bus.
The usual tpm operations and the 'tpm' command can be used to talk
to the device using the standard TPM Interface Specification (TIS)
protocol
+config TPM_TIS_I2C
- bool "Enable support for Infineon SLB9635/45 TPMs on I2C"
- depends on TPM && DM_I2C
- help
This driver supports Infineon TPM devices connected on the I2C bus.
The usual tpm operations and the 'tpm' command can be used to talk
to the device using the standard TPM Interface Specification (TIS)
protocol
+config TPM_TIS_I2C_BURST_LIMITATION
- bool "Enable I2C burst length limitation"
- depends on TPM_TIS_I2C
- help
Some broken TPMs have a limitation on the number of bytes they can
receive in one message. Enable this option to allow you to set this
option. The can allow a broken TPM to be used by splitting messages
into separate pieces.
+config TPM_TIS_I2C_BURST_LIMITATION_LEN
- int "Length"
- depends on TPM_TIS_I2C_BURST_LIMITATION
- help
Use this to set the burst limitation length
+config TPM_TIS_LPC
- bool "Enable support for Infineon SLB9635/45 TPMs on LPC"
- depends on TPM && X86
- help
This driver supports Infineon TPM devices connected on the I2C bus.
The usual tpm operations and the 'tpm' command can be used to talk
to the device using the standard TPM Interface Specification (TIS)
protocol
+config TPM_AUTH_SESSIONS
- bool "Enable TPM authentication session support"
- depends on TPM
- help
Enable support for authorised (AUTH1) commands as specified in the
TCG Main Specification 1.2. OIAP-authorised versions of the commands
TPM_LoadKey2 and TPM_GetPubKey are provided. Both features are
available using the 'tpm' command, too.
+endmenu diff --git a/lib/Kconfig b/lib/Kconfig index 884218a..0673072 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -54,6 +54,16 @@ source lib/dhry/Kconfig
source lib/rsa/Kconfig
+config TPM
bool "Trusted Platform Module (TPM) Support"
help
This enables support for TPMs which can be used to provide security
features for your board. The TPM can be connected via LPC or I2C
and a sandbox TPM is provided for testing purposes. Use the 'tpm'
command to interactive the TPM. Driver model support is provided
for the low-level TPM interface, but only one TPM is supported at
a time by the TPM library.
menu "Hashing Support"
config SHA1

On 24 August 2015 at 14:24, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

Convert all TPM options to Kconfig and tidy up.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com ---
Changes in v2: None
configs/chromebook_link_defconfig | 2 ++ configs/chromebox_panther_defconfig | 2 ++ configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig | 4 ++++ configs/controlcenterd_36BIT_SDCARD_defconfig | 4 ++++ configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig | 4 ++++ configs/controlcenterd_TRAILBLAZER_defconfig | 4 ++++ configs/coreboot-x86_defconfig | 2 ++ configs/peach-pi_defconfig | 3 +++ configs/peach-pit_defconfig | 3 +++ configs/sandbox_defconfig | 2 ++ configs/snow_defconfig | 3 +++ configs/spring_defconfig | 3 +++ include/configs/controlcenterd.h | 7 ------- include/configs/efi-x86.h | 2 -- include/configs/exynos5-common.h | 5 ----- include/configs/x86-common.h | 2 -- 16 files changed, 36 insertions(+), 16 deletions(-)
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index b987f3f..b0fc5ca 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -17,9 +17,11 @@ CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_TPM_TIS_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y CONFIG_DM_RTC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y +CONFIG_TPM=y diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index e82c8ec..e7ef8fe 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -17,9 +17,11 @@ CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_TPM_TIS_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y CONFIG_DM_RTC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y +CONFIG_TPM=y diff --git a/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig b/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig index 37ead03..c8ab862 100644 --- a/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig +++ b/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig @@ -4,4 +4,8 @@ CONFIG_TARGET_CONTROLCENTERD=y CONFIG_SYS_EXTRA_OPTIONS="36BIT,SDCARD,DEVELOP" # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y +CONFIG_TPM_ATMEL_TWI=y +CONFIG_TPM_AUTH_SESSIONS=y +CONFIG_TPM=y diff --git a/configs/controlcenterd_36BIT_SDCARD_defconfig b/configs/controlcenterd_36BIT_SDCARD_defconfig index 7166edb..21c0eab 100644 --- a/configs/controlcenterd_36BIT_SDCARD_defconfig +++ b/configs/controlcenterd_36BIT_SDCARD_defconfig @@ -4,4 +4,8 @@ CONFIG_TARGET_CONTROLCENTERD=y CONFIG_SYS_EXTRA_OPTIONS="36BIT,SDCARD" # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y +CONFIG_TPM_ATMEL_TWI=y +CONFIG_TPM_AUTH_SESSIONS=y +CONFIG_TPM=y diff --git a/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig b/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig index d99fcd4..c3a0920 100644 --- a/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig +++ b/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig @@ -6,3 +6,7 @@ CONFIG_SYS_EXTRA_OPTIONS="TRAILBLAZER,SPIFLASH,DEVELOP" # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TPM=y +CONFIG_TPM_ATMEL_TWI=y +CONFIG_TPM_AUTH_SESSIONS=y +CONFIG_TPM=y diff --git a/configs/controlcenterd_TRAILBLAZER_defconfig b/configs/controlcenterd_TRAILBLAZER_defconfig index 3557aea..08aae9a 100644 --- a/configs/controlcenterd_TRAILBLAZER_defconfig +++ b/configs/controlcenterd_TRAILBLAZER_defconfig @@ -6,3 +6,7 @@ CONFIG_SYS_EXTRA_OPTIONS="TRAILBLAZER,SPIFLASH" # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TPM=y +CONFIG_TPM_ATMEL_TWI=y +CONFIG_TPM_AUTH_SESSIONS=y +CONFIG_TPM=y diff --git a/configs/coreboot-x86_defconfig b/configs/coreboot-x86_defconfig index df3a624..66b8caa 100644 --- a/configs/coreboot-x86_defconfig +++ b/configs/coreboot-x86_defconfig @@ -14,5 +14,7 @@ CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_NETDEVICES=y CONFIG_E1000=y +CONFIG_TPM_TIS_LPC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y +CONFIG_TPM=y diff --git a/configs/peach-pi_defconfig b/configs/peach-pi_defconfig index 323a2d3..2be74fd 100644 --- a/configs/peach-pi_defconfig +++ b/configs/peach-pi_defconfig @@ -7,11 +7,13 @@ CONFIG_SPL=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_SPI=y CONFIG_CROS_EC_KEYB=y +CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y CONFIG_I2C_CROS_EC_TUNNEL=y @@ -30,5 +32,6 @@ CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_TPM=y CONFIG_ERRNO_STR=y CONFIG_SYS_PROMPT="Peach-Pi # " diff --git a/configs/peach-pit_defconfig b/configs/peach-pit_defconfig index 6a08296..875ddd1 100644 --- a/configs/peach-pit_defconfig +++ b/configs/peach-pit_defconfig @@ -7,11 +7,13 @@ CONFIG_SPL=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_SPI=y CONFIG_CROS_EC_KEYB=y +CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y CONFIG_I2C_CROS_EC_TUNNEL=y @@ -30,5 +32,6 @@ CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_TPM=y CONFIG_ERRNO_STR=y CONFIG_SYS_PROMPT="Peach-Pit # " diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 85ff95d..b68d688 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -11,6 +11,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y CONFIG_OF_CONTROL=y CONFIG_OF_HOSTFILE=y CONFIG_CLK=y @@ -49,6 +50,7 @@ CONFIG_DM_MMC=y CONFIG_DM_RTC=y CONFIG_SYS_VSNPRINTF=y CONFIG_CMD_DHRYSTONE=y +CONFIG_TPM=y CONFIG_ERRNO_STR=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y diff --git a/configs/snow_defconfig b/configs/snow_defconfig index f5decd5..f59aa3f 100644 --- a/configs/snow_defconfig +++ b/configs/snow_defconfig @@ -8,6 +8,7 @@ CONFIG_SPL=y CONFIG_CMD_SOUND=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y @@ -17,6 +18,7 @@ CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_S5P=y CONFIG_DEBUG_UART_BASE=0x12c30000 CONFIG_DEBUG_UART_CLOCK=100000000 +CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y CONFIG_I2C_CROS_EC_LDO=y @@ -41,4 +43,5 @@ CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_TPM=y CONFIG_ERRNO_STR=y diff --git a/configs/spring_defconfig b/configs/spring_defconfig index f1d9a58..6144f03 100644 --- a/configs/spring_defconfig +++ b/configs/spring_defconfig @@ -8,6 +8,7 @@ CONFIG_SPL=y CONFIG_CMD_SOUND=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y @@ -17,6 +18,7 @@ CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_S5P=y CONFIG_DEBUG_UART_BASE=0x12c30000 CONFIG_DEBUG_UART_CLOCK=100000000 +CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y CONFIG_I2C_CROS_EC_LDO=y @@ -40,4 +42,5 @@ CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_TPM=y CONFIG_ERRNO_STR=y diff --git a/include/configs/controlcenterd.h b/include/configs/controlcenterd.h index 8f829ed..9a1f6d0 100644 --- a/include/configs/controlcenterd.h +++ b/include/configs/controlcenterd.h @@ -226,14 +226,7 @@ #define CONFIG_SF_DEFAULT_MODE 0 #endif
-/* - * TPM - */ -#define CONFIG_TPM_ATMEL_TWI -#define CONFIG_TPM -#define CONFIG_TPM_AUTH_SESSIONS #define CONFIG_SHA1 -#define CONFIG_CMD_TPM
/* * MMC diff --git a/include/configs/efi-x86.h b/include/configs/efi-x86.h index 5779cfd..1c955d9 100644 --- a/include/configs/efi-x86.h +++ b/include/configs/efi-x86.h @@ -11,8 +11,6 @@
#undef CONFIG_CMD_SF_TEST
-#undef CONFIG_TPM -#undef CONFIG_TPM_TIS_LPC #undef CONFIG_TPM_TIS_BASE_ADDRESS
#undef CONFIG_CMD_IMLS diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index fb5ee0d..4866836 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -54,11 +54,6 @@ #define CONFIG_CMD_DTT #define CONFIG_TMU_CMD_DTT
-/* TPM */ -#define CONFIG_TPM -#define CONFIG_CMD_TPM -#define CONFIG_TPM_TIS_I2C - /* MMC SPL */ #define COPY_BL2_FNPTR_ADDR 0x02020030 #define CONFIG_SUPPORT_EMMC_BOOT diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h index 349b06c..27d3043 100644 --- a/include/configs/x86-common.h +++ b/include/configs/x86-common.h @@ -47,8 +47,6 @@ #endif
/* Generic TPM interfaced through LPC bus */ -#define CONFIG_TPM -#define CONFIG_TPM_TIS_LPC #define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000
/*-----------------------------------------------------------------------

Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
Convert all TPM options to Kconfig and tidy up.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2: None
configs/chromebook_link_defconfig | 2 ++ configs/chromebox_panther_defconfig | 2 ++ configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig | 4 ++++ configs/controlcenterd_36BIT_SDCARD_defconfig | 4 ++++ configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig | 4 ++++ configs/controlcenterd_TRAILBLAZER_defconfig | 4 ++++ configs/coreboot-x86_defconfig | 2 ++ configs/peach-pi_defconfig | 3 +++ configs/peach-pit_defconfig | 3 +++ configs/sandbox_defconfig | 2 ++ configs/snow_defconfig | 3 +++ configs/spring_defconfig | 3 +++ include/configs/controlcenterd.h | 7 ------- include/configs/efi-x86.h | 2 -- include/configs/exynos5-common.h | 5 ----- include/configs/x86-common.h | 2 -- 16 files changed, 36 insertions(+), 16 deletions(-)
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index b987f3f..b0fc5ca 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -17,9 +17,11 @@ CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_TPM_TIS_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y CONFIG_DM_RTC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y +CONFIG_TPM=y diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index e82c8ec..e7ef8fe 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -17,9 +17,11 @@ CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_TPM_TIS_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y CONFIG_DM_RTC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y +CONFIG_TPM=y diff --git a/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig b/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig index 37ead03..c8ab862 100644 --- a/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig +++ b/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig @@ -4,4 +4,8 @@ CONFIG_TARGET_CONTROLCENTERD=y CONFIG_SYS_EXTRA_OPTIONS="36BIT,SDCARD,DEVELOP" # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y +CONFIG_TPM_ATMEL_TWI=y +CONFIG_TPM_AUTH_SESSIONS=y +CONFIG_TPM=y diff --git a/configs/controlcenterd_36BIT_SDCARD_defconfig b/configs/controlcenterd_36BIT_SDCARD_defconfig index 7166edb..21c0eab 100644 --- a/configs/controlcenterd_36BIT_SDCARD_defconfig +++ b/configs/controlcenterd_36BIT_SDCARD_defconfig @@ -4,4 +4,8 @@ CONFIG_TARGET_CONTROLCENTERD=y CONFIG_SYS_EXTRA_OPTIONS="36BIT,SDCARD" # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y +CONFIG_TPM_ATMEL_TWI=y +CONFIG_TPM_AUTH_SESSIONS=y +CONFIG_TPM=y diff --git a/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig b/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig index d99fcd4..c3a0920 100644 --- a/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig +++ b/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig @@ -6,3 +6,7 @@ CONFIG_SYS_EXTRA_OPTIONS="TRAILBLAZER,SPIFLASH,DEVELOP" # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TPM=y +CONFIG_TPM_ATMEL_TWI=y +CONFIG_TPM_AUTH_SESSIONS=y +CONFIG_TPM=y diff --git a/configs/controlcenterd_TRAILBLAZER_defconfig b/configs/controlcenterd_TRAILBLAZER_defconfig index 3557aea..08aae9a 100644 --- a/configs/controlcenterd_TRAILBLAZER_defconfig +++ b/configs/controlcenterd_TRAILBLAZER_defconfig @@ -6,3 +6,7 @@ CONFIG_SYS_EXTRA_OPTIONS="TRAILBLAZER,SPIFLASH" # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TPM=y +CONFIG_TPM_ATMEL_TWI=y +CONFIG_TPM_AUTH_SESSIONS=y +CONFIG_TPM=y diff --git a/configs/coreboot-x86_defconfig b/configs/coreboot-x86_defconfig index df3a624..66b8caa 100644 --- a/configs/coreboot-x86_defconfig +++ b/configs/coreboot-x86_defconfig @@ -14,5 +14,7 @@ CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_NETDEVICES=y CONFIG_E1000=y +CONFIG_TPM_TIS_LPC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y +CONFIG_TPM=y diff --git a/configs/peach-pi_defconfig b/configs/peach-pi_defconfig index 323a2d3..2be74fd 100644 --- a/configs/peach-pi_defconfig +++ b/configs/peach-pi_defconfig @@ -7,11 +7,13 @@ CONFIG_SPL=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_SPI=y CONFIG_CROS_EC_KEYB=y +CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y CONFIG_I2C_CROS_EC_TUNNEL=y @@ -30,5 +32,6 @@ CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_TPM=y CONFIG_ERRNO_STR=y CONFIG_SYS_PROMPT="Peach-Pi # " diff --git a/configs/peach-pit_defconfig b/configs/peach-pit_defconfig index 6a08296..875ddd1 100644 --- a/configs/peach-pit_defconfig +++ b/configs/peach-pit_defconfig @@ -7,11 +7,13 @@ CONFIG_SPL=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_SPI=y CONFIG_CROS_EC_KEYB=y +CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y CONFIG_I2C_CROS_EC_TUNNEL=y @@ -30,5 +32,6 @@ CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_TPM=y CONFIG_ERRNO_STR=y CONFIG_SYS_PROMPT="Peach-Pit # " diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 85ff95d..b68d688 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -11,6 +11,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y CONFIG_OF_CONTROL=y CONFIG_OF_HOSTFILE=y CONFIG_CLK=y @@ -49,6 +50,7 @@ CONFIG_DM_MMC=y CONFIG_DM_RTC=y CONFIG_SYS_VSNPRINTF=y CONFIG_CMD_DHRYSTONE=y +CONFIG_TPM=y CONFIG_ERRNO_STR=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y diff --git a/configs/snow_defconfig b/configs/snow_defconfig index f5decd5..f59aa3f 100644 --- a/configs/snow_defconfig +++ b/configs/snow_defconfig @@ -8,6 +8,7 @@ CONFIG_SPL=y CONFIG_CMD_SOUND=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y @@ -17,6 +18,7 @@ CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_S5P=y CONFIG_DEBUG_UART_BASE=0x12c30000 CONFIG_DEBUG_UART_CLOCK=100000000 +CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y CONFIG_I2C_CROS_EC_LDO=y @@ -41,4 +43,5 @@ CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_TPM=y CONFIG_ERRNO_STR=y diff --git a/configs/spring_defconfig b/configs/spring_defconfig index f1d9a58..6144f03 100644 --- a/configs/spring_defconfig +++ b/configs/spring_defconfig @@ -8,6 +8,7 @@ CONFIG_SPL=y CONFIG_CMD_SOUND=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y @@ -17,6 +18,7 @@ CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_S5P=y CONFIG_DEBUG_UART_BASE=0x12c30000 CONFIG_DEBUG_UART_CLOCK=100000000 +CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y CONFIG_I2C_CROS_EC_LDO=y @@ -40,4 +42,5 @@ CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_TPM=y CONFIG_ERRNO_STR=y diff --git a/include/configs/controlcenterd.h b/include/configs/controlcenterd.h index 8f829ed..9a1f6d0 100644 --- a/include/configs/controlcenterd.h +++ b/include/configs/controlcenterd.h @@ -226,14 +226,7 @@ #define CONFIG_SF_DEFAULT_MODE 0 #endif
-/*
- TPM
- */
-#define CONFIG_TPM_ATMEL_TWI -#define CONFIG_TPM -#define CONFIG_TPM_AUTH_SESSIONS #define CONFIG_SHA1 -#define CONFIG_CMD_TPM
/*
- MMC
diff --git a/include/configs/efi-x86.h b/include/configs/efi-x86.h index 5779cfd..1c955d9 100644 --- a/include/configs/efi-x86.h +++ b/include/configs/efi-x86.h @@ -11,8 +11,6 @@
#undef CONFIG_CMD_SF_TEST
-#undef CONFIG_TPM -#undef CONFIG_TPM_TIS_LPC #undef CONFIG_TPM_TIS_BASE_ADDRESS
#undef CONFIG_CMD_IMLS diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index fb5ee0d..4866836 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -54,11 +54,6 @@ #define CONFIG_CMD_DTT #define CONFIG_TMU_CMD_DTT
-/* TPM */ -#define CONFIG_TPM -#define CONFIG_CMD_TPM -#define CONFIG_TPM_TIS_I2C
- /* MMC SPL */ #define COPY_BL2_FNPTR_ADDR 0x02020030 #define CONFIG_SUPPORT_EMMC_BOOT
diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h index 349b06c..27d3043 100644 --- a/include/configs/x86-common.h +++ b/include/configs/x86-common.h @@ -47,8 +47,6 @@ #endif
/* Generic TPM interfaced through LPC bus */ -#define CONFIG_TPM -#define CONFIG_TPM_TIS_LPC #define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000
/*-----------------------------------------------------------------------

On 24 August 2015 at 14:20, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

Add an SPDX header to two drivers that don't have it.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com ---
Changes in v2: None
drivers/tpm/tpm_atmel_twi.c | 15 +++------------ drivers/tpm/tpm_tis_i2c.c | 18 +----------------- 2 files changed, 4 insertions(+), 29 deletions(-)
diff --git a/drivers/tpm/tpm_atmel_twi.c b/drivers/tpm/tpm_atmel_twi.c index 361a772..205d7a5 100644 --- a/drivers/tpm/tpm_atmel_twi.c +++ b/drivers/tpm/tpm_atmel_twi.c @@ -1,18 +1,9 @@ /* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * Copyright (C) 2013 Guntermann & Drunck, GmbH * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Written by Dirk Eibach eibach@gdsys.de * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */
#include <common.h> diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index b6eaef1..438a221 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -17,23 +17,7 @@ * * Version: 2.1.1 * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0 */
#include <common.h>

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
Add an SPDX header to two drivers that don't have it.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2: None
drivers/tpm/tpm_atmel_twi.c | 15 +++------------ drivers/tpm/tpm_tis_i2c.c | 18 +----------------- 2 files changed, 4 insertions(+), 29 deletions(-)
Applied to u-boot-dm.

The current Infineon I2C TPM driver is written in two parts, intended to support use with other I2C devices. However we don't have any users and the Atmel I2C TPM device does not use this file.
We should simplify this and remove the unused abstration. As a first step, move the code into one file.
Also the name tpm_private.h suggests that the header file is generic to all TPMs but it is not. Rename it indicate that it relates only to this driver
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/tpm/Makefile | 2 - drivers/tpm/tpm.c | 594 --------------------------- drivers/tpm/tpm_tis_i2c.c | 548 +++++++++++++++++++++++- drivers/tpm/{tpm_private.h => tpm_tis_i2c.h} | 24 +- 4 files changed, 550 insertions(+), 618 deletions(-) delete mode 100644 drivers/tpm/tpm.c rename drivers/tpm/{tpm_private.h => tpm_tis_i2c.h} (73%)
diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index 150570e..597966c 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -3,9 +3,7 @@ # SPDX-License-Identifier: GPL-2.0+ #
-# TODO: Merge tpm_tis_lpc.c with tpm.c obj-$(CONFIG_TPM_ATMEL_TWI) += tpm_atmel_twi.o -obj-$(CONFIG_TPM_TIS_I2C) += tpm.o obj-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o obj-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o obj-$(CONFIG_TPM_TIS_SANDBOX) += tpm_tis_sandbox.o diff --git a/drivers/tpm/tpm.c b/drivers/tpm/tpm.c deleted file mode 100644 index 24997f6..0000000 --- a/drivers/tpm/tpm.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * Copyright (C) 2011 Infineon Technologies - * - * Authors: - * Peter Huewe huewe.external@infineon.com - * - * Description: - * Device driver for TCG/TCPA TPM (trusted platform module). - * Specifications at www.trustedcomputinggroup.org - * - * It is based on the Linux kernel driver tpm.c from Leendert van - * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. - * - * Version: 2.1.1 - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <config.h> -#include <common.h> -#include <dm.h> -#include <linux/compiler.h> -#include <fdtdec.h> -#include <i2c.h> -#include <tpm.h> -#include <asm-generic/errno.h> -#include <linux/types.h> -#include <linux/unaligned/be_byteshift.h> - -#include "tpm_private.h" - -DECLARE_GLOBAL_DATA_PTR; - -/* TPM configuration */ -struct tpm { - struct udevice *dev; - char inited; -} tpm; - -/* Global structure for tpm chip data */ -static struct tpm_chip g_chip; - -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, -}; - -/* Returns max number of milliseconds to wait */ -static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, - 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 = chip->vendor.duration[duration_idx]; - - if (duration <= 0) - return 2 * 60 * HZ; /* Two minutes timeout */ - else - return duration; -} - -static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) -{ - int rc; - u32 count, ordinal; - unsigned long start, stop; - - struct tpm_chip *chip = &g_chip; - - /* switch endianess: big->little */ - count = get_unaligned_be32(buf + TPM_CMD_COUNT_BYTE); - ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE); - - if (count == 0) { - error("no data\n"); - return -ENODATA; - } - if (count > bufsiz) { - error("invalid count value %x %zx\n", count, bufsiz); - return -E2BIG; - } - - debug("Calling send\n"); - rc = chip->vendor.send(chip, (u8 *)buf, count); - debug(" ... done calling send\n"); - if (rc < 0) { - error("tpm_transmit: tpm_send: error %d\n", rc); - goto out; - } - - if (chip->vendor.irq) - goto out_recv; - - start = get_timer(0); - stop = tpm_calc_ordinal_duration(chip, ordinal); - do { - debug("waiting for status... %ld %ld\n", start, stop); - u8 status = chip->vendor.status(chip); - if ((status & chip->vendor.req_complete_mask) == - chip->vendor.req_complete_val) { - debug("...got it;\n"); - goto out_recv; - } - - if (status == chip->vendor.req_canceled) { - error("Operation Canceled\n"); - rc = -ECANCELED; - goto out; - } - udelay(TPM_TIMEOUT * 1000); - } while (get_timer(start) < stop); - - chip->vendor.cancel(chip); - error("Operation Timed out\n"); - rc = -ETIME; - goto out; - -out_recv: - debug("out_recv: reading response...\n"); - rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE); - if (rc < 0) - error("tpm_transmit: tpm_recv: error %d\n", rc); - -out: - return rc; -} - -static int tpm_open_dev(struct udevice *dev) -{ - int rc; - - debug("%s: start\n", __func__); - if (g_chip.is_open) - return -EBUSY; - rc = tpm_vendor_init(dev); - if (rc < 0) - g_chip.is_open = 0; - return rc; -} - -static void tpm_close(void) -{ - if (g_chip.is_open) { - tpm_vendor_cleanup(&g_chip); - g_chip.is_open = 0; - } -} - -/** - * Decode TPM configuration. - * - * @param dev Returns a configuration of TPM device - * @return 0 if ok, -1 on error - */ -static int tpm_decode_config(struct tpm *dev) -{ - const void *blob = gd->fdt_blob; - struct udevice *bus; - int chip_addr; - int parent; - int node; - int ret; - - node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); - if (node < 0) { - node = fdtdec_next_compatible(blob, 0, - COMPAT_INFINEON_SLB9645_TPM); - } - if (node < 0) { - debug("%s: Node not found\n", __func__); - return -1; - } - parent = fdt_parent_offset(blob, node); - if (parent < 0) { - debug("%s: Cannot find node parent\n", __func__); - return -1; - } - - /* - * TODO(sjg@chromium.org): Remove this when driver model supports - * TPMs - */ - ret = uclass_get_device_by_of_offset(UCLASS_I2C, parent, &bus); - if (ret) { - debug("Cannot find bus for node '%s: ret=%d'\n", - fdt_get_name(blob, parent, NULL), ret); - return ret; - } - - chip_addr = fdtdec_get_int(blob, node, "reg", -1); - if (chip_addr == -1) { - debug("Cannot find reg property for node '%s: ret=%d'\n", - fdt_get_name(blob, node, NULL), ret); - return ret; - } - /* - * TODO(sjg@chromium.org): Older TPMs will need to use the older method - * in iic_tpm_read() so the offset length needs to be 0 here. - */ - ret = i2c_get_chip(bus, chip_addr, 1, &dev->dev); - if (ret) { - debug("Cannot find device for node '%s: ret=%d'\n", - fdt_get_name(blob, node, NULL), ret); - return ret; - } - - return 0; -} - -struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry) -{ - struct tpm_chip *chip; - - /* Driver specific per-device data */ - chip = &g_chip; - memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); - chip->is_open = 1; - - return chip; -} - -int tis_init(void) -{ - if (tpm.inited) - return 0; - - if (tpm_decode_config(&tpm)) - return -1; - - debug("%s: done\n", __func__); - - tpm.inited = 1; - - return 0; -} - -int tis_open(void) -{ - int rc; - - if (!tpm.inited) - return -1; - - rc = tpm_open_dev(tpm.dev); - - return rc; -} - -int tis_close(void) -{ - if (!tpm.inited) - return -1; - - tpm_close(); - - return 0; -} - -int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, - uint8_t *recvbuf, size_t *rbuf_len) -{ - int len; - uint8_t buf[4096]; - - if (!tpm.inited) - return -1; - - if (sizeof(buf) < sbuf_size) - return -1; - - memcpy(buf, sendbuf, sbuf_size); - - len = tpm_transmit(buf, sbuf_size); - - if (len < 10) { - *rbuf_len = 0; - return -1; - } - - memcpy(recvbuf, buf, len); - *rbuf_len = len; - - return 0; -} diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 438a221..e547f0a 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -30,7 +30,7 @@ #include <linux/types.h> #include <linux/unaligned/be_byteshift.h>
-#include "tpm_private.h" +#include "tpm_tis_i2c.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -95,6 +95,304 @@ static const char * const chip_name[] = { #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, +}; + +/* TPM configuration */ +struct tpm { + struct udevice *dev; + char inited; +} tpm; + +/* Global structure for tpm chip data */ +static struct tpm_chip g_chip; + /* Structure to store I2C TPM specific stuff */ struct tpm_dev { struct udevice *dev; @@ -595,3 +893,251 @@ void tpm_vendor_cleanup(struct tpm_chip *chip) { release_locality(chip, chip->vendor.locality, 1); } + +/* Returns max number of milliseconds to wait */ +static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, + 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 = chip->vendor.duration[duration_idx]; + + if (duration <= 0) + return 2 * 60 * HZ; /* Two minutes timeout */ + else + return duration; +} + +static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) +{ + int rc; + u32 count, ordinal; + unsigned long start, stop; + + struct tpm_chip *chip = &g_chip; + + /* switch endianess: big->little */ + count = get_unaligned_be32(buf + TPM_CMD_COUNT_BYTE); + ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE); + + if (count == 0) { + error("no data\n"); + return -ENODATA; + } + if (count > bufsiz) { + error("invalid count value %x %zx\n", count, bufsiz); + return -E2BIG; + } + + debug("Calling send\n"); + rc = chip->vendor.send(chip, (u8 *)buf, count); + debug(" ... done calling send\n"); + if (rc < 0) { + error("tpm_transmit: tpm_send: error %d\n", rc); + goto out; + } + + if (chip->vendor.irq) + goto out_recv; + + start = get_timer(0); + stop = tpm_calc_ordinal_duration(chip, ordinal); + do { + debug("waiting for status... %ld %ld\n", start, stop); + u8 status = chip->vendor.status(chip); + if ((status & chip->vendor.req_complete_mask) == + chip->vendor.req_complete_val) { + debug("...got it;\n"); + goto out_recv; + } + + if (status == chip->vendor.req_canceled) { + error("Operation Canceled\n"); + rc = -ECANCELED; + goto out; + } + udelay(TPM_TIMEOUT * 1000); + } while (get_timer(start) < stop); + + chip->vendor.cancel(chip); + error("Operation Timed out\n"); + rc = -ETIME; + goto out; + +out_recv: + debug("out_recv: reading response...\n"); + rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE); + if (rc < 0) + error("tpm_transmit: tpm_recv: error %d\n", rc); + +out: + return rc; +} + +static int tpm_open_dev(struct udevice *dev) +{ + int rc; + + debug("%s: start\n", __func__); + if (g_chip.is_open) + return -EBUSY; + rc = tpm_vendor_init(dev); + if (rc < 0) + g_chip.is_open = 0; + return rc; +} + +static void tpm_close(void) +{ + if (g_chip.is_open) { + tpm_vendor_cleanup(&g_chip); + g_chip.is_open = 0; + } +} + +/** + * Decode TPM configuration. + * + * @param dev Returns a configuration of TPM device + * @return 0 if ok, -1 on error + */ +static int tpm_decode_config(struct tpm *dev) +{ + const void *blob = gd->fdt_blob; + struct udevice *bus; + int chip_addr; + int parent; + int node; + int ret; + + node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); + if (node < 0) { + node = fdtdec_next_compatible(blob, 0, + COMPAT_INFINEON_SLB9645_TPM); + } + if (node < 0) { + debug("%s: Node not found\n", __func__); + return -1; + } + parent = fdt_parent_offset(blob, node); + if (parent < 0) { + debug("%s: Cannot find node parent\n", __func__); + return -1; + } + + /* + * TODO(sjg@chromium.org): Remove this when driver model supports + * TPMs + */ + ret = uclass_get_device_by_of_offset(UCLASS_I2C, parent, &bus); + if (ret) { + debug("Cannot find bus for node '%s: ret=%d'\n", + fdt_get_name(blob, parent, NULL), ret); + return ret; + } + + chip_addr = fdtdec_get_int(blob, node, "reg", -1); + if (chip_addr == -1) { + debug("Cannot find reg property for node '%s: ret=%d'\n", + fdt_get_name(blob, node, NULL), ret); + return ret; + } + /* + * TODO(sjg@chromium.org): Older TPMs will need to use the older method + * in iic_tpm_read() so the offset length needs to be 0 here. + */ + ret = i2c_get_chip(bus, chip_addr, 1, &dev->dev); + if (ret) { + debug("Cannot find device for node '%s: ret=%d'\n", + fdt_get_name(blob, node, NULL), ret); + return ret; + } + + return 0; +} + +struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry) +{ + struct tpm_chip *chip; + + /* Driver specific per-device data */ + chip = &g_chip; + memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); + chip->is_open = 1; + + return chip; +} + +int tis_init(void) +{ + if (tpm.inited) + return 0; + + if (tpm_decode_config(&tpm)) + return -1; + + debug("%s: done\n", __func__); + + tpm.inited = 1; + + return 0; +} + +int tis_open(void) +{ + int rc; + + if (!tpm.inited) + return -1; + + rc = tpm_open_dev(tpm.dev); + + return rc; +} + +int tis_close(void) +{ + if (!tpm.inited) + return -1; + + tpm_close(); + + return 0; +} + +int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, + uint8_t *recvbuf, size_t *rbuf_len) +{ + int len; + uint8_t buf[4096]; + + if (!tpm.inited) + return -1; + + if (sizeof(buf) < sbuf_size) + return -1; + + memcpy(buf, sendbuf, sbuf_size); + + len = tpm_transmit(buf, sbuf_size); + + if (len < 10) { + *rbuf_len = 0; + return -1; + } + + memcpy(recvbuf, buf, len); + *rbuf_len = len; + + return 0; +} diff --git a/drivers/tpm/tpm_private.h b/drivers/tpm/tpm_tis_i2c.h similarity index 73% rename from drivers/tpm/tpm_private.h rename to drivers/tpm/tpm_tis_i2c.h index daaf8b8..75fa829 100644 --- a/drivers/tpm/tpm_private.h +++ b/drivers/tpm/tpm_tis_i2c.h @@ -13,28 +13,11 @@ * It is based on the Linux kernel driver tpm.c from Leendert van * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. * - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0 */
-#ifndef _TPM_PRIVATE_H_ -#define _TPM_PRIVATE_H_ +#ifndef _TPM_TIS_I2C_H +#define _TPM_TIS_I2C_H
#include <linux/compiler.h> #include <linux/types.h> @@ -134,5 +117,4 @@ int tpm_vendor_init(struct udevice *dev);
void tpm_vendor_cleanup(struct tpm_chip *chip);
- #endif

Hi Simon,
I don't disagree with this patch (from patch 6 to patch 12). However, i believe it would be better to have this driver renamed tpm_i2c_infineon as shown in my previous patch: http://lists.denx.de/pipermail/u-boot/2015-August/223582.html
Could you update this ?
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
The current Infineon I2C TPM driver is written in two parts, intended to support use with other I2C devices. However we don't have any users and the Atmel I2C TPM device does not use this file.
We should simplify this and remove the unused abstration. As a first step, move the code into one file.
Also the name tpm_private.h suggests that the header file is generic to all TPMs but it is not. Rename it indicate that it relates only to this driver
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/tpm/Makefile | 2 - drivers/tpm/tpm.c | 594 --------------------------- drivers/tpm/tpm_tis_i2c.c | 548 +++++++++++++++++++++++- drivers/tpm/{tpm_private.h => tpm_tis_i2c.h} | 24 +- 4 files changed, 550 insertions(+), 618 deletions(-) delete mode 100644 drivers/tpm/tpm.c rename drivers/tpm/{tpm_private.h => tpm_tis_i2c.h} (73%)
diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index 150570e..597966c 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -3,9 +3,7 @@ # SPDX-License-Identifier: GPL-2.0+ #
-# TODO: Merge tpm_tis_lpc.c with tpm.c obj-$(CONFIG_TPM_ATMEL_TWI) += tpm_atmel_twi.o -obj-$(CONFIG_TPM_TIS_I2C) += tpm.o obj-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o obj-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o obj-$(CONFIG_TPM_TIS_SANDBOX) += tpm_tis_sandbox.o diff --git a/drivers/tpm/tpm.c b/drivers/tpm/tpm.c deleted file mode 100644 index 24997f6..0000000 --- a/drivers/tpm/tpm.c +++ /dev/null @@ -1,594 +0,0 @@ -/*
- Copyright (C) 2011 Infineon Technologies
- Authors:
- Peter Huewe huewe.external@infineon.com
- Description:
- Device driver for TCG/TCPA TPM (trusted platform module).
- Specifications at www.trustedcomputinggroup.org
- It is based on the Linux kernel driver tpm.c from Leendert van
- Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
- Version: 2.1.1
- See file CREDITS for list of people who contributed to this
- project.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation, version 2 of the
- License.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- */
-#include <config.h> -#include <common.h> -#include <dm.h> -#include <linux/compiler.h> -#include <fdtdec.h> -#include <i2c.h> -#include <tpm.h> -#include <asm-generic/errno.h> -#include <linux/types.h> -#include <linux/unaligned/be_byteshift.h>
-#include "tpm_private.h"
-DECLARE_GLOBAL_DATA_PTR;
-/* TPM configuration */ -struct tpm {
- struct udevice *dev;
- char inited;
-} tpm;
-/* Global structure for tpm chip data */ -static struct tpm_chip g_chip;
-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,
-};
-/* Returns max number of milliseconds to wait */ -static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
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 = chip->vendor.duration[duration_idx];
- if (duration <= 0)
return 2 * 60 * HZ; /* Two minutes timeout */
- else
return duration;
-}
-static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) -{
- int rc;
- u32 count, ordinal;
- unsigned long start, stop;
- struct tpm_chip *chip = &g_chip;
- /* switch endianess: big->little */
- count = get_unaligned_be32(buf + TPM_CMD_COUNT_BYTE);
- ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE);
- if (count == 0) {
error("no data\n");
return -ENODATA;
- }
- if (count > bufsiz) {
error("invalid count value %x %zx\n", count, bufsiz);
return -E2BIG;
- }
- debug("Calling send\n");
- rc = chip->vendor.send(chip, (u8 *)buf, count);
- debug(" ... done calling send\n");
- if (rc < 0) {
error("tpm_transmit: tpm_send: error %d\n", rc);
goto out;
- }
- if (chip->vendor.irq)
goto out_recv;
- start = get_timer(0);
- stop = tpm_calc_ordinal_duration(chip, ordinal);
- do {
debug("waiting for status... %ld %ld\n", start, stop);
u8 status = chip->vendor.status(chip);
if ((status & chip->vendor.req_complete_mask) ==
chip->vendor.req_complete_val) {
debug("...got it;\n");
goto out_recv;
}
if (status == chip->vendor.req_canceled) {
error("Operation Canceled\n");
rc = -ECANCELED;
goto out;
}
udelay(TPM_TIMEOUT * 1000);
- } while (get_timer(start) < stop);
- chip->vendor.cancel(chip);
- error("Operation Timed out\n");
- rc = -ETIME;
- goto out;
-out_recv:
- debug("out_recv: reading response...\n");
- rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE);
- if (rc < 0)
error("tpm_transmit: tpm_recv: error %d\n", rc);
-out:
- return rc;
-}
-static int tpm_open_dev(struct udevice *dev) -{
- int rc;
- debug("%s: start\n", __func__);
- if (g_chip.is_open)
return -EBUSY;
- rc = tpm_vendor_init(dev);
- if (rc < 0)
g_chip.is_open = 0;
- return rc;
-}
-static void tpm_close(void) -{
- if (g_chip.is_open) {
tpm_vendor_cleanup(&g_chip);
g_chip.is_open = 0;
- }
-}
-/**
- Decode TPM configuration.
- @param dev Returns a configuration of TPM device
- @return 0 if ok, -1 on error
- */
-static int tpm_decode_config(struct tpm *dev) -{
- const void *blob = gd->fdt_blob;
- struct udevice *bus;
- int chip_addr;
- int parent;
- int node;
- int ret;
- node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM);
- if (node < 0) {
node = fdtdec_next_compatible(blob, 0,
COMPAT_INFINEON_SLB9645_TPM);
- }
- if (node < 0) {
debug("%s: Node not found\n", __func__);
return -1;
- }
- parent = fdt_parent_offset(blob, node);
- if (parent < 0) {
debug("%s: Cannot find node parent\n", __func__);
return -1;
- }
- /*
* TODO(sjg@chromium.org): Remove this when driver model supports
* TPMs
*/
- ret = uclass_get_device_by_of_offset(UCLASS_I2C, parent, &bus);
- if (ret) {
debug("Cannot find bus for node '%s: ret=%d'\n",
fdt_get_name(blob, parent, NULL), ret);
return ret;
- }
- chip_addr = fdtdec_get_int(blob, node, "reg", -1);
- if (chip_addr == -1) {
debug("Cannot find reg property for node '%s: ret=%d'\n",
fdt_get_name(blob, node, NULL), ret);
return ret;
- }
- /*
* TODO(sjg@chromium.org): Older TPMs will need to use the older method
* in iic_tpm_read() so the offset length needs to be 0 here.
*/
- ret = i2c_get_chip(bus, chip_addr, 1, &dev->dev);
- if (ret) {
debug("Cannot find device for node '%s: ret=%d'\n",
fdt_get_name(blob, node, NULL), ret);
return ret;
- }
- return 0;
-}
-struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry) -{
- struct tpm_chip *chip;
- /* Driver specific per-device data */
- chip = &g_chip;
- memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
- chip->is_open = 1;
- return chip;
-}
-int tis_init(void) -{
- if (tpm.inited)
return 0;
- if (tpm_decode_config(&tpm))
return -1;
- debug("%s: done\n", __func__);
- tpm.inited = 1;
- return 0;
-}
-int tis_open(void) -{
- int rc;
- if (!tpm.inited)
return -1;
- rc = tpm_open_dev(tpm.dev);
- return rc;
-}
-int tis_close(void) -{
- if (!tpm.inited)
return -1;
- tpm_close();
- return 0;
-}
-int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
uint8_t *recvbuf, size_t *rbuf_len)
-{
- int len;
- uint8_t buf[4096];
- if (!tpm.inited)
return -1;
- if (sizeof(buf) < sbuf_size)
return -1;
- memcpy(buf, sendbuf, sbuf_size);
- len = tpm_transmit(buf, sbuf_size);
- if (len < 10) {
*rbuf_len = 0;
return -1;
- }
- memcpy(recvbuf, buf, len);
- *rbuf_len = len;
- return 0;
-} diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 438a221..e547f0a 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -30,7 +30,7 @@ #include <linux/types.h> #include <linux/unaligned/be_byteshift.h>
-#include "tpm_private.h" +#include "tpm_tis_i2c.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -95,6 +95,304 @@ static const char * const chip_name[] = { #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,
+};
+/* TPM configuration */ +struct tpm {
- struct udevice *dev;
- char inited;
+} tpm;
+/* Global structure for tpm chip data */ +static struct tpm_chip g_chip;
- /* Structure to store I2C TPM specific stuff */ struct tpm_dev { struct udevice *dev;
@@ -595,3 +893,251 @@ void tpm_vendor_cleanup(struct tpm_chip *chip) { release_locality(chip, chip->vendor.locality, 1); }
+/* Returns max number of milliseconds to wait */ +static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
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 = chip->vendor.duration[duration_idx];
- if (duration <= 0)
return 2 * 60 * HZ; /* Two minutes timeout */
- else
return duration;
+}
+static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) +{
- int rc;
- u32 count, ordinal;
- unsigned long start, stop;
- struct tpm_chip *chip = &g_chip;
- /* switch endianess: big->little */
- count = get_unaligned_be32(buf + TPM_CMD_COUNT_BYTE);
- ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE);
- if (count == 0) {
error("no data\n");
return -ENODATA;
- }
- if (count > bufsiz) {
error("invalid count value %x %zx\n", count, bufsiz);
return -E2BIG;
- }
- debug("Calling send\n");
- rc = chip->vendor.send(chip, (u8 *)buf, count);
- debug(" ... done calling send\n");
- if (rc < 0) {
error("tpm_transmit: tpm_send: error %d\n", rc);
goto out;
- }
- if (chip->vendor.irq)
goto out_recv;
- start = get_timer(0);
- stop = tpm_calc_ordinal_duration(chip, ordinal);
- do {
debug("waiting for status... %ld %ld\n", start, stop);
u8 status = chip->vendor.status(chip);
if ((status & chip->vendor.req_complete_mask) ==
chip->vendor.req_complete_val) {
debug("...got it;\n");
goto out_recv;
}
if (status == chip->vendor.req_canceled) {
error("Operation Canceled\n");
rc = -ECANCELED;
goto out;
}
udelay(TPM_TIMEOUT * 1000);
- } while (get_timer(start) < stop);
- chip->vendor.cancel(chip);
- error("Operation Timed out\n");
- rc = -ETIME;
- goto out;
+out_recv:
- debug("out_recv: reading response...\n");
- rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE);
- if (rc < 0)
error("tpm_transmit: tpm_recv: error %d\n", rc);
+out:
- return rc;
+}
+static int tpm_open_dev(struct udevice *dev) +{
- int rc;
- debug("%s: start\n", __func__);
- if (g_chip.is_open)
return -EBUSY;
- rc = tpm_vendor_init(dev);
- if (rc < 0)
g_chip.is_open = 0;
- return rc;
+}
+static void tpm_close(void) +{
- if (g_chip.is_open) {
tpm_vendor_cleanup(&g_chip);
g_chip.is_open = 0;
- }
+}
+/**
- Decode TPM configuration.
- @param dev Returns a configuration of TPM device
- @return 0 if ok, -1 on error
- */
+static int tpm_decode_config(struct tpm *dev) +{
- const void *blob = gd->fdt_blob;
- struct udevice *bus;
- int chip_addr;
- int parent;
- int node;
- int ret;
- node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM);
- if (node < 0) {
node = fdtdec_next_compatible(blob, 0,
COMPAT_INFINEON_SLB9645_TPM);
- }
- if (node < 0) {
debug("%s: Node not found\n", __func__);
return -1;
- }
- parent = fdt_parent_offset(blob, node);
- if (parent < 0) {
debug("%s: Cannot find node parent\n", __func__);
return -1;
- }
- /*
* TODO(sjg@chromium.org): Remove this when driver model supports
* TPMs
*/
- ret = uclass_get_device_by_of_offset(UCLASS_I2C, parent, &bus);
- if (ret) {
debug("Cannot find bus for node '%s: ret=%d'\n",
fdt_get_name(blob, parent, NULL), ret);
return ret;
- }
- chip_addr = fdtdec_get_int(blob, node, "reg", -1);
- if (chip_addr == -1) {
debug("Cannot find reg property for node '%s: ret=%d'\n",
fdt_get_name(blob, node, NULL), ret);
return ret;
- }
- /*
* TODO(sjg@chromium.org): Older TPMs will need to use the older method
* in iic_tpm_read() so the offset length needs to be 0 here.
*/
- ret = i2c_get_chip(bus, chip_addr, 1, &dev->dev);
- if (ret) {
debug("Cannot find device for node '%s: ret=%d'\n",
fdt_get_name(blob, node, NULL), ret);
return ret;
- }
- return 0;
+}
+struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry) +{
- struct tpm_chip *chip;
- /* Driver specific per-device data */
- chip = &g_chip;
- memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
- chip->is_open = 1;
- return chip;
+}
+int tis_init(void) +{
- if (tpm.inited)
return 0;
- if (tpm_decode_config(&tpm))
return -1;
- debug("%s: done\n", __func__);
- tpm.inited = 1;
- return 0;
+}
+int tis_open(void) +{
- int rc;
- if (!tpm.inited)
return -1;
- rc = tpm_open_dev(tpm.dev);
- return rc;
+}
+int tis_close(void) +{
- if (!tpm.inited)
return -1;
- tpm_close();
- return 0;
+}
+int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
uint8_t *recvbuf, size_t *rbuf_len)
+{
- int len;
- uint8_t buf[4096];
- if (!tpm.inited)
return -1;
- if (sizeof(buf) < sbuf_size)
return -1;
- memcpy(buf, sendbuf, sbuf_size);
- len = tpm_transmit(buf, sbuf_size);
- if (len < 10) {
*rbuf_len = 0;
return -1;
- }
- memcpy(recvbuf, buf, len);
- *rbuf_len = len;
- return 0;
+} diff --git a/drivers/tpm/tpm_private.h b/drivers/tpm/tpm_tis_i2c.h similarity index 73% rename from drivers/tpm/tpm_private.h rename to drivers/tpm/tpm_tis_i2c.h index daaf8b8..75fa829 100644 --- a/drivers/tpm/tpm_private.h +++ b/drivers/tpm/tpm_tis_i2c.h @@ -13,28 +13,11 @@
- It is based on the Linux kernel driver tpm.c from Leendert van
- Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
- See file CREDITS for list of people who contributed to this
- project.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation, version 2 of the
- License.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
*/
- SPDX-License-Identifier: GPL-2.0
-#ifndef _TPM_PRIVATE_H_ -#define _TPM_PRIVATE_H_ +#ifndef _TPM_TIS_I2C_H +#define _TPM_TIS_I2C_H
#include <linux/compiler.h> #include <linux/types.h> @@ -134,5 +117,4 @@ int tpm_vendor_init(struct udevice *dev);
void tpm_vendor_cleanup(struct tpm_chip *chip);
- #endif

Hi Christophe,
On 24 August 2015 at 14:24, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
I don't disagree with this patch (from patch 6 to patch 12). However, i believe it would be better to have this driver renamed tpm_i2c_infineon as shown in my previous patch: http://lists.denx.de/pipermail/u-boot/2015-August/223582.html
Could you update this ?
Yes, although I think this can be a separate patch. I was going to use yours...
Best Regards Christophe
[snip]

Hi Simon,
Le 25/08/2015 06:13, Simon Glass a écrit :
Hi Christophe,
On 24 August 2015 at 14:24, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
I don't disagree with this patch (from patch 6 to patch 12). However, i believe it would be better to have this driver renamed tpm_i2c_infineon as shown in my previous patch: http://lists.denx.de/pipermail/u-boot/2015-August/223582.html
Could you update this ?
Yes, although I think this can be a separate patch. I was going to use yours...
Then ok. This is fine for me :)
Best Regards Christophe
[snip]
Best Regards Christophe

On 25 August 2015 at 12:38, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
Le 25/08/2015 06:13, Simon Glass a écrit :
Hi Christophe,
On 24 August 2015 at 14:24, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
I don't disagree with this patch (from patch 6 to patch 12). However, i believe it would be better to have this driver renamed tpm_i2c_infineon as shown in my previous patch: http://lists.denx.de/pipermail/u-boot/2015-August/223582.html
Could you update this ?
Yes, although I think this can be a separate patch. I was going to use yours...
Then ok. This is fine for me :)
Best Regards Christophe
[snip]
Best Regards Christophe
Applied to u-boot-dm.

The function methods in struct tpm_vendor_specific just call local functions. Change the code to use a direct call.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 12 ++++-------- drivers/tpm/tpm_tis_i2c.h | 4 ---- 2 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index e547f0a..6a3991f 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -810,10 +810,6 @@ out_err: }
static struct tpm_vendor_specific tpm_tis_i2c = { - .status = tpm_tis_i2c_status, - .recv = tpm_tis_i2c_recv, - .send = tpm_tis_i2c_send, - .cancel = tpm_tis_i2c_ready, .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, .req_canceled = TPM_STS_COMMAND_READY, @@ -940,7 +936,7 @@ static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) }
debug("Calling send\n"); - rc = chip->vendor.send(chip, (u8 *)buf, count); + rc = tpm_tis_i2c_send(chip, (u8 *)buf, count); debug(" ... done calling send\n"); if (rc < 0) { error("tpm_transmit: tpm_send: error %d\n", rc); @@ -954,7 +950,7 @@ static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) stop = tpm_calc_ordinal_duration(chip, ordinal); do { debug("waiting for status... %ld %ld\n", start, stop); - u8 status = chip->vendor.status(chip); + u8 status = tpm_tis_i2c_status(chip); if ((status & chip->vendor.req_complete_mask) == chip->vendor.req_complete_val) { debug("...got it;\n"); @@ -969,14 +965,14 @@ static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) udelay(TPM_TIMEOUT * 1000); } while (get_timer(start) < stop);
- chip->vendor.cancel(chip); + tpm_tis_i2c_ready(chip); error("Operation Timed out\n"); rc = -ETIME; goto out;
out_recv: debug("out_recv: reading response...\n"); - rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE); + rc = tpm_tis_i2c_recv(chip, (u8 *)buf, TPM_BUFSIZE); if (rc < 0) error("tpm_transmit: tpm_recv: error %d\n", rc);
diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_i2c.h index 75fa829..426c519 100644 --- a/drivers/tpm/tpm_tis_i2c.h +++ b/drivers/tpm/tpm_tis_i2c.h @@ -40,10 +40,6 @@ struct tpm_vendor_specific { const u8 req_complete_val; const u8 req_canceled; int irq; - int (*recv) (struct tpm_chip *, u8 *, size_t); - int (*send) (struct tpm_chip *, u8 *, size_t); - void (*cancel) (struct tpm_chip *); - u8(*status) (struct tpm_chip *); int locality; unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ unsigned long duration[3]; /* msec */

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
The function methods in struct tpm_vendor_specific just call local functions. Change the code to use a direct call.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 12 ++++-------- drivers/tpm/tpm_tis_i2c.h | 4 ---- 2 files changed, 4 insertions(+), 12 deletions(-)
Applied to u-boot-dm.

This function is misnamed since it only applies to a single driver. Merge its fields into its parent.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 79 ++++++++++++++++++----------------------------- drivers/tpm/tpm_tis_i2c.h | 16 +++------- 2 files changed, 35 insertions(+), 60 deletions(-)
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 6a3991f..3ae1a4e 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -531,7 +531,7 @@ static int check_locality(struct tpm_chip *chip, int loc) return rc;
if ((buf & mask) == mask) { - chip->vendor.locality = loc; + chip->locality = loc; return loc; }
@@ -567,7 +567,7 @@ static int request_locality(struct tpm_chip *chip, int loc)
/* Wait for burstcount */ start = get_timer(0); - stop = chip->vendor.timeout_a; + stop = chip->timeout_a; do { if (check_locality(chip, loc) >= 0) return loc; @@ -582,7 +582,7 @@ static u8 tpm_tis_i2c_status(struct tpm_chip *chip) /* NOTE: Since i2c read may fail, return 0 in this case --> time-out */ u8 buf;
- if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) + if (iic_tpm_read(TPM_STS(chip->locality), &buf, 1) < 0) return 0; else return buf; @@ -596,7 +596,7 @@ static void tpm_tis_i2c_ready(struct tpm_chip *chip) u8 buf = TPM_STS_COMMAND_READY;
debug("%s\n", __func__); - rc = iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); + rc = iic_tpm_write_long(TPM_STS(chip->locality), &buf, 1); if (rc) debug("%s: rc=%d\n", __func__, rc); } @@ -610,10 +610,10 @@ static ssize_t get_burstcount(struct tpm_chip *chip) /* Wait for burstcount */ /* XXX: Which timeout value? Spec has 2 answers (c & d) */ start = get_timer(0); - stop = chip->vendor.timeout_d; + stop = chip->timeout_d; do { /* Note: STS is little endian */ - addr = TPM_STS(chip->vendor.locality) + 1; + addr = TPM_STS(chip->locality) + 1; if (iic_tpm_read(addr, buf, 3) < 0) burstcnt = 0; else @@ -666,7 +666,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) if (burstcnt > (count - size)) burstcnt = count - size;
- rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality), + rc = iic_tpm_read(TPM_DATA_FIFO(chip->locality), &(buf[size]), burstcnt); if (rc == 0) size += burstcnt; @@ -708,7 +708,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) goto out; }
- wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); + wait_for_stat(chip, TPM_STS_VALID, chip->timeout_c, &status); if (status & TPM_STS_DATA_AVAIL) { /* Retry? */ error("Error left over data\n"); size = -EIO; @@ -722,7 +722,7 @@ out: * so we sleep rather than keeping the bus busy */ udelay(2000); - release_locality(chip, chip->vendor.locality, 0); + release_locality(chip, chip->locality, 0);
return size; } @@ -746,7 +746,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) if ((status & TPM_STS_COMMAND_READY) == 0) { tpm_tis_i2c_ready(chip); if (wait_for_stat(chip, TPM_STS_COMMAND_READY, - chip->vendor.timeout_b, &status) < 0) { + chip->timeout_b, &status) < 0) { rc = -ETIME; goto out_err; } @@ -768,7 +768,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION; #endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */
- rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), + rc = iic_tpm_write(TPM_DATA_FIFO(chip->locality), &(buf[count]), burstcnt); if (rc == 0) count += burstcnt; @@ -779,7 +779,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) goto out_err; } rc = wait_for_stat(chip, TPM_STS_VALID, - chip->vendor.timeout_c, &status); + chip->timeout_c, &status); if (rc) goto out_err;
@@ -791,7 +791,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) }
/* Go and do it */ - iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); + iic_tpm_write(TPM_STS(chip->locality), &sts, 1); debug("done\n");
return len; @@ -804,18 +804,11 @@ out_err: * so we sleep rather than keeping the bus busy */ udelay(2000); - release_locality(chip, chip->vendor.locality, 0); + release_locality(chip, chip->locality, 0);
return rc; }
-static struct tpm_vendor_specific tpm_tis_i2c = { - .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, - .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, - .req_canceled = TPM_STS_COMMAND_READY, -}; - - static enum i2c_chip_type tpm_vendor_chip_type(void) { #if CONFIG_IS_ENABLED(OF_CONTROL) @@ -832,25 +825,25 @@ static enum i2c_chip_type tpm_vendor_chip_type(void)
int tpm_vendor_init(struct udevice *dev) { - struct tpm_chip *chip; + struct tpm_chip *chip = &g_chip; u32 vendor; u32 expected_did_vid;
tpm_dev.dev = dev; tpm_dev.chip_type = tpm_vendor_chip_type(); - - chip = tpm_register_hardware(&tpm_tis_i2c); - if (chip < 0) - return -ENODEV; + chip->is_open = 1;
/* Disable interrupts (not supported) */ - chip->vendor.irq = 0; + chip->irq = 0;
/* Default timeouts */ - chip->vendor.timeout_a = TIS_SHORT_TIMEOUT; - chip->vendor.timeout_b = TIS_LONG_TIMEOUT; - chip->vendor.timeout_c = TIS_SHORT_TIMEOUT; - chip->vendor.timeout_d = TIS_SHORT_TIMEOUT; + chip->timeout_a = TIS_SHORT_TIMEOUT; + chip->timeout_b = TIS_LONG_TIMEOUT; + chip->timeout_c = TIS_SHORT_TIMEOUT; + chip->timeout_d = TIS_SHORT_TIMEOUT; + chip->req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID; + chip->req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID; + chip->req_canceled = TPM_STS_COMMAND_READY;
if (request_locality(chip, 0) < 0) return -ENODEV; @@ -887,7 +880,7 @@ int tpm_vendor_init(struct udevice *dev)
void tpm_vendor_cleanup(struct tpm_chip *chip) { - release_locality(chip, chip->vendor.locality, 1); + release_locality(chip, chip->locality, 1); }
/* Returns max number of milliseconds to wait */ @@ -906,7 +899,7 @@ static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, }
if (duration_idx != TPM_UNDEFINED) - duration = chip->vendor.duration[duration_idx]; + duration = chip->duration[duration_idx];
if (duration <= 0) return 2 * 60 * HZ; /* Two minutes timeout */ @@ -943,7 +936,7 @@ static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) goto out; }
- if (chip->vendor.irq) + if (chip->irq) goto out_recv;
start = get_timer(0); @@ -951,13 +944,13 @@ static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) do { debug("waiting for status... %ld %ld\n", start, stop); u8 status = tpm_tis_i2c_status(chip); - if ((status & chip->vendor.req_complete_mask) == - chip->vendor.req_complete_val) { + if ((status & chip->req_complete_mask) == + chip->req_complete_val) { debug("...got it;\n"); goto out_recv; }
- if (status == chip->vendor.req_canceled) { + if (status == chip->req_canceled) { error("Operation Canceled\n"); rc = -ECANCELED; goto out; @@ -1062,18 +1055,6 @@ static int tpm_decode_config(struct tpm *dev) return 0; }
-struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry) -{ - struct tpm_chip *chip; - - /* Driver specific per-device data */ - chip = &g_chip; - memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); - chip->is_open = 1; - - return chip; -} - int tis_init(void) { if (tpm.inited) diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_i2c.h index 426c519..2a4ad77 100644 --- a/drivers/tpm/tpm_tis_i2c.h +++ b/drivers/tpm/tpm_tis_i2c.h @@ -35,21 +35,17 @@ enum tpm_timeout {
struct tpm_chip;
-struct tpm_vendor_specific { - const u8 req_complete_mask; - const u8 req_complete_val; - const u8 req_canceled; +struct tpm_chip { + int is_open; + u8 req_complete_mask; + u8 req_complete_val; + u8 req_canceled; int irq; int locality; unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ unsigned long duration[3]; /* msec */ };
-struct tpm_chip { - int is_open; - struct tpm_vendor_specific vendor; -}; - struct tpm_input_header { __be16 tag; __be32 length; @@ -106,8 +102,6 @@ struct tpm_cmd_t { union tpm_cmd_params params; } __packed;
-struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *); - struct udevice; int tpm_vendor_init(struct udevice *dev);

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
This function is misnamed since it only applies to a single driver. Merge its fields into its parent.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 79 ++++++++++++++++++----------------------------- drivers/tpm/tpm_tis_i2c.h | 16 +++------- 2 files changed, 35 insertions(+), 60 deletions(-)
Applied to u-boot-dm.

There are too many structures storing the same sort of information. Move the fields from struct tpm_dev into struct tpm_chip and remove the former struct.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 52 +++++++++++++---------------------------------- drivers/tpm/tpm_tis_i2c.h | 17 ++++++++++------ 2 files changed, 25 insertions(+), 44 deletions(-)
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 3ae1a4e..81a3bb5 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -34,9 +34,6 @@
DECLARE_GLOBAL_DATA_PTR;
-/* Max buffer size supported by our tpm */ -#define TPM_DEV_BUFSIZE 1260 - /* Max number of iterations after i2c NAK */ #define MAX_COUNT 3
@@ -78,12 +75,6 @@ enum tis_defaults { #define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L #define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L
-enum i2c_chip_type { - SLB9635, - SLB9645, - UNKNOWN, -}; - static const char * const chip_name[] = { [SLB9635] = "slb9635tt", [SLB9645] = "slb9645tt", @@ -390,18 +381,8 @@ struct tpm { char inited; } tpm;
-/* Global structure for tpm chip data */ static struct tpm_chip g_chip;
-/* Structure to store I2C TPM specific stuff */ -struct tpm_dev { - struct udevice *dev; - u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)]; /* Max buffer size + addr */ - enum i2c_chip_type chip_type; -}; - -static struct tpm_dev tpm_dev; - /* * iic_tpm_read() - read from TPM register * @addr: register address to read from @@ -422,10 +403,10 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) int count; uint32_t addrbuf = addr;
- if ((tpm_dev.chip_type == SLB9635) || (tpm_dev.chip_type == UNKNOWN)) { + if ((g_chip.chip_type == SLB9635) || (g_chip.chip_type == UNKNOWN)) { /* slb9635 protocol should work in both cases */ for (count = 0; count < MAX_COUNT; count++) { - rc = dm_i2c_write(tpm_dev.dev, 0, (uchar *)&addrbuf, 1); + rc = dm_i2c_write(g_chip.dev, 0, (uchar *)&addrbuf, 1); if (rc == 0) break; /* Success, break to skip sleep */ udelay(SLEEP_DURATION); @@ -439,7 +420,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) */ for (count = 0; count < MAX_COUNT; count++) { udelay(SLEEP_DURATION); - rc = dm_i2c_read(tpm_dev.dev, 0, buffer, len); + rc = dm_i2c_read(g_chip.dev, 0, buffer, len); if (rc == 0) break; /* success, break to skip sleep */ } @@ -452,7 +433,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) * be safe on the safe side. */ for (count = 0; count < MAX_COUNT; count++) { - rc = dm_i2c_read(tpm_dev.dev, addr, buffer, len); + rc = dm_i2c_read(g_chip.dev, addr, buffer, len); if (rc == 0) break; /* break here to skip sleep */ udelay(SLEEP_DURATION); @@ -474,7 +455,7 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, int count;
for (count = 0; count < max_count; count++) { - rc = dm_i2c_write(tpm_dev.dev, addr, buffer, len); + rc = dm_i2c_write(g_chip.dev, addr, buffer, len); if (rc == 0) break; /* Success, break to skip sleep */ udelay(sleep_time); @@ -809,7 +790,7 @@ out_err: return rc; }
-static enum i2c_chip_type tpm_vendor_chip_type(void) +static enum i2c_chip_type tpm_tis_i2c_chip_type(void) { #if CONFIG_IS_ENABLED(OF_CONTROL) const void *blob = gd->fdt_blob; @@ -823,14 +804,14 @@ static enum i2c_chip_type tpm_vendor_chip_type(void) return UNKNOWN; }
-int tpm_vendor_init(struct udevice *dev) +static int tpm_tis_i2c_init(struct udevice *dev) { struct tpm_chip *chip = &g_chip; u32 vendor; u32 expected_did_vid;
- tpm_dev.dev = dev; - tpm_dev.chip_type = tpm_vendor_chip_type(); + g_chip.dev = dev; + g_chip.chip_type = tpm_tis_i2c_chip_type(); chip->is_open = 1;
/* Disable interrupts (not supported) */ @@ -854,7 +835,7 @@ int tpm_vendor_init(struct udevice *dev) return -EIO; }
- if (tpm_dev.chip_type == SLB9635) { + if (g_chip.chip_type == SLB9635) { vendor = be32_to_cpu(vendor); expected_did_vid = TPM_TIS_I2C_DID_VID_9635; } else { @@ -862,13 +843,13 @@ int tpm_vendor_init(struct udevice *dev) expected_did_vid = TPM_TIS_I2C_DID_VID_9645; }
- if (tpm_dev.chip_type != UNKNOWN && vendor != expected_did_vid) { + if (g_chip.chip_type != UNKNOWN && vendor != expected_did_vid) { error("Vendor id did not match! ID was %08x\n", vendor); return -ENODEV; }
debug("1.2 TPM (chip type %s device-id 0x%X)\n", - chip_name[tpm_dev.chip_type], vendor >> 16); + chip_name[g_chip.chip_type], vendor >> 16);
/* * A timeout query to TPM can be placed here. @@ -878,11 +859,6 @@ int tpm_vendor_init(struct udevice *dev) return 0; }
-void tpm_vendor_cleanup(struct tpm_chip *chip) -{ - release_locality(chip, chip->locality, 1); -} - /* Returns max number of milliseconds to wait */ static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) @@ -980,7 +956,7 @@ static int tpm_open_dev(struct udevice *dev) debug("%s: start\n", __func__); if (g_chip.is_open) return -EBUSY; - rc = tpm_vendor_init(dev); + rc = tpm_tis_i2c_init(dev); if (rc < 0) g_chip.is_open = 0; return rc; @@ -989,7 +965,7 @@ static int tpm_open_dev(struct udevice *dev) static void tpm_close(void) { if (g_chip.is_open) { - tpm_vendor_cleanup(&g_chip); + release_locality(&g_chip, g_chip.locality, 1); g_chip.is_open = 0; } } diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_i2c.h index 2a4ad77..0fec464 100644 --- a/drivers/tpm/tpm_tis_i2c.h +++ b/drivers/tpm/tpm_tis_i2c.h @@ -33,7 +33,14 @@ enum tpm_timeout { #define TPM_RSP_SIZE_BYTE 2 #define TPM_RSP_RC_BYTE 6
-struct tpm_chip; +/* Max buffer size supported by our tpm */ +#define TPM_DEV_BUFSIZE 1260 + +enum i2c_chip_type { + SLB9635, + SLB9645, + UNKNOWN, +};
struct tpm_chip { int is_open; @@ -44,6 +51,9 @@ struct tpm_chip { int locality; unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ unsigned long duration[3]; /* msec */ + struct udevice *dev; + u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)]; /* Max buffer size + addr */ + enum i2c_chip_type chip_type; };
struct tpm_input_header { @@ -102,9 +112,4 @@ struct tpm_cmd_t { union tpm_cmd_params params; } __packed;
-struct udevice; -int tpm_vendor_init(struct udevice *dev); - -void tpm_vendor_cleanup(struct tpm_chip *chip); - #endif

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
There are too many structures storing the same sort of information. Move the fields from struct tpm_dev into struct tpm_chip and remove the former struct.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 52 +++++++++++++---------------------------------- drivers/tpm/tpm_tis_i2c.h | 17 ++++++++++------ 2 files changed, 25 insertions(+), 44 deletions(-)
Applied to u-boot-dm.

There are too many structures storing the same sort of information. Move the fields from struct tpm into struct tpm_chip and remove the former struct.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 24 +++++++++--------------- drivers/tpm/tpm_tis_i2c.h | 1 + 2 files changed, 10 insertions(+), 15 deletions(-)
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 81a3bb5..046e282 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -375,12 +375,6 @@ static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { TPM_MEDIUM, };
-/* TPM configuration */ -struct tpm { - struct udevice *dev; - char inited; -} tpm; - static struct tpm_chip g_chip;
/* @@ -976,7 +970,7 @@ static void tpm_close(void) * @param dev Returns a configuration of TPM device * @return 0 if ok, -1 on error */ -static int tpm_decode_config(struct tpm *dev) +static int tpm_decode_config(struct tpm_chip *chip) { const void *blob = gd->fdt_blob; struct udevice *bus; @@ -1021,7 +1015,7 @@ static int tpm_decode_config(struct tpm *dev) * TODO(sjg@chromium.org): Older TPMs will need to use the older method * in iic_tpm_read() so the offset length needs to be 0 here. */ - ret = i2c_get_chip(bus, chip_addr, 1, &dev->dev); + ret = i2c_get_chip(bus, chip_addr, 1, &chip->dev); if (ret) { debug("Cannot find device for node '%s: ret=%d'\n", fdt_get_name(blob, node, NULL), ret); @@ -1033,15 +1027,15 @@ static int tpm_decode_config(struct tpm *dev)
int tis_init(void) { - if (tpm.inited) + if (g_chip.inited) return 0;
- if (tpm_decode_config(&tpm)) + if (tpm_decode_config(&g_chip)) return -1;
debug("%s: done\n", __func__);
- tpm.inited = 1; + g_chip.inited = 1;
return 0; } @@ -1050,17 +1044,17 @@ int tis_open(void) { int rc;
- if (!tpm.inited) + if (!g_chip.inited) return -1;
- rc = tpm_open_dev(tpm.dev); + rc = tpm_open_dev(g_chip.dev);
return rc; }
int tis_close(void) { - if (!tpm.inited) + if (!g_chip.inited) return -1;
tpm_close(); @@ -1074,7 +1068,7 @@ int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, int len; uint8_t buf[4096];
- if (!tpm.inited) + if (!g_chip.inited) return -1;
if (sizeof(buf) < sbuf_size) diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_i2c.h index 0fec464..161e63b 100644 --- a/drivers/tpm/tpm_tis_i2c.h +++ b/drivers/tpm/tpm_tis_i2c.h @@ -43,6 +43,7 @@ enum i2c_chip_type { };
struct tpm_chip { + bool inited; int is_open; u8 req_complete_mask; u8 req_complete_val;

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
There are too many structures storing the same sort of information. Move the fields from struct tpm into struct tpm_chip and remove the former struct.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 24 +++++++++--------------- drivers/tpm/tpm_tis_i2c.h | 1 + 2 files changed, 10 insertions(+), 15 deletions(-)
Applied to u-boot-dm.

Some definitions are in the C file and some are in the header file. Move everything into the header file for consistency and to reduce clutter.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 335 ---------------------------------------------- drivers/tpm/tpm_tis_i2c.h | 335 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 335 insertions(+), 335 deletions(-)
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 046e282..39652a9 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -34,347 +34,12 @@
DECLARE_GLOBAL_DATA_PTR;
-/* Max number of iterations after i2c NAK */ -#define MAX_COUNT 3 - -/* - * Max number of iterations after i2c NAK for 'long' commands - * - * We need this especially for sending TPM_READY, since the cleanup after the - * transtion to the ready state may take some time, but it is unpredictable - * how long it will take. - */ -#define MAX_COUNT_LONG 50 - -#define SLEEP_DURATION 60 /* in usec */ -#define SLEEP_DURATION_LONG 210 /* in usec */ - -#define TPM_HEADER_SIZE 10 - -enum tis_access { - TPM_ACCESS_VALID = 0x80, - TPM_ACCESS_ACTIVE_LOCALITY = 0x20, - TPM_ACCESS_REQUEST_PENDING = 0x04, - TPM_ACCESS_REQUEST_USE = 0x02, -}; - -enum tis_status { - TPM_STS_VALID = 0x80, - TPM_STS_COMMAND_READY = 0x40, - TPM_STS_GO = 0x20, - TPM_STS_DATA_AVAIL = 0x10, - TPM_STS_DATA_EXPECT = 0x08, -}; - -enum tis_defaults { - TIS_SHORT_TIMEOUT = 750, /* ms */ - TIS_LONG_TIMEOUT = 2000, /* ms */ -}; - -/* expected value for DIDVID register */ -#define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L -#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L - static const char * const chip_name[] = { [SLB9635] = "slb9635tt", [SLB9645] = "slb9645tt", [UNKNOWN] = "unknown/fallback to slb9635", };
-#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) -#define TPM_STS(l) (0x0001 | ((l) << 4)) -#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, -}; - static struct tpm_chip g_chip;
/* diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_i2c.h index 161e63b..db99200 100644 --- a/drivers/tpm/tpm_tis_i2c.h +++ b/drivers/tpm/tpm_tis_i2c.h @@ -113,4 +113,339 @@ struct tpm_cmd_t { union tpm_cmd_params params; } __packed;
+/* Max number of iterations after i2c NAK */ +#define MAX_COUNT 3 + +/* + * Max number of iterations after i2c NAK for 'long' commands + * + * We need this especially for sending TPM_READY, since the cleanup after the + * transtion to the ready state may take some time, but it is unpredictable + * how long it will take. + */ +#define MAX_COUNT_LONG 50 + +#define SLEEP_DURATION 60 /* in usec */ +#define SLEEP_DURATION_LONG 210 /* in usec */ + +#define TPM_HEADER_SIZE 10 + +enum tis_access { + TPM_ACCESS_VALID = 0x80, + TPM_ACCESS_ACTIVE_LOCALITY = 0x20, + TPM_ACCESS_REQUEST_PENDING = 0x04, + TPM_ACCESS_REQUEST_USE = 0x02, +}; + +enum tis_status { + TPM_STS_VALID = 0x80, + TPM_STS_COMMAND_READY = 0x40, + TPM_STS_GO = 0x20, + TPM_STS_DATA_AVAIL = 0x10, + TPM_STS_DATA_EXPECT = 0x08, +}; + +enum tis_defaults { + TIS_SHORT_TIMEOUT = 750, /* ms */ + TIS_LONG_TIMEOUT = 2000, /* ms */ +}; + +/* expected value for DIDVID register */ +#define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L +#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L + +#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) +#define TPM_STS(l) (0x0001 | ((l) << 4)) +#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

2015-08-22 18:31 GMT-06:00 Simon Glass sjg@chromium.org:
Some definitions are in the C file and some are in the header file. Move everything into the header file for consistency and to reduce clutter.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 335 ---------------------------------------------- drivers/tpm/tpm_tis_i2c.h | 335 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 335 insertions(+), 335 deletions(-)
Applied to u-boot-dm.

Move all the init and uninit code into one place.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-)
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 39652a9..9dd40dd 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -608,27 +608,6 @@ out: return rc; }
-static int tpm_open_dev(struct udevice *dev) -{ - int rc; - - debug("%s: start\n", __func__); - if (g_chip.is_open) - return -EBUSY; - rc = tpm_tis_i2c_init(dev); - if (rc < 0) - g_chip.is_open = 0; - return rc; -} - -static void tpm_close(void) -{ - if (g_chip.is_open) { - release_locality(&g_chip, g_chip.locality, 1); - g_chip.is_open = 0; - } -} - /** * Decode TPM configuration. * @@ -712,7 +691,12 @@ int tis_open(void) if (!g_chip.inited) return -1;
- rc = tpm_open_dev(g_chip.dev); + debug("%s: start\n", __func__); + if (g_chip.is_open) + return -EBUSY; + rc = tpm_tis_i2c_init(g_chip.dev); + if (rc < 0) + g_chip.is_open = 0;
return rc; } @@ -722,7 +706,10 @@ int tis_close(void) if (!g_chip.inited) return -1;
- tpm_close(); + if (g_chip.is_open) { + release_locality(&g_chip, g_chip.locality, 1); + g_chip.is_open = 0; + }
return 0; }

Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
Move all the init and uninit code into one place.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-)
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 39652a9..9dd40dd 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -608,27 +608,6 @@ out: return rc; }
-static int tpm_open_dev(struct udevice *dev) -{
- int rc;
- debug("%s: start\n", __func__);
- if (g_chip.is_open)
return -EBUSY;
- rc = tpm_tis_i2c_init(dev);
- if (rc < 0)
g_chip.is_open = 0;
- return rc;
-}
-static void tpm_close(void) -{
- if (g_chip.is_open) {
release_locality(&g_chip, g_chip.locality, 1);
g_chip.is_open = 0;
- }
-}
- /**
- Decode TPM configuration.
@@ -712,7 +691,12 @@ int tis_open(void) if (!g_chip.inited) return -1;
- rc = tpm_open_dev(g_chip.dev);
debug("%s: start\n", __func__);
if (g_chip.is_open)
return -EBUSY;
rc = tpm_tis_i2c_init(g_chip.dev);
if (rc < 0)
g_chip.is_open = 0;
return rc; }
@@ -722,7 +706,10 @@ int tis_close(void) if (!g_chip.inited) return -1;
- tpm_close();
if (g_chip.is_open) {
release_locality(&g_chip, g_chip.locality, 1);
g_chip.is_open = 0;
}
return 0; }

On 24 August 2015 at 14:20, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

Use the same prefix on each function for consistency.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com ---
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 113 ++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 55 deletions(-)
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 9dd40dd..e04e8f5 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -43,7 +43,7 @@ static const char * const chip_name[] = { static struct tpm_chip g_chip;
/* - * iic_tpm_read() - read from TPM register + * tpm_tis_i2c_read() - read from TPM register * @addr: register address to read from * @buffer: provided by caller * @len: number of bytes to read @@ -56,7 +56,7 @@ static struct tpm_chip g_chip; * * Return -EIO on error, 0 on success. */ -static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) +static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) { int rc; int count; @@ -107,8 +107,8 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) return 0; }
-static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, - unsigned int sleep_time, u8 max_count) +static int tpm_tis_i2c_write_generic(u8 addr, u8 *buffer, size_t len, + unsigned int sleep_time, u8 max_count) { int rc = 0; int count; @@ -129,7 +129,7 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, }
/* - * iic_tpm_write() - write to TPM register + * tpm_tis_i2c_write() - write to TPM register * @addr: register address to write to * @buffer: containing data to be written * @len: number of bytes to write @@ -140,13 +140,13 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, * NOTE: TPM is big-endian for multi-byte values. Multi-byte * values have to be swapped. * - * NOTE: use this function instead of the iic_tpm_write_generic function. + * NOTE: use this function instead of the tpm_tis_i2c_write_generic function. * * Return -EIO on error, 0 on success */ -static int iic_tpm_write(u8 addr, u8 *buffer, size_t len) +static int tpm_tis_i2c_write(u8 addr, u8 *buffer, size_t len) { - return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION, + return tpm_tis_i2c_write_generic(addr, buffer, len, SLEEP_DURATION, MAX_COUNT); }
@@ -154,19 +154,19 @@ static int iic_tpm_write(u8 addr, u8 *buffer, size_t len) * This function is needed especially for the cleanup situation after * sending TPM_READY */ -static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len) +static int tpm_tis_i2c_write_long(u8 addr, u8 *buffer, size_t len) { - return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG, + return tpm_tis_i2c_write_generic(addr, buffer, len, SLEEP_DURATION_LONG, MAX_COUNT_LONG); }
-static int check_locality(struct tpm_chip *chip, int loc) +static int tpm_tis_i2c_check_locality(struct tpm_chip *chip, int loc) { const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID; u8 buf; int rc;
- rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1); + rc = tpm_tis_i2c_read(TPM_ACCESS(loc), &buf, 1); if (rc < 0) return rc;
@@ -178,30 +178,31 @@ static int check_locality(struct tpm_chip *chip, int loc) return -1; }
-static void release_locality(struct tpm_chip *chip, int loc, int force) +static void tpm_tis_i2c_release_locality(struct tpm_chip *chip, int loc, + int force) { const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID; u8 buf;
- if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0) + if (tpm_tis_i2c_read(TPM_ACCESS(loc), &buf, 1) < 0) return;
if (force || (buf & mask) == mask) { buf = TPM_ACCESS_ACTIVE_LOCALITY; - iic_tpm_write(TPM_ACCESS(loc), &buf, 1); + tpm_tis_i2c_write(TPM_ACCESS(loc), &buf, 1); } }
-static int request_locality(struct tpm_chip *chip, int loc) +static int tpm_tis_i2c_request_locality(struct tpm_chip *chip, int loc) { unsigned long start, stop; u8 buf = TPM_ACCESS_REQUEST_USE; int rc;
- if (check_locality(chip, loc) >= 0) + if (tpm_tis_i2c_check_locality(chip, loc) >= 0) return loc; /* We already have the locality */
- rc = iic_tpm_write(TPM_ACCESS(loc), &buf, 1); + rc = tpm_tis_i2c_write(TPM_ACCESS(loc), &buf, 1); if (rc) return rc;
@@ -209,7 +210,7 @@ static int request_locality(struct tpm_chip *chip, int loc) start = get_timer(0); stop = chip->timeout_a; do { - if (check_locality(chip, loc) >= 0) + if (tpm_tis_i2c_check_locality(chip, loc) >= 0) return loc; udelay(TPM_TIMEOUT * 1000); } while (get_timer(start) < stop); @@ -222,7 +223,7 @@ static u8 tpm_tis_i2c_status(struct tpm_chip *chip) /* NOTE: Since i2c read may fail, return 0 in this case --> time-out */ u8 buf;
- if (iic_tpm_read(TPM_STS(chip->locality), &buf, 1) < 0) + if (tpm_tis_i2c_read(TPM_STS(chip->locality), &buf, 1) < 0) return 0; else return buf; @@ -236,12 +237,12 @@ static void tpm_tis_i2c_ready(struct tpm_chip *chip) u8 buf = TPM_STS_COMMAND_READY;
debug("%s\n", __func__); - rc = iic_tpm_write_long(TPM_STS(chip->locality), &buf, 1); + rc = tpm_tis_i2c_write_long(TPM_STS(chip->locality), &buf, 1); if (rc) debug("%s: rc=%d\n", __func__, rc); }
-static ssize_t get_burstcount(struct tpm_chip *chip) +static ssize_t tpm_tis_i2c_get_burstcount(struct tpm_chip *chip) { unsigned long start, stop; ssize_t burstcnt; @@ -254,7 +255,7 @@ static ssize_t get_burstcount(struct tpm_chip *chip) do { /* Note: STS is little endian */ addr = TPM_STS(chip->locality) + 1; - if (iic_tpm_read(addr, buf, 3) < 0) + if (tpm_tis_i2c_read(addr, buf, 3) < 0) burstcnt = 0; else burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; @@ -267,8 +268,8 @@ static ssize_t get_burstcount(struct tpm_chip *chip) return -EBUSY; }
-static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, - int *status) +static int tpm_tis_i2c_wait_for_stat(struct tpm_chip *chip, u8 mask, + unsigned long timeout, int *status) { unsigned long start, stop;
@@ -289,14 +290,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, return -ETIME; }
-static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) +static int tpm_tis_i2c_recv_data(struct tpm_chip *chip, u8 *buf, size_t count) { size_t size = 0; ssize_t burstcnt; int rc;
while (size < count) { - burstcnt = get_burstcount(chip); + burstcnt = tpm_tis_i2c_get_burstcount(chip);
/* burstcount < 0 -> tpm is busy */ if (burstcnt < 0) @@ -306,7 +307,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) if (burstcnt > (count - size)) burstcnt = count - size;
- rc = iic_tpm_read(TPM_DATA_FIFO(chip->locality), + rc = tpm_tis_i2c_read(TPM_DATA_FIFO(chip->locality), &(buf[size]), burstcnt); if (rc == 0) size += burstcnt; @@ -326,7 +327,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) }
/* Read first 10 bytes, including tag, paramsize, and result */ - size = recv_data(chip, buf, TPM_HEADER_SIZE); + size = tpm_tis_i2c_recv_data(chip, buf, TPM_HEADER_SIZE); if (size < TPM_HEADER_SIZE) { error("Unable to read header\n"); goto out; @@ -340,15 +341,16 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) goto out; }
- size += recv_data(chip, &buf[TPM_HEADER_SIZE], - expected - TPM_HEADER_SIZE); + size += tpm_tis_i2c_recv_data(chip, &buf[TPM_HEADER_SIZE], + expected - TPM_HEADER_SIZE); if (size < expected) { error("Unable to read remainder of result\n"); size = -ETIME; goto out; }
- wait_for_stat(chip, TPM_STS_VALID, chip->timeout_c, &status); + tpm_tis_i2c_wait_for_stat(chip, TPM_STS_VALID, chip->timeout_c, + &status); if (status & TPM_STS_DATA_AVAIL) { /* Retry? */ error("Error left over data\n"); size = -EIO; @@ -362,7 +364,7 @@ out: * so we sleep rather than keeping the bus busy */ udelay(2000); - release_locality(chip, chip->locality, 0); + tpm_tis_i2c_release_locality(chip, chip->locality, 0);
return size; } @@ -379,20 +381,20 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) if (len > TPM_DEV_BUFSIZE) return -E2BIG; /* Command is too long for our tpm, sorry */
- if (request_locality(chip, 0) < 0) + if (tpm_tis_i2c_request_locality(chip, 0) < 0) return -EBUSY;
status = tpm_tis_i2c_status(chip); if ((status & TPM_STS_COMMAND_READY) == 0) { tpm_tis_i2c_ready(chip); - if (wait_for_stat(chip, TPM_STS_COMMAND_READY, - chip->timeout_b, &status) < 0) { + if (tpm_tis_i2c_wait_for_stat(chip, TPM_STS_COMMAND_READY, + chip->timeout_b, &status) < 0) { rc = -ETIME; goto out_err; } }
- burstcnt = get_burstcount(chip); + burstcnt = tpm_tis_i2c_get_burstcount(chip);
/* burstcount < 0 -> tpm is busy */ if (burstcnt < 0) @@ -408,7 +410,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION; #endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */
- rc = iic_tpm_write(TPM_DATA_FIFO(chip->locality), + rc = tpm_tis_i2c_write(TPM_DATA_FIFO(chip->locality), &(buf[count]), burstcnt); if (rc == 0) count += burstcnt; @@ -418,8 +420,9 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) rc = -EIO; goto out_err; } - rc = wait_for_stat(chip, TPM_STS_VALID, - chip->timeout_c, &status); + rc = tpm_tis_i2c_wait_for_stat(chip, TPM_STS_VALID, + chip->timeout_c, + &status); if (rc) goto out_err;
@@ -431,7 +434,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) }
/* Go and do it */ - iic_tpm_write(TPM_STS(chip->locality), &sts, 1); + tpm_tis_i2c_write(TPM_STS(chip->locality), &sts, 1); debug("done\n");
return len; @@ -444,7 +447,7 @@ out_err: * so we sleep rather than keeping the bus busy */ udelay(2000); - release_locality(chip, chip->locality, 0); + tpm_tis_i2c_release_locality(chip, chip->locality, 0);
return rc; } @@ -476,7 +479,7 @@ static int tpm_tis_i2c_init(struct udevice *dev) /* Disable interrupts (not supported) */ chip->irq = 0;
- /* Default timeouts */ + /* Default timeouts - these could move to the device tree */ chip->timeout_a = TIS_SHORT_TIMEOUT; chip->timeout_b = TIS_LONG_TIMEOUT; chip->timeout_c = TIS_SHORT_TIMEOUT; @@ -485,12 +488,12 @@ static int tpm_tis_i2c_init(struct udevice *dev) chip->req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID; chip->req_canceled = TPM_STS_COMMAND_READY;
- if (request_locality(chip, 0) < 0) + if (tpm_tis_i2c_request_locality(chip, 0) < 0) return -ENODEV;
/* Read four bytes from DID_VID register */ - if (iic_tpm_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { - release_locality(chip, 0, 1); + if (tpm_tis_i2c_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { + tpm_tis_i2c_release_locality(chip, 0, 1); return -EIO; }
@@ -519,8 +522,8 @@ static int tpm_tis_i2c_init(struct udevice *dev) }
/* Returns max number of milliseconds to wait */ -static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, - u32 ordinal) +static unsigned long tpm_tis_i2c_calc_ordinal_duration(struct tpm_chip *chip, + u32 ordinal) { int duration_idx = TPM_UNDEFINED; int duration = 0; @@ -542,7 +545,7 @@ static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, return duration; }
-static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) +static ssize_t tpm_tis_i2c_transmit(const unsigned char *buf, size_t bufsiz) { int rc; u32 count, ordinal; @@ -575,7 +578,7 @@ static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) goto out_recv;
start = get_timer(0); - stop = tpm_calc_ordinal_duration(chip, ordinal); + stop = tpm_tis_i2c_calc_ordinal_duration(chip, ordinal); do { debug("waiting for status... %ld %ld\n", start, stop); u8 status = tpm_tis_i2c_status(chip); @@ -614,7 +617,7 @@ out: * @param dev Returns a configuration of TPM device * @return 0 if ok, -1 on error */ -static int tpm_decode_config(struct tpm_chip *chip) +static int tpm_tis_i2c_decode_config(struct tpm_chip *chip) { const void *blob = gd->fdt_blob; struct udevice *bus; @@ -657,7 +660,7 @@ static int tpm_decode_config(struct tpm_chip *chip) } /* * TODO(sjg@chromium.org): Older TPMs will need to use the older method - * in iic_tpm_read() so the offset length needs to be 0 here. + * in tpm_tis_i2c_read() so the offset length needs to be 0 here. */ ret = i2c_get_chip(bus, chip_addr, 1, &chip->dev); if (ret) { @@ -674,7 +677,7 @@ int tis_init(void) if (g_chip.inited) return 0;
- if (tpm_decode_config(&g_chip)) + if (tpm_tis_i2c_decode_config(&g_chip)) return -1;
debug("%s: done\n", __func__); @@ -707,7 +710,7 @@ int tis_close(void) return -1;
if (g_chip.is_open) { - release_locality(&g_chip, g_chip.locality, 1); + tpm_tis_i2c_release_locality(&g_chip, g_chip.locality, 1); g_chip.is_open = 0; }
@@ -728,7 +731,7 @@ int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
memcpy(buf, sendbuf, sbuf_size);
- len = tpm_transmit(buf, sbuf_size); + len = tpm_tis_i2c_transmit(buf, sbuf_size);
if (len < 10) { *rbuf_len = 0;

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
Use the same prefix on each function for consistency.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 113 ++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 55 deletions(-)
Applied to u-boot-dm.

Use a _US suffix for microseconds and a _MS suffic for milliseconds. Move all timeouts and delays into one place. Use mdelay() instead of udelay() where appropriate.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com ---
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 43 ++++++++++++++++++++++--------------------- drivers/tpm/tpm_tis_i2c.h | 16 ++++++---------- 2 files changed, 28 insertions(+), 31 deletions(-)
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index e04e8f5..4b2ef94 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -68,7 +68,7 @@ static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) rc = dm_i2c_write(g_chip.dev, 0, (uchar *)&addrbuf, 1); if (rc == 0) break; /* Success, break to skip sleep */ - udelay(SLEEP_DURATION); + udelay(SLEEP_DURATION_US); } if (rc) return -rc; @@ -78,7 +78,7 @@ static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) * retrieving the data */ for (count = 0; count < MAX_COUNT; count++) { - udelay(SLEEP_DURATION); + udelay(SLEEP_DURATION_US); rc = dm_i2c_read(g_chip.dev, 0, buffer, len); if (rc == 0) break; /* success, break to skip sleep */ @@ -95,12 +95,12 @@ static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) rc = dm_i2c_read(g_chip.dev, addr, buffer, len); if (rc == 0) break; /* break here to skip sleep */ - udelay(SLEEP_DURATION); + udelay(SLEEP_DURATION_US); } }
/* Take care of 'guard time' */ - udelay(SLEEP_DURATION); + udelay(SLEEP_DURATION_US); if (rc) return -rc;
@@ -108,7 +108,7 @@ static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) }
static int tpm_tis_i2c_write_generic(u8 addr, u8 *buffer, size_t len, - unsigned int sleep_time, u8 max_count) + unsigned int sleep_time_us, u8 max_count) { int rc = 0; int count; @@ -117,11 +117,11 @@ static int tpm_tis_i2c_write_generic(u8 addr, u8 *buffer, size_t len, rc = dm_i2c_write(g_chip.dev, addr, buffer, len); if (rc == 0) break; /* Success, break to skip sleep */ - udelay(sleep_time); + udelay(sleep_time_us); }
/* take care of 'guard time' */ - udelay(sleep_time); + udelay(sleep_time_us); if (rc) return -rc;
@@ -146,8 +146,8 @@ static int tpm_tis_i2c_write_generic(u8 addr, u8 *buffer, size_t len, */ static int tpm_tis_i2c_write(u8 addr, u8 *buffer, size_t len) { - return tpm_tis_i2c_write_generic(addr, buffer, len, SLEEP_DURATION, - MAX_COUNT); + return tpm_tis_i2c_write_generic(addr, buffer, len, SLEEP_DURATION_US, + MAX_COUNT); }
/* @@ -156,8 +156,9 @@ static int tpm_tis_i2c_write(u8 addr, u8 *buffer, size_t len) */ static int tpm_tis_i2c_write_long(u8 addr, u8 *buffer, size_t len) { - return tpm_tis_i2c_write_generic(addr, buffer, len, SLEEP_DURATION_LONG, - MAX_COUNT_LONG); + return tpm_tis_i2c_write_generic(addr, buffer, len, + SLEEP_DURATION_LONG_US, + MAX_COUNT_LONG); }
static int tpm_tis_i2c_check_locality(struct tpm_chip *chip, int loc) @@ -212,7 +213,7 @@ static int tpm_tis_i2c_request_locality(struct tpm_chip *chip, int loc) do { if (tpm_tis_i2c_check_locality(chip, loc) >= 0) return loc; - udelay(TPM_TIMEOUT * 1000); + mdelay(TPM_TIMEOUT_MS); } while (get_timer(start) < stop);
return -1; @@ -262,7 +263,7 @@ static ssize_t tpm_tis_i2c_get_burstcount(struct tpm_chip *chip)
if (burstcnt) return burstcnt; - udelay(TPM_TIMEOUT * 1000); + mdelay(TPM_TIMEOUT_MS); } while (get_timer(start) < stop);
return -EBUSY; @@ -281,7 +282,7 @@ static int tpm_tis_i2c_wait_for_stat(struct tpm_chip *chip, u8 mask, start = get_timer(0); stop = timeout; do { - udelay(TPM_TIMEOUT * 1000); + mdelay(TPM_TIMEOUT_MS); *status = tpm_tis_i2c_status(chip); if ((*status & mask) == mask) return 0; @@ -363,7 +364,7 @@ out: * The TPM needs some time to clean up here, * so we sleep rather than keeping the bus busy */ - udelay(2000); + mdelay(2); tpm_tis_i2c_release_locality(chip, chip->locality, 0);
return size; @@ -446,7 +447,7 @@ out_err: * The TPM needs some time to clean up here, * so we sleep rather than keeping the bus busy */ - udelay(2000); + mdelay(2); tpm_tis_i2c_release_locality(chip, chip->locality, 0);
return rc; @@ -480,10 +481,10 @@ static int tpm_tis_i2c_init(struct udevice *dev) chip->irq = 0;
/* Default timeouts - these could move to the device tree */ - chip->timeout_a = TIS_SHORT_TIMEOUT; - chip->timeout_b = TIS_LONG_TIMEOUT; - chip->timeout_c = TIS_SHORT_TIMEOUT; - chip->timeout_d = TIS_SHORT_TIMEOUT; + chip->timeout_a = TIS_SHORT_TIMEOUT_MS; + chip->timeout_b = TIS_LONG_TIMEOUT_MS; + chip->timeout_c = TIS_SHORT_TIMEOUT_MS; + chip->timeout_d = TIS_SHORT_TIMEOUT_MS; chip->req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID; chip->req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID; chip->req_canceled = TPM_STS_COMMAND_READY; @@ -593,7 +594,7 @@ static ssize_t tpm_tis_i2c_transmit(const unsigned char *buf, size_t bufsiz) rc = -ECANCELED; goto out; } - udelay(TPM_TIMEOUT * 1000); + mdelay(TPM_TIMEOUT_MS); } while (get_timer(start) < stop);
tpm_tis_i2c_ready(chip); diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_i2c.h index db99200..ecdaf0c 100644 --- a/drivers/tpm/tpm_tis_i2c.h +++ b/drivers/tpm/tpm_tis_i2c.h @@ -23,7 +23,11 @@ #include <linux/types.h>
enum tpm_timeout { - TPM_TIMEOUT = 5, /* msecs */ + TPM_TIMEOUT_MS = 5, + TIS_SHORT_TIMEOUT_MS = 750, + TIS_LONG_TIMEOUT_MS = 2000, + SLEEP_DURATION_US = 60, + SLEEP_DURATION_LONG_US = 210, };
/* Size of external transmit buffer (used in tpm_transmit)*/ @@ -125,9 +129,6 @@ struct tpm_cmd_t { */ #define MAX_COUNT_LONG 50
-#define SLEEP_DURATION 60 /* in usec */ -#define SLEEP_DURATION_LONG 210 /* in usec */ - #define TPM_HEADER_SIZE 10
enum tis_access { @@ -145,11 +146,6 @@ enum tis_status { TPM_STS_DATA_EXPECT = 0x08, };
-enum tis_defaults { - TIS_SHORT_TIMEOUT = 750, /* ms */ - TIS_LONG_TIMEOUT = 2000, /* ms */ -}; - /* expected value for DIDVID register */ #define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L #define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L @@ -169,7 +165,7 @@ enum tpm_duration { /* Extended error numbers from linux (see errno.h) */ #define ECANCELED 125 /* Operation Canceled */
-/* Timer frequency. Corresponds to msec timer resolution*/ +/* Timer frequency. Corresponds to msec timer resolution */ #define HZ 1000
#define TPM_MAX_ORDINAL 243

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
Use a _US suffix for microseconds and a _MS suffic for milliseconds. Move all timeouts and delays into one place. Use mdelay() instead of udelay() where appropriate.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2: None
drivers/tpm/tpm_tis_i2c.c | 43 ++++++++++++++++++++++--------------------- drivers/tpm/tpm_tis_i2c.h | 16 ++++++---------- 2 files changed, 28 insertions(+), 31 deletions(-)
Applied to u-boot-dm.

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@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@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. *

Hi Simon,
This one looks good to me as well.
Acked-by: Christophe Ricardchristophe-h.ricard@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@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@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.

On 24 August 2015 at 14:21, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
This one looks good to me as well. Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

Add driver model support to the TPM command and the TPM library. Both support only a single TPM at present.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Correct error checking code in tpm_sendrecv_command() - Use tpm_ prefix instead of tis_ for TPM functions
common/cmd_tpm.c | 26 ++++++++++++++++++++++++++ include/tpm.h | 2 +- lib/tpm.c | 31 ++++++++++++++++++++++++++----- 3 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index 0294952..bad2006 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -6,6 +6,7 @@
#include <common.h> #include <command.h> +#include <dm.h> #include <malloc.h> #include <tpm.h> #include <asm/unaligned.h> @@ -438,6 +439,21 @@ TPM_COMMAND_NO_ARG(tpm_force_clear) TPM_COMMAND_NO_ARG(tpm_physical_enable) TPM_COMMAND_NO_ARG(tpm_physical_disable)
+#ifdef CONFIG_DM_TPM +static int get_tpm(struct udevice **devp) +{ + int rc; + + rc = uclass_first_device(UCLASS_TPM, devp); + if (rc) { + printf("Could not find TPM (ret=%d)\n", rc); + return CMD_RET_FAILURE; + } + + return 0; +} +#endif + static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -452,7 +468,17 @@ static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, return CMD_RET_FAILURE; }
+#ifdef CONFIG_DM_TPM + struct udevice *dev; + + rc = get_tpm(&dev); + if (rc) + return rc; + + rc = tpm_xfer(dev, command, count, response, &response_length); +#else rc = tis_sendrecv(command, count, response, &response_length); +#endif free(command); if (!rc) { puts("tpm response:\n"); diff --git a/include/tpm.h b/include/tpm.h index e4472d3..445952b 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -349,7 +349,7 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size, * * @return 0 on success, non-0 on error. */ -uint32_t tpm_init(void); +int tpm_init(void);
/** * Issue a TPM_Startup command. diff --git a/lib/tpm.c b/lib/tpm.c index d9789b0..19bf0b5 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -6,10 +6,11 @@ */
#include <common.h> -#include <stdarg.h> -#include <u-boot/sha1.h> +#include <dm.h> +#include <tis.h> #include <tpm.h> #include <asm/unaligned.h> +#include <u-boot/sha1.h>
/* Internal error of TPM command library */ #define TPM_LIB_ERROR ((uint32_t)~0u) @@ -240,9 +241,20 @@ static uint32_t tpm_sendrecv_command(const void *command, response = response_buffer; response_length = sizeof(response_buffer); } +#ifdef CONFIG_DM_TPM + struct udevice *dev; + int ret; + + ret = uclass_first_device(UCLASS_TPM, &dev); + if (ret) + return ret; + err = tpm_xfer(dev, command, tpm_command_size(command), + response, &response_length); +#else err = tis_sendrecv(command, tpm_command_size(command), response, &response_length); - if (err) +#endif + if (err < 0) return TPM_LIB_ERROR; if (size_ptr) *size_ptr = response_length; @@ -250,15 +262,24 @@ static uint32_t tpm_sendrecv_command(const void *command, return tpm_return_code(response); }
-uint32_t tpm_init(void) +int tpm_init(void) { - uint32_t err; + int err;
+#ifdef CONFIG_DM_TPM + struct udevice *dev; + + err = uclass_first_device(UCLASS_TPM, &dev); + if (err) + return err; + return tpm_open(dev); +#else err = tis_init(); if (err) return err;
return tis_open(); +#endif }
uint32_t tpm_startup(enum tpm_startup_type mode)

Hi Simon,
This one looks good to me. Actually, i think atmel driver is trivial to move to driver model following the current TPM class. I would assume this will be changed very soon.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
Add driver model support to the TPM command and the TPM library. Both support only a single TPM at present.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
Correct error checking code in tpm_sendrecv_command()
Use tpm_ prefix instead of tis_ for TPM functions
common/cmd_tpm.c | 26 ++++++++++++++++++++++++++ include/tpm.h | 2 +- lib/tpm.c | 31 ++++++++++++++++++++++++++----- 3 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index 0294952..bad2006 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -6,6 +6,7 @@
#include <common.h> #include <command.h> +#include <dm.h> #include <malloc.h> #include <tpm.h> #include <asm/unaligned.h> @@ -438,6 +439,21 @@ TPM_COMMAND_NO_ARG(tpm_force_clear) TPM_COMMAND_NO_ARG(tpm_physical_enable) TPM_COMMAND_NO_ARG(tpm_physical_disable)
+#ifdef CONFIG_DM_TPM +static int get_tpm(struct udevice **devp) +{
- int rc;
- rc = uclass_first_device(UCLASS_TPM, devp);
- if (rc) {
printf("Could not find TPM (ret=%d)\n", rc);
return CMD_RET_FAILURE;
- }
- return 0;
+} +#endif
- static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
@@ -452,7 +468,17 @@ static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, return CMD_RET_FAILURE; }
+#ifdef CONFIG_DM_TPM
- struct udevice *dev;
- rc = get_tpm(&dev);
- if (rc)
return rc;
- rc = tpm_xfer(dev, command, count, response, &response_length);
+#else rc = tis_sendrecv(command, count, response, &response_length); +#endif free(command); if (!rc) { puts("tpm response:\n"); diff --git a/include/tpm.h b/include/tpm.h index e4472d3..445952b 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -349,7 +349,7 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size,
- @return 0 on success, non-0 on error.
*/ -uint32_t tpm_init(void); +int tpm_init(void);
/**
- Issue a TPM_Startup command.
diff --git a/lib/tpm.c b/lib/tpm.c index d9789b0..19bf0b5 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -6,10 +6,11 @@ */
#include <common.h> -#include <stdarg.h> -#include <u-boot/sha1.h> +#include <dm.h> +#include <tis.h> #include <tpm.h> #include <asm/unaligned.h> +#include <u-boot/sha1.h>
/* Internal error of TPM command library */ #define TPM_LIB_ERROR ((uint32_t)~0u) @@ -240,9 +241,20 @@ static uint32_t tpm_sendrecv_command(const void *command, response = response_buffer; response_length = sizeof(response_buffer); } +#ifdef CONFIG_DM_TPM
- struct udevice *dev;
- int ret;
- ret = uclass_first_device(UCLASS_TPM, &dev);
- if (ret)
return ret;
- err = tpm_xfer(dev, command, tpm_command_size(command),
response, &response_length);
+#else err = tis_sendrecv(command, tpm_command_size(command), response, &response_length);
- if (err)
+#endif
- if (err < 0) return TPM_LIB_ERROR; if (size_ptr) *size_ptr = response_length;
@@ -250,15 +262,24 @@ static uint32_t tpm_sendrecv_command(const void *command, return tpm_return_code(response); }
-uint32_t tpm_init(void) +int tpm_init(void) {
- uint32_t err;
- int err;
+#ifdef CONFIG_DM_TPM
- struct udevice *dev;
- err = uclass_first_device(UCLASS_TPM, &dev);
- if (err)
return err;
- return tpm_open(dev);
+#else err = tis_init(); if (err) return err;
return tis_open(); +#endif }
uint32_t tpm_startup(enum tpm_startup_type mode)

+Dirk
On 24 August 2015 at 14:21, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
This one looks good to me. Actually, i think atmel driver is trivial to move to driver model following the current TPM class. I would assume this will be changed very soon.
Actually, yes we should do this soon to and drop the pre-driver-model stuff. The problem is that we need device tree for the I2C port and I can't test it.
Perhaps Dirk (on Cc) can take a look?
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

I2C chips can support a register offset, with registers accessible by sending this offset as the first part of any read or write transaction. Most I2C chips have a single byte offset, thus the offset length is 1. This provides access for up 256 registers.
However other offset lengths are supported, including 0.
Add a command to provide access to the offset length from the command line. This allows the offset length to be read or written.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/cmd_i2c.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index 1bc0db8..864b259 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -453,6 +453,37 @@ static int do_i2c_flags(cmd_tbl_t *cmdtp, int flag, int argc,
return 0; } + +static int do_i2c_olen(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + struct udevice *dev; + uint olen; + int chip; + int ret; + + if (argc < 2) + return CMD_RET_USAGE; + + chip = simple_strtoul(argv[1], NULL, 16); + ret = i2c_get_cur_bus_chip(chip, &dev); + if (ret) + return i2c_report_err(ret, I2C_ERR_READ); + + if (argc > 2) { + olen = simple_strtoul(argv[2], NULL, 16); + ret = i2c_set_chip_offset_len(dev, olen); + } else { + ret = i2c_get_chip_offset_len(dev); + if (ret >= 0) { + printf("%x\n", ret); + ret = 0; + } + } + if (ret) + return i2c_report_err(ret, I2C_ERR_READ); + + return 0; +} #endif
/** @@ -1903,6 +1934,7 @@ static cmd_tbl_t cmd_i2c_sub[] = { U_BOOT_CMD_MKENT(write, 6, 0, do_i2c_write, "", ""), #ifdef CONFIG_DM_I2C U_BOOT_CMD_MKENT(flags, 2, 1, do_i2c_flags, "", ""), + U_BOOT_CMD_MKENT(olen, 2, 1, do_i2c_olen, "", ""), #endif U_BOOT_CMD_MKENT(reset, 0, 1, do_i2c_reset, "", ""), #if defined(CONFIG_CMD_SDRAM) @@ -1971,6 +2003,7 @@ static char i2c_help_text[] = " to I2C; the -s option selects bulk write in a single transaction\n" #ifdef CONFIG_DM_I2C "i2c flags chip [flags] - set or get chip flags\n" + "i2c olen chip [offset_length] - set or get chip offset length\n" #endif "i2c reset - re-init the I2C Controller\n" #if defined(CONFIG_CMD_SDRAM)

Hi Simon,
This one is fine with me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
I2C chips can support a register offset, with registers accessible by sending this offset as the first part of any read or write transaction. Most I2C chips have a single byte offset, thus the offset length is 1. This provides access for up 256 registers.
However other offset lengths are supported, including 0.
Add a command to provide access to the offset length from the command line. This allows the offset length to be read or written.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/cmd_i2c.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index 1bc0db8..864b259 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -453,6 +453,37 @@ static int do_i2c_flags(cmd_tbl_t *cmdtp, int flag, int argc,
return 0; }
+static int do_i2c_olen(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{
- struct udevice *dev;
- uint olen;
- int chip;
- int ret;
- if (argc < 2)
return CMD_RET_USAGE;
- chip = simple_strtoul(argv[1], NULL, 16);
- ret = i2c_get_cur_bus_chip(chip, &dev);
- if (ret)
return i2c_report_err(ret, I2C_ERR_READ);
- if (argc > 2) {
olen = simple_strtoul(argv[2], NULL, 16);
ret = i2c_set_chip_offset_len(dev, olen);
- } else {
ret = i2c_get_chip_offset_len(dev);
if (ret >= 0) {
printf("%x\n", ret);
ret = 0;
}
- }
- if (ret)
return i2c_report_err(ret, I2C_ERR_READ);
- return 0;
+} #endif
/** @@ -1903,6 +1934,7 @@ static cmd_tbl_t cmd_i2c_sub[] = { U_BOOT_CMD_MKENT(write, 6, 0, do_i2c_write, "", ""), #ifdef CONFIG_DM_I2C U_BOOT_CMD_MKENT(flags, 2, 1, do_i2c_flags, "", ""),
- U_BOOT_CMD_MKENT(olen, 2, 1, do_i2c_olen, "", ""), #endif U_BOOT_CMD_MKENT(reset, 0, 1, do_i2c_reset, "", ""), #if defined(CONFIG_CMD_SDRAM)
@@ -1971,6 +2003,7 @@ static char i2c_help_text[] = " to I2C; the -s option selects bulk write in a single transaction\n" #ifdef CONFIG_DM_I2C "i2c flags chip [flags] - set or get chip flags\n"
- "i2c olen chip [offset_length] - set or get chip offset length\n" #endif "i2c reset - re-init the I2C Controller\n" #if defined(CONFIG_CMD_SDRAM)

On 24 August 2015 at 14:21, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
This one is fine with me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

When a 'tpm' command fails, we set the return code but give no indication of failure. This can be confusing.
Add an error message when any tpm command fails.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Correct error-checking code in report_return_code()
common/cmd_tpm.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index bad2006..65e7371 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -80,17 +80,19 @@ static void *parse_byte_string(char *bytes, uint8_t *data, size_t *count_ptr) }
/** - * Convert TPM command return code to U-Boot command error codes. + * report_return_code() - Report any error and return failure or success * * @param return_code TPM command return code * @return value of enum command_ret_t */ -static int convert_return_code(uint32_t return_code) +static int report_return_code(int return_code) { - if (return_code) + if (return_code) { + printf("Error: %d\n", return_code); return CMD_RET_FAILURE; - else + } else { return CMD_RET_SUCCESS; + } }
/** @@ -252,7 +254,7 @@ static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag, return CMD_RET_FAILURE; }
- return convert_return_code(tpm_startup(mode)); + return report_return_code(tpm_startup(mode)); }
static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag, @@ -266,7 +268,7 @@ static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag, perm = simple_strtoul(argv[2], NULL, 0); size = simple_strtoul(argv[3], NULL, 0);
- return convert_return_code(tpm_nv_define_space(index, perm, size)); + return report_return_code(tpm_nv_define_space(index, perm, size)); }
static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag, @@ -287,7 +289,7 @@ static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag, print_byte_string(data, count); }
- return convert_return_code(rc); + return report_return_code(rc); }
static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag, @@ -309,7 +311,7 @@ static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag, rc = tpm_nv_write_value(index, data, count); free(data);
- return convert_return_code(rc); + return report_return_code(rc); }
static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, @@ -332,7 +334,7 @@ static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, print_byte_string(out_digest, sizeof(out_digest)); }
- return convert_return_code(rc); + return report_return_code(rc); }
static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag, @@ -353,7 +355,7 @@ static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag, print_byte_string(data, count); }
- return convert_return_code(rc); + return report_return_code(rc); }
static int do_tpm_tsc_physical_presence(cmd_tbl_t *cmdtp, int flag, @@ -365,7 +367,7 @@ static int do_tpm_tsc_physical_presence(cmd_tbl_t *cmdtp, int flag, return CMD_RET_USAGE; presence = (uint16_t)simple_strtoul(argv[1], NULL, 0);
- return convert_return_code(tpm_tsc_physical_presence(presence)); + return report_return_code(tpm_tsc_physical_presence(presence)); }
static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag, @@ -385,7 +387,7 @@ static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag, print_byte_string(data, count); }
- return convert_return_code(rc); + return report_return_code(rc); }
static int do_tpm_physical_set_deactivated(cmd_tbl_t *cmdtp, int flag, @@ -397,7 +399,7 @@ static int do_tpm_physical_set_deactivated(cmd_tbl_t *cmdtp, int flag, return CMD_RET_USAGE; state = (uint8_t)simple_strtoul(argv[1], NULL, 0);
- return convert_return_code(tpm_physical_set_deactivated(state)); + return report_return_code(tpm_physical_set_deactivated(state)); }
static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag, @@ -420,7 +422,7 @@ static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag, print_byte_string(cap, count); }
- return convert_return_code(rc); + return report_return_code(rc); }
#define TPM_COMMAND_NO_ARG(cmd) \ @@ -429,7 +431,7 @@ static int do_##cmd(cmd_tbl_t *cmdtp, int flag, \ { \ if (argc != 1) \ return CMD_RET_USAGE; \ - return convert_return_code(cmd()); \ + return report_return_code(cmd()); \ }
TPM_COMMAND_NO_ARG(tpm_init) @@ -485,7 +487,7 @@ static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, print_byte_string(response, response_length); }
- return convert_return_code(rc); + return report_return_code(rc); }
static int do_tpm_nv_define(cmd_tbl_t *cmdtp, int flag, @@ -503,7 +505,7 @@ static int do_tpm_nv_define(cmd_tbl_t *cmdtp, int flag, index = simple_strtoul(argv[2], NULL, 0); perm = simple_strtoul(argv[3], NULL, 0);
- return convert_return_code(tpm_nv_define_space(index, perm, size)); + return report_return_code(tpm_nv_define_space(index, perm, size)); }
static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag, @@ -532,7 +534,7 @@ static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag, } free(data);
- return convert_return_code(err); + return report_return_code(err); }
static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag, @@ -560,7 +562,7 @@ static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag, err = tpm_nv_write_value(index, data, count); free(data);
- return convert_return_code(err); + return report_return_code(err); }
#ifdef CONFIG_TPM_AUTH_SESSIONS @@ -572,7 +574,7 @@ static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag,
err = tpm_oiap(&auth_handle);
- return convert_return_code(err); + return report_return_code(err); }
static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag, @@ -597,7 +599,7 @@ static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag, if (!err) printf("Key handle is 0x%x\n", key_handle);
- return convert_return_code(err); + return report_return_code(err); }
static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag, @@ -622,7 +624,7 @@ static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag, printf("dump of received pub key structure:\n"); print_byte_string(pub_key_buffer, pub_key_len); } - return convert_return_code(err); + return report_return_code(err); }
TPM_COMMAND_NO_ARG(tpm_end_oiap)

Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
When a 'tpm' command fails, we set the return code but give no indication of failure. This can be confusing.
Add an error message when any tpm command fails.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
Correct error-checking code in report_return_code()
common/cmd_tpm.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index bad2006..65e7371 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -80,17 +80,19 @@ static void *parse_byte_string(char *bytes, uint8_t *data, size_t *count_ptr) }
/**
- Convert TPM command return code to U-Boot command error codes.
*/
- report_return_code() - Report any error and return failure or success
- @param return_code TPM command return code
- @return value of enum command_ret_t
-static int convert_return_code(uint32_t return_code) +static int report_return_code(int return_code) {
- if (return_code)
- if (return_code) {
return CMD_RET_FAILURE;printf("Error: %d\n", return_code);
- else
} else { return CMD_RET_SUCCESS;
} }
/**
@@ -252,7 +254,7 @@ static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag, return CMD_RET_FAILURE; }
- return convert_return_code(tpm_startup(mode));
return report_return_code(tpm_startup(mode)); }
static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag,
@@ -266,7 +268,7 @@ static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag, perm = simple_strtoul(argv[2], NULL, 0); size = simple_strtoul(argv[3], NULL, 0);
- return convert_return_code(tpm_nv_define_space(index, perm, size));
return report_return_code(tpm_nv_define_space(index, perm, size)); }
static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag,
@@ -287,7 +289,7 @@ static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag, print_byte_string(data, count); }
- return convert_return_code(rc);
return report_return_code(rc); }
static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag,
@@ -309,7 +311,7 @@ static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag, rc = tpm_nv_write_value(index, data, count); free(data);
- return convert_return_code(rc);
return report_return_code(rc); }
static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag,
@@ -332,7 +334,7 @@ static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, print_byte_string(out_digest, sizeof(out_digest)); }
- return convert_return_code(rc);
return report_return_code(rc); }
static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag,
@@ -353,7 +355,7 @@ static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag, print_byte_string(data, count); }
- return convert_return_code(rc);
return report_return_code(rc); }
static int do_tpm_tsc_physical_presence(cmd_tbl_t *cmdtp, int flag,
@@ -365,7 +367,7 @@ static int do_tpm_tsc_physical_presence(cmd_tbl_t *cmdtp, int flag, return CMD_RET_USAGE; presence = (uint16_t)simple_strtoul(argv[1], NULL, 0);
- return convert_return_code(tpm_tsc_physical_presence(presence));
return report_return_code(tpm_tsc_physical_presence(presence)); }
static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag,
@@ -385,7 +387,7 @@ static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag, print_byte_string(data, count); }
- return convert_return_code(rc);
return report_return_code(rc); }
static int do_tpm_physical_set_deactivated(cmd_tbl_t *cmdtp, int flag,
@@ -397,7 +399,7 @@ static int do_tpm_physical_set_deactivated(cmd_tbl_t *cmdtp, int flag, return CMD_RET_USAGE; state = (uint8_t)simple_strtoul(argv[1], NULL, 0);
- return convert_return_code(tpm_physical_set_deactivated(state));
return report_return_code(tpm_physical_set_deactivated(state)); }
static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag,
@@ -420,7 +422,7 @@ static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag, print_byte_string(cap, count); }
- return convert_return_code(rc);
return report_return_code(rc); }
#define TPM_COMMAND_NO_ARG(cmd) \
@@ -429,7 +431,7 @@ static int do_##cmd(cmd_tbl_t *cmdtp, int flag, \ { \ if (argc != 1) \ return CMD_RET_USAGE; \
- return convert_return_code(cmd()); \
return report_return_code(cmd()); \ }
TPM_COMMAND_NO_ARG(tpm_init)
@@ -485,7 +487,7 @@ static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, print_byte_string(response, response_length); }
- return convert_return_code(rc);
return report_return_code(rc); }
static int do_tpm_nv_define(cmd_tbl_t *cmdtp, int flag,
@@ -503,7 +505,7 @@ static int do_tpm_nv_define(cmd_tbl_t *cmdtp, int flag, index = simple_strtoul(argv[2], NULL, 0); perm = simple_strtoul(argv[3], NULL, 0);
- return convert_return_code(tpm_nv_define_space(index, perm, size));
return report_return_code(tpm_nv_define_space(index, perm, size)); }
static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag,
@@ -532,7 +534,7 @@ static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag, } free(data);
- return convert_return_code(err);
return report_return_code(err); }
static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag,
@@ -560,7 +562,7 @@ static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag, err = tpm_nv_write_value(index, data, count); free(data);
- return convert_return_code(err);
return report_return_code(err); }
#ifdef CONFIG_TPM_AUTH_SESSIONS
@@ -572,7 +574,7 @@ static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag,
err = tpm_oiap(&auth_handle);
- return convert_return_code(err);
return report_return_code(err); }
static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag,
@@ -597,7 +599,7 @@ static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag, if (!err) printf("Key handle is 0x%x\n", key_handle);
- return convert_return_code(err);
return report_return_code(err); }
static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag,
@@ -622,7 +624,7 @@ static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag, printf("dump of received pub key structure:\n"); print_byte_string(pub_key_buffer, pub_key_len); }
- return convert_return_code(err);
return report_return_code(err); }
TPM_COMMAND_NO_ARG(tpm_end_oiap)

On 24 August 2015 at 14:21, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

Convert the sandbox TPM driver to use driver model. Add it to the device tree so that it can be found on start-up.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com ---
Changes in v2: - Implement the get_desc() method - Include tpm.h header file instead of tis.h
arch/sandbox/dts/sandbox.dts | 4 +++ configs/sandbox_defconfig | 1 + drivers/tpm/tpm_tis_sandbox.c | 57 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 50 insertions(+), 12 deletions(-)
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts index 8927527..758c4a5 100644 --- a/arch/sandbox/dts/sandbox.dts +++ b/arch/sandbox/dts/sandbox.dts @@ -156,6 +156,10 @@ sides = <4>; };
+ tpm { + compatible = "google,sandbox-tpm"; + }; + triangle { compatible = "demo-shape"; colour = "cyan"; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index b68d688..2600bf7 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -31,6 +31,7 @@ CONFIG_CROS_EC_KEYB=y CONFIG_LED=y CONFIG_LED_GPIO=y CONFIG_SANDBOX_SERIAL=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_SANDBOX=y CONFIG_SYS_I2C_SANDBOX=y CONFIG_SANDBOX_SPI=y diff --git a/drivers/tpm/tpm_tis_sandbox.c b/drivers/tpm/tpm_tis_sandbox.c index ed4b039..9ea9807 100644 --- a/drivers/tpm/tpm_tis_sandbox.c +++ b/drivers/tpm/tpm_tis_sandbox.c @@ -5,6 +5,8 @@ */
#include <common.h> +#include <dm.h> +#include <tpm.h> #include <asm/state.h> #include <asm/unaligned.h> #include <linux/crc8.h> @@ -56,7 +58,7 @@ enum { */ static struct tpm_state { uint8_t nvdata[NV_SEQ_COUNT][NV_DATA_SIZE]; -} state; +} g_state;
/** * sandbox_tpm_read_state() - read the sandbox EC state from the state file @@ -82,7 +84,7 @@ static int sandbox_tpm_read_state(const void *blob, int node) sprintf(prop_name, "nvdata%d", i); prop = fdt_getprop(blob, node, prop_name, &len); if (prop && len == NV_DATA_SIZE) - memcpy(state.nvdata[i], prop, NV_DATA_SIZE); + memcpy(g_state.nvdata[i], prop, NV_DATA_SIZE); }
return 0; @@ -110,7 +112,7 @@ static int sandbox_tpm_write_state(void *blob, int node) char prop_name[20];
sprintf(prop_name, "nvdata%d", i); - fdt_setprop(blob, node, prop_name, state.nvdata[i], + fdt_setprop(blob, node, prop_name, g_state.nvdata[i], NV_DATA_SIZE); }
@@ -135,10 +137,11 @@ static int index_to_seq(uint32_t index) return -1; }
-int tis_sendrecv(const u8 *sendbuf, size_t send_size, - u8 *recvbuf, size_t *recv_len) +static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, + size_t send_size, uint8_t *recvbuf, + size_t *recv_len) { - struct tpm_state *tpm = &state; + struct tpm_state *tpm = dev_get_priv(dev); uint32_t code, index, length, type; uint8_t *data; int seq; @@ -241,20 +244,50 @@ int tis_sendrecv(const u8 *sendbuf, size_t send_size, return 0; }
-int tis_open(void) +static int sandbox_tpm_get_desc(struct udevice *dev, char *buf, int size) { - printf("%s\n", __func__); + if (size < 15) + return -ENOSPC; + + return snprintf(buf, size, "sandbox TPM"); +} + +static int sandbox_tpm_probe(struct udevice *dev) +{ + struct tpm_state *tpm = dev_get_priv(dev); + + memcpy(tpm, &g_state, sizeof(*tpm)); + return 0; }
-int tis_close(void) +static int sandbox_tpm_open(struct udevice *dev) { - printf("%s\n", __func__); return 0; }
-int tis_init(void) +static int sandbox_tpm_close(struct udevice *dev) { - printf("%s\n", __func__); return 0; } + +static const struct tpm_ops sandbox_tpm_ops = { + .open = sandbox_tpm_open, + .close = sandbox_tpm_close, + .get_desc = sandbox_tpm_get_desc, + .xfer = sandbox_tpm_xfer, +}; + +static const struct udevice_id sandbox_tpm_ids[] = { + { .compatible = "google,sandbox-tpm" }, + { } +}; + +U_BOOT_DRIVER(sandbox_tpm) = { + .name = "sandbox_tpm", + .id = UCLASS_TPM, + .of_match = sandbox_tpm_ids, + .ops = &sandbox_tpm_ops, + .probe = sandbox_tpm_probe, + .priv_auto_alloc_size = sizeof(struct tpm_state), +};

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
Convert the sandbox TPM driver to use driver model. Add it to the device tree so that it can be found on start-up.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2:
- Implement the get_desc() method
- Include tpm.h header file instead of tis.h
arch/sandbox/dts/sandbox.dts | 4 +++ configs/sandbox_defconfig | 1 + drivers/tpm/tpm_tis_sandbox.c | 57 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 50 insertions(+), 12 deletions(-)
Applied to u-boot-dm.

Rather then crashing when there is no data, print an error.
Acked-by: Christophe Ricard christophe-h.ricard@st.com Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/cmd_tpm.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index 65e7371..e9c6618 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -58,6 +58,8 @@ static void *parse_byte_string(char *bytes, uint8_t *data, size_t *count_ptr) size_t count, length; int i;
+ if (!bytes) + return NULL; length = strlen(bytes); count = length / 2;

Hi Simon,
Print an error ? Are you sure ? I guess the comment is not accurate ;).
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
Rather then crashing when there is no data, print an error.
Acked-by: Christophe Ricard christophe-h.ricard@st.com Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/cmd_tpm.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index 65e7371..e9c6618 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -58,6 +58,8 @@ static void *parse_byte_string(char *bytes, uint8_t *data, size_t *count_ptr) size_t count, length; int i;
- if (!bytes)
length = strlen(bytes); count = length / 2;return NULL;

Hi Christophe,
On 24 August 2015 at 14:22, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
Print an error ? Are you sure ? I guess the comment is not accurate ;).
Well returning NULL from parse_byte_string() will cause an error to be printed by the caller...
Regards, Simon
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
Rather then crashing when there is no data, print an error.
Acked-by: Christophe Ricard christophe-h.ricard@st.com Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/cmd_tpm.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index 65e7371..e9c6618 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -58,6 +58,8 @@ static void *parse_byte_string(char *bytes, uint8_t *data, size_t *count_ptr) size_t count, length; int i;
if (!bytes)
return NULL; length = strlen(bytes); count = length / 2;

Hi Simon, Le 25/08/2015 06:13, Simon Glass a écrit :
Hi Christophe,
On 24 August 2015 at 14:22, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
Print an error ? Are you sure ? I guess the comment is not accurate ;).
Well returning NULL from parse_byte_string() will cause an error to be printed by the caller...
This is just a comment nitpick. I think it is clear enough but from the patch the printing is may be not so obvious. It is just fine like that.
Regards, Simon
Best Regards Christophe
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
Rather then crashing when there is no data, print an error.
Acked-by: Christophe Ricard christophe-h.ricard@st.com Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/cmd_tpm.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index 65e7371..e9c6618 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -58,6 +58,8 @@ static void *parse_byte_string(char *bytes, uint8_t *data, size_t *count_ptr) size_t count, length; int i;
if (!bytes)
return NULL; length = strlen(bytes); count = length / 2;

On 25 August 2015 at 12:40, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon, Le 25/08/2015 06:13, Simon Glass a écrit :
Hi Christophe,
On 24 August 2015 at 14:22, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
Print an error ? Are you sure ? I guess the comment is not accurate ;).
Well returning NULL from parse_byte_string() will cause an error to be printed by the caller...
This is just a comment nitpick. I think it is clear enough but from the patch the printing is may be not so obvious. It is just fine like that.
OK thanks. I fixed up the commit message to be a bit more explanatory.
Applied to u-boot-dm.

Add a TPM node to the various Chromebooks so that driver can be converted to driver model.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add tpm device tree node for panther also
arch/arm/dts/exynos5250-snow.dts | 9 +++++++++ arch/arm/dts/exynos5250-spring.dts | 8 ++++++++ arch/arm/dts/exynos5420-peach-pit.dts | 6 +++--- arch/arm/dts/exynos5800-peach-pi.dts | 6 +++--- arch/x86/dts/chromebook_link.dts | 5 +++++ arch/x86/dts/chromebox_panther.dts | 5 +++++ 6 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/arch/arm/dts/exynos5250-snow.dts b/arch/arm/dts/exynos5250-snow.dts index 32c0098..bda5499 100644 --- a/arch/arm/dts/exynos5250-snow.dts +++ b/arch/arm/dts/exynos5250-snow.dts @@ -206,6 +206,15 @@ }; };
+ i2c@12C90000 { + clock-frequency = <100000>; + tpm@20 { + reg = <0x20>; + u-boot,i2c-offset-len = <0>; + compatible = "infineon,slb9635tt"; + }; + }; + spi@12d30000 { spi-max-frequency = <50000000>; firmware_storage_spi: flash@0 { diff --git a/arch/arm/dts/exynos5250-spring.dts b/arch/arm/dts/exynos5250-spring.dts index 76d5323..81b3d29 100644 --- a/arch/arm/dts/exynos5250-spring.dts +++ b/arch/arm/dts/exynos5250-spring.dts @@ -59,6 +59,14 @@ <&gpy4 2 0>; };
+ i2c@12C90000 { + clock-frequency = <100000>; + tpm@20 { + reg = <0x20>; + compatible = "infineon,slb9645tt"; + }; + }; + mmc@12200000 { samsung,bus-width = <8>; samsung,timing = <1 3 3>; diff --git a/arch/arm/dts/exynos5420-peach-pit.dts b/arch/arm/dts/exynos5420-peach-pit.dts index 2d2b7c9..16d52f4 100644 --- a/arch/arm/dts/exynos5420-peach-pit.dts +++ b/arch/arm/dts/exynos5420-peach-pit.dts @@ -197,9 +197,9 @@
i2c@12E10000 { /* i2c9 */ clock-frequency = <400000>; - tpm@20 { - compatible = "infineon,slb9645tt"; - reg = <0x20>; + tpm@20 { + compatible = "infineon,slb9645tt"; + reg = <0x20>; }; };
diff --git a/arch/arm/dts/exynos5800-peach-pi.dts b/arch/arm/dts/exynos5800-peach-pi.dts index 600c294..1d7ff23 100644 --- a/arch/arm/dts/exynos5800-peach-pi.dts +++ b/arch/arm/dts/exynos5800-peach-pi.dts @@ -72,9 +72,9 @@
i2c@12E10000 { /* i2c9 */ clock-frequency = <400000>; - tpm@20 { - compatible = "infineon,slb9645tt"; - reg = <0x20>; + tpm@20 { + compatible = "infineon,slb9645tt"; + reg = <0x20>; }; };
diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts index ad390bf..4291141 100644 --- a/arch/x86/dts/chromebook_link.dts +++ b/arch/x86/dts/chromebook_link.dts @@ -237,6 +237,11 @@ }; };
+ tpm { + reg = <0xfed40000 0x5000>; + compatible = "infineon,slb9635lpc"; + }; + microcode { update@0 { #include "microcode/m12306a9_0000001b.dtsi" diff --git a/arch/x86/dts/chromebox_panther.dts b/arch/x86/dts/chromebox_panther.dts index 84eae3a..36feb96 100644 --- a/arch/x86/dts/chromebox_panther.dts +++ b/arch/x86/dts/chromebox_panther.dts @@ -62,4 +62,9 @@ }; };
+ tpm { + reg = <0xfed40000 0x5000>; + compatible = "infineon,slb9635lpc"; + }; + };

Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
Add a TPM node to the various Chromebooks so that driver can be converted to driver model.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
Add tpm device tree node for panther also
arch/arm/dts/exynos5250-snow.dts | 9 +++++++++ arch/arm/dts/exynos5250-spring.dts | 8 ++++++++ arch/arm/dts/exynos5420-peach-pit.dts | 6 +++--- arch/arm/dts/exynos5800-peach-pi.dts | 6 +++--- arch/x86/dts/chromebook_link.dts | 5 +++++ arch/x86/dts/chromebox_panther.dts | 5 +++++ 6 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/arch/arm/dts/exynos5250-snow.dts b/arch/arm/dts/exynos5250-snow.dts index 32c0098..bda5499 100644 --- a/arch/arm/dts/exynos5250-snow.dts +++ b/arch/arm/dts/exynos5250-snow.dts @@ -206,6 +206,15 @@ }; };
- i2c@12C90000 {
clock-frequency = <100000>;
tpm@20 {
reg = <0x20>;
u-boot,i2c-offset-len = <0>;
compatible = "infineon,slb9635tt";
};
- };
- spi@12d30000 { spi-max-frequency = <50000000>; firmware_storage_spi: flash@0 {
diff --git a/arch/arm/dts/exynos5250-spring.dts b/arch/arm/dts/exynos5250-spring.dts index 76d5323..81b3d29 100644 --- a/arch/arm/dts/exynos5250-spring.dts +++ b/arch/arm/dts/exynos5250-spring.dts @@ -59,6 +59,14 @@ <&gpy4 2 0>; };
- i2c@12C90000 {
clock-frequency = <100000>;
tpm@20 {
reg = <0x20>;
compatible = "infineon,slb9645tt";
};
- };
- mmc@12200000 { samsung,bus-width = <8>; samsung,timing = <1 3 3>;
diff --git a/arch/arm/dts/exynos5420-peach-pit.dts b/arch/arm/dts/exynos5420-peach-pit.dts index 2d2b7c9..16d52f4 100644 --- a/arch/arm/dts/exynos5420-peach-pit.dts +++ b/arch/arm/dts/exynos5420-peach-pit.dts @@ -197,9 +197,9 @@
i2c@12E10000 { /* i2c9 */ clock-frequency = <400000>;
tpm@20 {
compatible = "infineon,slb9645tt";
reg = <0x20>;
tpm@20 {
compatible = "infineon,slb9645tt";
}; };reg = <0x20>;
diff --git a/arch/arm/dts/exynos5800-peach-pi.dts b/arch/arm/dts/exynos5800-peach-pi.dts index 600c294..1d7ff23 100644 --- a/arch/arm/dts/exynos5800-peach-pi.dts +++ b/arch/arm/dts/exynos5800-peach-pi.dts @@ -72,9 +72,9 @@
i2c@12E10000 { /* i2c9 */ clock-frequency = <400000>;
tpm@20 {
compatible = "infineon,slb9645tt";
reg = <0x20>;
tpm@20 {
compatible = "infineon,slb9645tt";
}; };reg = <0x20>;
diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts index ad390bf..4291141 100644 --- a/arch/x86/dts/chromebook_link.dts +++ b/arch/x86/dts/chromebook_link.dts @@ -237,6 +237,11 @@ }; };
- tpm {
reg = <0xfed40000 0x5000>;
compatible = "infineon,slb9635lpc";
- };
- microcode { update@0 { #include "microcode/m12306a9_0000001b.dtsi"
diff --git a/arch/x86/dts/chromebox_panther.dts b/arch/x86/dts/chromebox_panther.dts index 84eae3a..36feb96 100644 --- a/arch/x86/dts/chromebox_panther.dts +++ b/arch/x86/dts/chromebox_panther.dts @@ -62,4 +62,9 @@ }; };
- tpm {
reg = <0xfed40000 0x5000>;
compatible = "infineon,slb9635lpc";
- };
- };

On 24 August 2015 at 14:22, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

Convert the tpm_tis_i2c driver to use driver model and update boards which use it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Update driver for v2 TPM uclass which supports timeouts
configs/peach-pi_defconfig | 1 + configs/peach-pit_defconfig | 1 + configs/snow_defconfig | 1 + configs/spring_defconfig | 1 + drivers/tpm/tpm_tis_i2c.c | 529 +++++++++++++++++--------------------------- drivers/tpm/tpm_tis_i2c.h | 20 +- include/fdtdec.h | 2 - lib/fdtdec.c | 2 - 8 files changed, 207 insertions(+), 350 deletions(-)
diff --git a/configs/peach-pi_defconfig b/configs/peach-pi_defconfig index 2be74fd..6416f16 100644 --- a/configs/peach-pi_defconfig +++ b/configs/peach-pi_defconfig @@ -13,6 +13,7 @@ CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_SPI=y CONFIG_CROS_EC_KEYB=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y diff --git a/configs/peach-pit_defconfig b/configs/peach-pit_defconfig index 875ddd1..d0646ab 100644 --- a/configs/peach-pit_defconfig +++ b/configs/peach-pit_defconfig @@ -13,6 +13,7 @@ CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_SPI=y CONFIG_CROS_EC_KEYB=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y diff --git a/configs/snow_defconfig b/configs/snow_defconfig index f59aa3f..7624ad2 100644 --- a/configs/snow_defconfig +++ b/configs/snow_defconfig @@ -18,6 +18,7 @@ CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_S5P=y CONFIG_DEBUG_UART_BASE=0x12c30000 CONFIG_DEBUG_UART_CLOCK=100000000 +CONFIG_DM_TPM=y CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y diff --git a/configs/spring_defconfig b/configs/spring_defconfig index 6144f03..3b109fa 100644 --- a/configs/spring_defconfig +++ b/configs/spring_defconfig @@ -18,6 +18,7 @@ CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_S5P=y CONFIG_DEBUG_UART_BASE=0x12c30000 CONFIG_DEBUG_UART_CLOCK=100000000 +CONFIG_DM_TPM=y CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 645f702..9afe46c 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -23,11 +23,11 @@ #include <common.h> #include <dm.h> #include <fdtdec.h> -#include <linux/compiler.h> #include <i2c.h> #include <tis.h> #include <tpm.h> #include <asm-generic/errno.h> +#include <linux/compiler.h> #include <linux/types.h> #include <linux/unaligned/be_byteshift.h>
@@ -42,8 +42,6 @@ static const char * const chip_name[] = { [UNKNOWN] = "unknown/fallback to slb9635", };
-static struct tpm_chip g_chip; - /* * tpm_tis_i2c_read() - read from TPM register * @addr: register address to read from @@ -58,22 +56,24 @@ static struct tpm_chip g_chip; * * Return -EIO on error, 0 on success. */ -static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) +static int tpm_tis_i2c_read(struct udevice *dev, u8 addr, u8 *buffer, + size_t len) { + struct tpm_chip *chip = dev_get_priv(dev); int rc; int count; uint32_t addrbuf = addr;
- if ((g_chip.chip_type == SLB9635) || (g_chip.chip_type == UNKNOWN)) { + if ((chip->chip_type == SLB9635) || (chip->chip_type == UNKNOWN)) { /* slb9635 protocol should work in both cases */ for (count = 0; count < MAX_COUNT; count++) { - rc = dm_i2c_write(g_chip.dev, 0, (uchar *)&addrbuf, 1); + rc = dm_i2c_write(dev, 0, (uchar *)&addrbuf, 1); if (rc == 0) break; /* Success, break to skip sleep */ udelay(SLEEP_DURATION_US); } if (rc) - return -rc; + return rc;
/* After the TPM has successfully received the register address * it needs some time, thus we're sleeping here again, before @@ -81,7 +81,7 @@ static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) */ for (count = 0; count < MAX_COUNT; count++) { udelay(SLEEP_DURATION_US); - rc = dm_i2c_read(g_chip.dev, 0, buffer, len); + rc = dm_i2c_read(dev, 0, buffer, len); if (rc == 0) break; /* success, break to skip sleep */ } @@ -94,7 +94,7 @@ static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) * be safe on the safe side. */ for (count = 0; count < MAX_COUNT; count++) { - rc = dm_i2c_read(g_chip.dev, addr, buffer, len); + rc = dm_i2c_read(dev, addr, buffer, len); if (rc == 0) break; /* break here to skip sleep */ udelay(SLEEP_DURATION_US); @@ -104,19 +104,31 @@ static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) /* Take care of 'guard time' */ udelay(SLEEP_DURATION_US); if (rc) - return -rc; + return rc;
return 0; }
-static int tpm_tis_i2c_write_generic(u8 addr, u8 *buffer, size_t len, +static int tpm_tis_i2c_write_generic(struct udevice *dev, u8 addr, + const u8 *buffer, size_t len, unsigned int sleep_time_us, u8 max_count) { + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); + struct tpm_chip *chip = dev_get_priv(dev); int rc = 0; int count;
+ if (chip->chip_type == SLB9635) { + /* Prepare send buffer to include the address */ + priv->buf[0] = addr; + memcpy(&(priv->buf[1]), buffer, len); + buffer = priv->buf; + len++; + addr = 0; + } + for (count = 0; count < max_count; count++) { - rc = dm_i2c_write(g_chip.dev, addr, buffer, len); + rc = dm_i2c_write(dev, addr, buffer, len); if (rc == 0) break; /* Success, break to skip sleep */ udelay(sleep_time_us); @@ -125,7 +137,7 @@ static int tpm_tis_i2c_write_generic(u8 addr, u8 *buffer, size_t len, /* take care of 'guard time' */ udelay(sleep_time_us); if (rc) - return -rc; + return rc;
return 0; } @@ -146,30 +158,33 @@ static int tpm_tis_i2c_write_generic(u8 addr, u8 *buffer, size_t len, * * Return -EIO on error, 0 on success */ -static int tpm_tis_i2c_write(u8 addr, u8 *buffer, size_t len) +static int tpm_tis_i2c_write(struct udevice *dev, u8 addr, const u8 *buffer, + size_t len) { - return tpm_tis_i2c_write_generic(addr, buffer, len, SLEEP_DURATION_US, - MAX_COUNT); + return tpm_tis_i2c_write_generic(dev, addr, buffer, len, + SLEEP_DURATION_US, MAX_COUNT); }
/* * This function is needed especially for the cleanup situation after * sending TPM_READY */ -static int tpm_tis_i2c_write_long(u8 addr, u8 *buffer, size_t len) +static int tpm_tis_i2c_write_long(struct udevice *dev, u8 addr, u8 *buffer, + size_t len) { - return tpm_tis_i2c_write_generic(addr, buffer, len, + return tpm_tis_i2c_write_generic(dev, addr, buffer, len, SLEEP_DURATION_LONG_US, MAX_COUNT_LONG); }
-static int tpm_tis_i2c_check_locality(struct tpm_chip *chip, int loc) +static int tpm_tis_i2c_check_locality(struct udevice *dev, int loc) { const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID; + struct tpm_chip *chip = dev_get_priv(dev); u8 buf; int rc;
- rc = tpm_tis_i2c_read(TPM_ACCESS(loc), &buf, 1); + rc = tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1); if (rc < 0) return rc;
@@ -178,75 +193,96 @@ static int tpm_tis_i2c_check_locality(struct tpm_chip *chip, int loc) return loc; }
- return -1; + return -ENOENT; }
-static void tpm_tis_i2c_release_locality(struct tpm_chip *chip, int loc, +static void tpm_tis_i2c_release_locality(struct udevice *dev, int loc, int force) { const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID; u8 buf;
- if (tpm_tis_i2c_read(TPM_ACCESS(loc), &buf, 1) < 0) + if (tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1) < 0) return;
if (force || (buf & mask) == mask) { buf = TPM_ACCESS_ACTIVE_LOCALITY; - tpm_tis_i2c_write(TPM_ACCESS(loc), &buf, 1); + tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1); } }
-static int tpm_tis_i2c_request_locality(struct tpm_chip *chip, int loc) +static int tpm_tis_i2c_request_locality(struct udevice *dev, int loc) { + struct tpm_chip *chip = dev_get_priv(dev); unsigned long start, stop; u8 buf = TPM_ACCESS_REQUEST_USE; int rc;
- if (tpm_tis_i2c_check_locality(chip, loc) >= 0) + rc = tpm_tis_i2c_check_locality(dev, loc); + if (rc >= 0) { + debug("%s: Already have locality\n", __func__); return loc; /* We already have the locality */ + } else if (rc != -ENOENT) { + debug("%s: Failed to get locality: %d\n", __func__, rc); + return rc; + }
- rc = tpm_tis_i2c_write(TPM_ACCESS(loc), &buf, 1); - if (rc) + rc = tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1); + if (rc) { + debug("%s: Failed to write to TPM: %d\n", __func__, rc); return rc; + }
/* Wait for burstcount */ start = get_timer(0); stop = chip->timeout_a; do { - if (tpm_tis_i2c_check_locality(chip, loc) >= 0) + rc = tpm_tis_i2c_check_locality(dev, loc); + if (rc >= 0) { + debug("%s: Have locality\n", __func__); return loc; + } else if (rc != -ENOENT) { + debug("%s: Failed to get locality: %d\n", __func__, rc); + return rc; + } mdelay(TPM_TIMEOUT_MS); } while (get_timer(start) < stop); + debug("%s: Timeout getting locality: %d\n", __func__, rc);
- return -1; + return rc; }
-static u8 tpm_tis_i2c_status(struct tpm_chip *chip) +static u8 tpm_tis_i2c_status(struct udevice *dev) { + struct tpm_chip *chip = dev_get_priv(dev); /* NOTE: Since i2c read may fail, return 0 in this case --> time-out */ u8 buf;
- if (tpm_tis_i2c_read(TPM_STS(chip->locality), &buf, 1) < 0) + if (tpm_tis_i2c_read(dev, TPM_STS(chip->locality), &buf, 1) < 0) return 0; else return buf; }
-static void tpm_tis_i2c_ready(struct tpm_chip *chip) +static int tpm_tis_i2c_ready(struct udevice *dev) { + struct tpm_chip *chip = dev_get_priv(dev); int rc;
/* This causes the current command to be aborted */ u8 buf = TPM_STS_COMMAND_READY;
debug("%s\n", __func__); - rc = tpm_tis_i2c_write_long(TPM_STS(chip->locality), &buf, 1); + rc = tpm_tis_i2c_write_long(dev, TPM_STS(chip->locality), &buf, 1); if (rc) debug("%s: rc=%d\n", __func__, rc); + + return rc; }
-static ssize_t tpm_tis_i2c_get_burstcount(struct tpm_chip *chip) +static ssize_t tpm_tis_i2c_get_burstcount(struct udevice *dev) { + struct tpm_chip *chip = dev_get_priv(dev); unsigned long start, stop; ssize_t burstcnt; u8 addr, buf[3]; @@ -258,7 +294,7 @@ static ssize_t tpm_tis_i2c_get_burstcount(struct tpm_chip *chip) do { /* Note: STS is little endian */ addr = TPM_STS(chip->locality) + 1; - if (tpm_tis_i2c_read(addr, buf, 3) < 0) + if (tpm_tis_i2c_read(dev, addr, buf, 3) < 0) burstcnt = 0; else burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; @@ -271,13 +307,13 @@ static ssize_t tpm_tis_i2c_get_burstcount(struct tpm_chip *chip) return -EBUSY; }
-static int tpm_tis_i2c_wait_for_stat(struct tpm_chip *chip, u8 mask, +static int tpm_tis_i2c_wait_for_stat(struct udevice *dev, u8 mask, unsigned long timeout, int *status) { unsigned long start, stop;
/* Check current status */ - *status = tpm_tis_i2c_status(chip); + *status = tpm_tis_i2c_status(dev); if ((*status & mask) == mask) return 0;
@@ -285,22 +321,23 @@ static int tpm_tis_i2c_wait_for_stat(struct tpm_chip *chip, u8 mask, stop = timeout; do { mdelay(TPM_TIMEOUT_MS); - *status = tpm_tis_i2c_status(chip); + *status = tpm_tis_i2c_status(dev); if ((*status & mask) == mask) return 0; } while (get_timer(start) < stop);
- return -ETIME; + return -ETIMEDOUT; }
-static int tpm_tis_i2c_recv_data(struct tpm_chip *chip, u8 *buf, size_t count) +static int tpm_tis_i2c_recv_data(struct udevice *dev, u8 *buf, size_t count) { + struct tpm_chip *chip = dev_get_priv(dev); size_t size = 0; ssize_t burstcnt; int rc;
while (size < count) { - burstcnt = tpm_tis_i2c_get_burstcount(chip); + burstcnt = tpm_tis_i2c_get_burstcount(dev);
/* burstcount < 0 -> tpm is busy */ if (burstcnt < 0) @@ -310,8 +347,8 @@ static int tpm_tis_i2c_recv_data(struct tpm_chip *chip, u8 *buf, size_t count) if (burstcnt > (count - size)) burstcnt = count - size;
- rc = tpm_tis_i2c_read(TPM_DATA_FIFO(chip->locality), - &(buf[size]), burstcnt); + rc = tpm_tis_i2c_read(dev, TPM_DATA_FIFO(chip->locality), + &(buf[size]), burstcnt); if (rc == 0) size += burstcnt; } @@ -319,61 +356,58 @@ static int tpm_tis_i2c_recv_data(struct tpm_chip *chip, u8 *buf, size_t count) return size; }
-static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) +static int tpm_tis_i2c_recv(struct udevice *dev, u8 *buf, size_t count) { + struct tpm_chip *chip = dev_get_priv(dev); int size = 0; int expected, status; + int rc;
- if (count < TPM_HEADER_SIZE) { - size = -EIO; - goto out; - } + status = tpm_tis_i2c_status(dev); + if (status == TPM_STS_COMMAND_READY) + return -EINTR; + if ((status & (TPM_STS_DATA_AVAIL | TPM_STS_VALID)) != + (TPM_STS_DATA_AVAIL | TPM_STS_VALID)) + return -EAGAIN; + + debug("...got it;\n");
/* Read first 10 bytes, including tag, paramsize, and result */ - size = tpm_tis_i2c_recv_data(chip, buf, TPM_HEADER_SIZE); + size = tpm_tis_i2c_recv_data(dev, buf, TPM_HEADER_SIZE); if (size < TPM_HEADER_SIZE) { - error("Unable to read header\n"); - goto out; + debug("Unable to read header\n"); + return size < 0 ? size : -EIO; }
expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE); if ((size_t)expected > count) { - error("Error size=%x, expected=%x, count=%x\n", size, expected, + debug("Error size=%x, expected=%x, count=%x\n", size, expected, count); - size = -EIO; - goto out; + return -ENOSPC; }
- size += tpm_tis_i2c_recv_data(chip, &buf[TPM_HEADER_SIZE], + size += tpm_tis_i2c_recv_data(dev, &buf[TPM_HEADER_SIZE], expected - TPM_HEADER_SIZE); if (size < expected) { - error("Unable to read remainder of result\n"); - size = -ETIME; - goto out; + debug("Unable to read remainder of result\n"); + return -ETIMEDOUT; }
- tpm_tis_i2c_wait_for_stat(chip, TPM_STS_VALID, chip->timeout_c, - &status); + rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID, chip->timeout_c, + &status); + if (rc) + return rc; if (status & TPM_STS_DATA_AVAIL) { /* Retry? */ - error("Error left over data\n"); - size = -EIO; - goto out; + debug("Error left over data\n"); + return -EIO; }
-out: - tpm_tis_i2c_ready(chip); - /* - * The TPM needs some time to clean up here, - * so we sleep rather than keeping the bus busy - */ - mdelay(2); - tpm_tis_i2c_release_locality(chip, chip->locality, 0); - return size; }
-static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) +static int tpm_tis_i2c_send(struct udevice *dev, const u8 *buf, size_t len) { + struct tpm_chip *chip = dev_get_priv(dev); int rc, status; size_t burstcnt; size_t count = 0; @@ -384,20 +418,21 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) if (len > TPM_DEV_BUFSIZE) return -E2BIG; /* Command is too long for our tpm, sorry */
- if (tpm_tis_i2c_request_locality(chip, 0) < 0) + if (tpm_tis_i2c_request_locality(dev, 0) < 0) return -EBUSY;
- status = tpm_tis_i2c_status(chip); + status = tpm_tis_i2c_status(dev); if ((status & TPM_STS_COMMAND_READY) == 0) { - tpm_tis_i2c_ready(chip); - if (tpm_tis_i2c_wait_for_stat(chip, TPM_STS_COMMAND_READY, - chip->timeout_b, &status) < 0) { - rc = -ETIME; - goto out_err; - } + rc = tpm_tis_i2c_ready(dev); + if (rc) + return rc; + rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_COMMAND_READY, + chip->timeout_b, &status); + if (rc) + return rc; }
- burstcnt = tpm_tis_i2c_get_burstcount(chip); + burstcnt = tpm_tis_i2c_get_burstcount(dev);
/* burstcount < 0 -> tpm is busy */ if (burstcnt < 0) @@ -409,98 +444,79 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = len - count;
#ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION - if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION) - burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION; + if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN) + burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN; #endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */
- rc = tpm_tis_i2c_write(TPM_DATA_FIFO(chip->locality), - &(buf[count]), burstcnt); + rc = tpm_tis_i2c_write(dev, TPM_DATA_FIFO(chip->locality), + &(buf[count]), burstcnt); if (rc == 0) count += burstcnt; else { debug("%s: error\n", __func__); - if (retry++ > 10) { - rc = -EIO; - goto out_err; - } - rc = tpm_tis_i2c_wait_for_stat(chip, TPM_STS_VALID, + if (retry++ > 10) + return -EIO; + rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID, chip->timeout_c, &status); if (rc) - goto out_err; + return rc;
- if ((status & TPM_STS_DATA_EXPECT) == 0) { - rc = -EIO; - goto out_err; - } + if ((status & TPM_STS_DATA_EXPECT) == 0) + return -EIO; } }
/* Go and do it */ - tpm_tis_i2c_write(TPM_STS(chip->locality), &sts, 1); - debug("done\n"); + rc = tpm_tis_i2c_write(dev, TPM_STS(chip->locality), &sts, 1); + if (rc < 0) + return rc; + debug("%s: done, rc=%d\n", __func__, rc);
return len; +} + +static int tpm_tis_i2c_cleanup(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev);
-out_err: - debug("%s: out_err\n", __func__); - tpm_tis_i2c_ready(chip); + tpm_tis_i2c_ready(dev); /* * The TPM needs some time to clean up here, * so we sleep rather than keeping the bus busy */ mdelay(2); - tpm_tis_i2c_release_locality(chip, chip->locality, 0); + tpm_tis_i2c_release_locality(dev, chip->locality, 0);
- return rc; -} - -static enum i2c_chip_type tpm_tis_i2c_chip_type(void) -{ -#if CONFIG_IS_ENABLED(OF_CONTROL) - const void *blob = gd->fdt_blob; - - if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9645_TPM) >= 0) - return SLB9645; - - if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM) >= 0) - return SLB9635; -#endif - return UNKNOWN; + return 0; }
static int tpm_tis_i2c_init(struct udevice *dev) { - struct tpm_chip *chip = &g_chip; + struct tpm_chip *chip = dev_get_priv(dev); u32 vendor; u32 expected_did_vid; + int rc;
- g_chip.dev = dev; - g_chip.chip_type = tpm_tis_i2c_chip_type(); chip->is_open = 1;
- /* Disable interrupts (not supported) */ - chip->irq = 0; - /* Default timeouts - these could move to the device tree */ chip->timeout_a = TIS_SHORT_TIMEOUT_MS; chip->timeout_b = TIS_LONG_TIMEOUT_MS; chip->timeout_c = TIS_SHORT_TIMEOUT_MS; chip->timeout_d = TIS_SHORT_TIMEOUT_MS; - chip->req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID; - chip->req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID; - chip->req_canceled = TPM_STS_COMMAND_READY;
- if (tpm_tis_i2c_request_locality(chip, 0) < 0) - return -ENODEV; + rc = tpm_tis_i2c_request_locality(dev, 0); + if (rc < 0) + return rc;
/* Read four bytes from DID_VID register */ - if (tpm_tis_i2c_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { - tpm_tis_i2c_release_locality(chip, 0, 1); + if (tpm_tis_i2c_read(dev, TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { + tpm_tis_i2c_release_locality(dev, 0, 1); return -EIO; }
- if (g_chip.chip_type == SLB9635) { + if (chip->chip_type == SLB9635) { vendor = be32_to_cpu(vendor); expected_did_vid = TPM_TIS_I2C_DID_VID_9635; } else { @@ -508,13 +524,14 @@ static int tpm_tis_i2c_init(struct udevice *dev) expected_did_vid = TPM_TIS_I2C_DID_VID_9645; }
- if (g_chip.chip_type != UNKNOWN && vendor != expected_did_vid) { + if (chip->chip_type != UNKNOWN && vendor != expected_did_vid) { error("Vendor id did not match! ID was %08x\n", vendor); return -ENODEV; }
+ chip->vend_dev = vendor; debug("1.2 TPM (chip type %s device-id 0x%X)\n", - chip_name[g_chip.chip_type], vendor >> 16); + chip_name[chip->chip_type], vendor >> 16);
/* * A timeout query to TPM can be placed here. @@ -524,225 +541,83 @@ static int tpm_tis_i2c_init(struct udevice *dev) return 0; }
-/* Returns max number of milliseconds to wait */ -static unsigned long tpm_tis_i2c_calc_ordinal_duration(struct tpm_chip *chip, - 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 = chip->duration[duration_idx]; - - if (duration <= 0) - return 2 * 60 * HZ; /* Two minutes timeout */ - else - return duration; -} - -static ssize_t tpm_tis_i2c_transmit(const unsigned char *buf, size_t bufsiz) +static int tpm_tis_i2c_open(struct udevice *dev) { + struct tpm_chip *chip = dev_get_priv(dev); int rc; - u32 count, ordinal; - unsigned long start, stop; - - struct tpm_chip *chip = &g_chip; - - /* switch endianess: big->little */ - count = get_unaligned_be32(buf + TPM_CMD_COUNT_BYTE); - ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE);
- if (count == 0) { - error("no data\n"); - return -ENODATA; - } - if (count > bufsiz) { - error("invalid count value %x %zx\n", count, bufsiz); - return -E2BIG; - } - - debug("Calling send\n"); - rc = tpm_tis_i2c_send(chip, (u8 *)buf, count); - debug(" ... done calling send\n"); - if (rc < 0) { - error("tpm_transmit: tpm_send: error %d\n", rc); - goto out; - } - - if (chip->irq) - goto out_recv; - - start = get_timer(0); - stop = tpm_tis_i2c_calc_ordinal_duration(chip, ordinal); - do { - debug("waiting for status... %ld %ld\n", start, stop); - u8 status = tpm_tis_i2c_status(chip); - if ((status & chip->req_complete_mask) == - chip->req_complete_val) { - debug("...got it;\n"); - goto out_recv; - } - - if (status == chip->req_canceled) { - error("Operation Canceled\n"); - rc = -ECANCELED; - goto out; - } - mdelay(TPM_TIMEOUT_MS); - } while (get_timer(start) < stop); - - tpm_tis_i2c_ready(chip); - error("Operation Timed out\n"); - rc = -ETIME; - goto out; - -out_recv: - debug("out_recv: reading response...\n"); - rc = tpm_tis_i2c_recv(chip, (u8 *)buf, TPM_BUFSIZE); + debug("%s: start\n", __func__); + if (chip->is_open) + return -EBUSY; + rc = tpm_tis_i2c_init(dev); if (rc < 0) - error("tpm_transmit: tpm_recv: error %d\n", rc); + chip->is_open = 0;
-out: return rc; }
-/** - * Decode TPM configuration. - * - * @param dev Returns a configuration of TPM device - * @return 0 if ok, -1 on error - */ -static int tpm_tis_i2c_decode_config(struct tpm_chip *chip) +static int tpm_tis_i2c_close(struct udevice *dev) { - const void *blob = gd->fdt_blob; - struct udevice *bus; - int chip_addr; - int parent; - int node; - int ret; - - node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); - if (node < 0) { - node = fdtdec_next_compatible(blob, 0, - COMPAT_INFINEON_SLB9645_TPM); - } - if (node < 0) { - debug("%s: Node not found\n", __func__); - return -1; - } - parent = fdt_parent_offset(blob, node); - if (parent < 0) { - debug("%s: Cannot find node parent\n", __func__); - return -1; - } + struct tpm_chip *chip = dev_get_priv(dev);
- /* - * TODO(sjg@chromium.org): Remove this when driver model supports - * TPMs - */ - ret = uclass_get_device_by_of_offset(UCLASS_I2C, parent, &bus); - if (ret) { - debug("Cannot find bus for node '%s: ret=%d'\n", - fdt_get_name(blob, parent, NULL), ret); - return ret; - } - - chip_addr = fdtdec_get_int(blob, node, "reg", -1); - if (chip_addr == -1) { - debug("Cannot find reg property for node '%s: ret=%d'\n", - fdt_get_name(blob, node, NULL), ret); - return ret; - } - /* - * TODO(sjg@chromium.org): Older TPMs will need to use the older method - * in tpm_tis_i2c_read() so the offset length needs to be 0 here. - */ - ret = i2c_get_chip(bus, chip_addr, 1, &chip->dev); - if (ret) { - debug("Cannot find device for node '%s: ret=%d'\n", - fdt_get_name(blob, node, NULL), ret); - return ret; + if (chip->is_open) { + tpm_tis_i2c_release_locality(dev, chip->locality, 1); + chip->is_open = 0; + chip->vend_dev = 0; }
return 0; }
-int tis_init(void) +static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size) { - if (g_chip.inited) - return 0; - - if (tpm_tis_i2c_decode_config(&g_chip)) - return -1; - - debug("%s: done\n", __func__); + struct tpm_chip *chip = dev_get_priv(dev);
- g_chip.inited = 1; + if (size < 50) + return -ENOSPC;
- return 0; + return snprintf(buf, size, "1.2 TPM (%s, chip type %s device-id 0x%x)", + chip->is_open ? "open" : "closed", + chip_name[chip->chip_type], + chip->vend_dev >> 16); }
-int tis_open(void) +static int tpm_tis_i2c_probe(struct udevice *dev) { - int rc; - - if (!g_chip.inited) - return -1; - - debug("%s: start\n", __func__); - if (g_chip.is_open) - return -EBUSY; - rc = tpm_tis_i2c_init(g_chip.dev); - if (rc < 0) - g_chip.is_open = 0; - - return rc; -} + struct tpm_chip_priv *uc_priv = dev_get_uclass_priv(dev); + struct tpm_chip *chip = dev_get_priv(dev);
-int tis_close(void) -{ - if (!g_chip.inited) - return -1; + chip->chip_type = dev_get_driver_data(dev);
- if (g_chip.is_open) { - tpm_tis_i2c_release_locality(&g_chip, g_chip.locality, 1); - g_chip.is_open = 0; - } + /* TODO: These need to be checked and tuned */ + uc_priv->duration_ms[TPM_SHORT] = TIS_SHORT_TIMEOUT_MS; + uc_priv->duration_ms[TPM_MEDIUM] = TIS_LONG_TIMEOUT_MS; + uc_priv->duration_ms[TPM_LONG] = TIS_LONG_TIMEOUT_MS; + uc_priv->retry_time_ms = TPM_TIMEOUT_MS;
return 0; }
-int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, - uint8_t *recvbuf, size_t *rbuf_len) -{ - int len; - uint8_t buf[4096]; - - if (!g_chip.inited) - return -1; - - if (sizeof(buf) < sbuf_size) - return -1; - - memcpy(buf, sendbuf, sbuf_size); - - len = tpm_tis_i2c_transmit(buf, sbuf_size); - - if (len < 10) { - *rbuf_len = 0; - return -1; - } +static const struct tpm_ops tpm_tis_i2c_ops = { + .open = tpm_tis_i2c_open, + .close = tpm_tis_i2c_close, + .get_desc = tpm_tis_get_desc, + .send = tpm_tis_i2c_send, + .recv = tpm_tis_i2c_recv, + .cleanup = tpm_tis_i2c_cleanup, +};
- memcpy(recvbuf, buf, len); - *rbuf_len = len; +static const struct udevice_id tpm_tis_i2c_ids[] = { + { .compatible = "infineon,slb9635tt", .data = SLB9635 }, + { .compatible = "infineon,slb9645tt", .data = SLB9645 }, + { } +};
- return 0; -} +U_BOOT_DRIVER(tpm_tis_i2c) = { + .name = "tpm_tis_i2c", + .id = UCLASS_TPM, + .of_match = tpm_tis_i2c_ids, + .ops = &tpm_tis_i2c_ops, + .probe = tpm_tis_i2c_probe, + .priv_auto_alloc_size = sizeof(struct tpm_chip), +}; diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_i2c.h index 02cc2eb..3b510d1 100644 --- a/drivers/tpm/tpm_tis_i2c.h +++ b/drivers/tpm/tpm_tis_i2c.h @@ -37,9 +37,6 @@ enum tpm_timeout { #define TPM_RSP_SIZE_BYTE 2 #define TPM_RSP_RC_BYTE 6
-/* Max buffer size supported by our tpm */ -#define TPM_DEV_BUFSIZE 1260 - enum i2c_chip_type { SLB9635, SLB9645, @@ -47,17 +44,10 @@ enum i2c_chip_type { };
struct tpm_chip { - bool inited; int is_open; - u8 req_complete_mask; - u8 req_complete_val; - u8 req_canceled; - int irq; int locality; + u32 vend_dev; unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ - unsigned long duration[3]; /* msec */ - struct udevice *dev; - u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)]; /* Max buffer size + addr */ enum i2c_chip_type chip_type; };
@@ -129,8 +119,6 @@ struct tpm_cmd_t { */ #define MAX_COUNT_LONG 50
-#define TPM_HEADER_SIZE 10 - enum tis_access { TPM_ACCESS_VALID = 0x80, TPM_ACCESS_ACTIVE_LOCALITY = 0x20, @@ -155,10 +143,4 @@ enum tis_status { #define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) #define TPM_DID_VID(l) (0x0006 | ((l) << 4))
-/* Extended error numbers from linux (see errno.h) */ -#define ECANCELED 125 /* Operation Canceled */ - -/* Timer frequency. Corresponds to msec timer resolution */ -#define HZ 1000 - #endif diff --git a/include/fdtdec.h b/include/fdtdec.h index 0cb6fa0..3e23731 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -154,8 +154,6 @@ enum fdt_compat_id { COMPAT_MAXIM_MAX77686_PMIC, /* MAX77686 PMIC */ COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */ COMPAT_MAXIM_98095_CODEC, /* MAX98095 Codec */ - COMPAT_INFINEON_SLB9635_TPM, /* Infineon SLB9635 TPM */ - COMPAT_INFINEON_SLB9645_TPM, /* Infineon SLB9645 TPM */ COMPAT_SAMSUNG_EXYNOS5_I2C, /* Exynos5 High Speed I2C Controller */ COMPAT_SANDBOX_LCD_SDL, /* Sandbox LCD emulation with SDL */ COMPAT_SAMSUNG_EXYNOS_SYSMMU, /* Exynos sysmmu */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index b65e1e6..197ef02 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -58,8 +58,6 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686"), COMPAT(GENERIC_SPI_FLASH, "spi-flash"), COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"), - COMPAT(INFINEON_SLB9635_TPM, "infineon,slb9635-tpm"), - COMPAT(INFINEON_SLB9645_TPM, "infineon,slb9645tt"), COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"), COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"), COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),

Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
Convert the tpm_tis_i2c driver to use driver model and update boards which use it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
Update driver for v2 TPM uclass which supports timeouts
configs/peach-pi_defconfig | 1 + configs/peach-pit_defconfig | 1 + configs/snow_defconfig | 1 + configs/spring_defconfig | 1 + drivers/tpm/tpm_tis_i2c.c | 529 +++++++++++++++++--------------------------- drivers/tpm/tpm_tis_i2c.h | 20 +- include/fdtdec.h | 2 - lib/fdtdec.c | 2 - 8 files changed, 207 insertions(+), 350 deletions(-)
diff --git a/configs/peach-pi_defconfig b/configs/peach-pi_defconfig index 2be74fd..6416f16 100644 --- a/configs/peach-pi_defconfig +++ b/configs/peach-pi_defconfig @@ -13,6 +13,7 @@ CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_SPI=y CONFIG_CROS_EC_KEYB=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y diff --git a/configs/peach-pit_defconfig b/configs/peach-pit_defconfig index 875ddd1..d0646ab 100644 --- a/configs/peach-pit_defconfig +++ b/configs/peach-pit_defconfig @@ -13,6 +13,7 @@ CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_SPI=y CONFIG_CROS_EC_KEYB=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y diff --git a/configs/snow_defconfig b/configs/snow_defconfig index f59aa3f..7624ad2 100644 --- a/configs/snow_defconfig +++ b/configs/snow_defconfig @@ -18,6 +18,7 @@ CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_S5P=y CONFIG_DEBUG_UART_BASE=0x12c30000 CONFIG_DEBUG_UART_CLOCK=100000000 +CONFIG_DM_TPM=y CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y diff --git a/configs/spring_defconfig b/configs/spring_defconfig index 6144f03..3b109fa 100644 --- a/configs/spring_defconfig +++ b/configs/spring_defconfig @@ -18,6 +18,7 @@ CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_S5P=y CONFIG_DEBUG_UART_BASE=0x12c30000 CONFIG_DEBUG_UART_CLOCK=100000000 +CONFIG_DM_TPM=y CONFIG_TPM_TIS_I2C=y CONFIG_DM_I2C=y CONFIG_DM_I2C_COMPAT=y diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 645f702..9afe46c 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -23,11 +23,11 @@ #include <common.h> #include <dm.h> #include <fdtdec.h> -#include <linux/compiler.h> #include <i2c.h> #include <tis.h> #include <tpm.h> #include <asm-generic/errno.h> +#include <linux/compiler.h> #include <linux/types.h> #include <linux/unaligned/be_byteshift.h>
@@ -42,8 +42,6 @@ static const char * const chip_name[] = { [UNKNOWN] = "unknown/fallback to slb9635", };
-static struct tpm_chip g_chip;
- /*
- tpm_tis_i2c_read() - read from TPM register
- @addr: register address to read from
@@ -58,22 +56,24 @@ static struct tpm_chip g_chip;
- Return -EIO on error, 0 on success.
*/ -static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) +static int tpm_tis_i2c_read(struct udevice *dev, u8 addr, u8 *buffer,
{size_t len)
- struct tpm_chip *chip = dev_get_priv(dev); int rc; int count; uint32_t addrbuf = addr;
- if ((g_chip.chip_type == SLB9635) || (g_chip.chip_type == UNKNOWN)) {
- if ((chip->chip_type == SLB9635) || (chip->chip_type == UNKNOWN)) { /* slb9635 protocol should work in both cases */ for (count = 0; count < MAX_COUNT; count++) {
rc = dm_i2c_write(g_chip.dev, 0, (uchar *)&addrbuf, 1);
} if (rc)rc = dm_i2c_write(dev, 0, (uchar *)&addrbuf, 1); if (rc == 0) break; /* Success, break to skip sleep */ udelay(SLEEP_DURATION_US);
return -rc;
return rc;
/* After the TPM has successfully received the register address
- it needs some time, thus we're sleeping here again, before
@@ -81,7 +81,7 @@ static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) */ for (count = 0; count < MAX_COUNT; count++) { udelay(SLEEP_DURATION_US);
rc = dm_i2c_read(g_chip.dev, 0, buffer, len);
}rc = dm_i2c_read(dev, 0, buffer, len); if (rc == 0) break; /* success, break to skip sleep */
@@ -94,7 +94,7 @@ static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) * be safe on the safe side. */ for (count = 0; count < MAX_COUNT; count++) {
rc = dm_i2c_read(g_chip.dev, addr, buffer, len);
rc = dm_i2c_read(dev, addr, buffer, len); if (rc == 0) break; /* break here to skip sleep */ udelay(SLEEP_DURATION_US);
@@ -104,19 +104,31 @@ static int tpm_tis_i2c_read(u8 addr, u8 *buffer, size_t len) /* Take care of 'guard time' */ udelay(SLEEP_DURATION_US); if (rc)
return -rc;
return rc;
return 0; }
-static int tpm_tis_i2c_write_generic(u8 addr, u8 *buffer, size_t len, +static int tpm_tis_i2c_write_generic(struct udevice *dev, u8 addr,
const u8 *buffer, size_t len, unsigned int sleep_time_us, u8 max_count)
{
struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
struct tpm_chip *chip = dev_get_priv(dev); int rc = 0; int count;
if (chip->chip_type == SLB9635) {
/* Prepare send buffer to include the address */
priv->buf[0] = addr;
memcpy(&(priv->buf[1]), buffer, len);
buffer = priv->buf;
len++;
addr = 0;
}
for (count = 0; count < max_count; count++) {
rc = dm_i2c_write(g_chip.dev, addr, buffer, len);
if (rc == 0) break; /* Success, break to skip sleep */ udelay(sleep_time_us);rc = dm_i2c_write(dev, addr, buffer, len);
@@ -125,7 +137,7 @@ static int tpm_tis_i2c_write_generic(u8 addr, u8 *buffer, size_t len, /* take care of 'guard time' */ udelay(sleep_time_us); if (rc)
return -rc;
return rc;
return 0; }
@@ -146,30 +158,33 @@ static int tpm_tis_i2c_write_generic(u8 addr, u8 *buffer, size_t len,
- Return -EIO on error, 0 on success
*/ -static int tpm_tis_i2c_write(u8 addr, u8 *buffer, size_t len) +static int tpm_tis_i2c_write(struct udevice *dev, u8 addr, const u8 *buffer,
{size_t len)
- return tpm_tis_i2c_write_generic(addr, buffer, len, SLEEP_DURATION_US,
MAX_COUNT);
return tpm_tis_i2c_write_generic(dev, addr, buffer, len,
SLEEP_DURATION_US, MAX_COUNT);
}
/*
- This function is needed especially for the cleanup situation after
- sending TPM_READY
*/
-static int tpm_tis_i2c_write_long(u8 addr, u8 *buffer, size_t len) +static int tpm_tis_i2c_write_long(struct udevice *dev, u8 addr, u8 *buffer,
{size_t len)
- return tpm_tis_i2c_write_generic(addr, buffer, len,
- return tpm_tis_i2c_write_generic(dev, addr, buffer, len, SLEEP_DURATION_LONG_US, MAX_COUNT_LONG); }
-static int tpm_tis_i2c_check_locality(struct tpm_chip *chip, int loc) +static int tpm_tis_i2c_check_locality(struct udevice *dev, int loc) { const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID;
- struct tpm_chip *chip = dev_get_priv(dev); u8 buf; int rc;
- rc = tpm_tis_i2c_read(TPM_ACCESS(loc), &buf, 1);
- rc = tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1); if (rc < 0) return rc;
@@ -178,75 +193,96 @@ static int tpm_tis_i2c_check_locality(struct tpm_chip *chip, int loc) return loc; }
- return -1;
- return -ENOENT; }
-static void tpm_tis_i2c_release_locality(struct tpm_chip *chip, int loc, +static void tpm_tis_i2c_release_locality(struct udevice *dev, int loc, int force) { const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID; u8 buf;
- if (tpm_tis_i2c_read(TPM_ACCESS(loc), &buf, 1) < 0)
if (tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1) < 0) return;
if (force || (buf & mask) == mask) { buf = TPM_ACCESS_ACTIVE_LOCALITY;
tpm_tis_i2c_write(TPM_ACCESS(loc), &buf, 1);
} }tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1);
-static int tpm_tis_i2c_request_locality(struct tpm_chip *chip, int loc) +static int tpm_tis_i2c_request_locality(struct udevice *dev, int loc) {
- struct tpm_chip *chip = dev_get_priv(dev); unsigned long start, stop; u8 buf = TPM_ACCESS_REQUEST_USE; int rc;
- if (tpm_tis_i2c_check_locality(chip, loc) >= 0)
- rc = tpm_tis_i2c_check_locality(dev, loc);
- if (rc >= 0) {
return loc; /* We already have the locality */debug("%s: Already have locality\n", __func__);
- } else if (rc != -ENOENT) {
debug("%s: Failed to get locality: %d\n", __func__, rc);
return rc;
- }
- rc = tpm_tis_i2c_write(TPM_ACCESS(loc), &buf, 1);
- if (rc)
rc = tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1);
if (rc) {
debug("%s: Failed to write to TPM: %d\n", __func__, rc);
return rc;
}
/* Wait for burstcount */ start = get_timer(0); stop = chip->timeout_a; do {
if (tpm_tis_i2c_check_locality(chip, loc) >= 0)
rc = tpm_tis_i2c_check_locality(dev, loc);
if (rc >= 0) {
debug("%s: Have locality\n", __func__); return loc;
} else if (rc != -ENOENT) {
debug("%s: Failed to get locality: %d\n", __func__, rc);
return rc;
mdelay(TPM_TIMEOUT_MS); } while (get_timer(start) < stop);}
- debug("%s: Timeout getting locality: %d\n", __func__, rc);
- return -1;
- return rc; }
-static u8 tpm_tis_i2c_status(struct tpm_chip *chip) +static u8 tpm_tis_i2c_status(struct udevice *dev) {
- struct tpm_chip *chip = dev_get_priv(dev); /* NOTE: Since i2c read may fail, return 0 in this case --> time-out */ u8 buf;
- if (tpm_tis_i2c_read(TPM_STS(chip->locality), &buf, 1) < 0)
- if (tpm_tis_i2c_read(dev, TPM_STS(chip->locality), &buf, 1) < 0) return 0; else return buf; }
-static void tpm_tis_i2c_ready(struct tpm_chip *chip) +static int tpm_tis_i2c_ready(struct udevice *dev) {
struct tpm_chip *chip = dev_get_priv(dev); int rc;
/* This causes the current command to be aborted */ u8 buf = TPM_STS_COMMAND_READY;
debug("%s\n", __func__);
- rc = tpm_tis_i2c_write_long(TPM_STS(chip->locality), &buf, 1);
- rc = tpm_tis_i2c_write_long(dev, TPM_STS(chip->locality), &buf, 1); if (rc) debug("%s: rc=%d\n", __func__, rc);
- return rc; }
-static ssize_t tpm_tis_i2c_get_burstcount(struct tpm_chip *chip) +static ssize_t tpm_tis_i2c_get_burstcount(struct udevice *dev) {
- struct tpm_chip *chip = dev_get_priv(dev); unsigned long start, stop; ssize_t burstcnt; u8 addr, buf[3];
@@ -258,7 +294,7 @@ static ssize_t tpm_tis_i2c_get_burstcount(struct tpm_chip *chip) do { /* Note: STS is little endian */ addr = TPM_STS(chip->locality) + 1;
if (tpm_tis_i2c_read(addr, buf, 3) < 0)
else burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];if (tpm_tis_i2c_read(dev, addr, buf, 3) < 0) burstcnt = 0;
@@ -271,13 +307,13 @@ static ssize_t tpm_tis_i2c_get_burstcount(struct tpm_chip *chip) return -EBUSY; }
-static int tpm_tis_i2c_wait_for_stat(struct tpm_chip *chip, u8 mask, +static int tpm_tis_i2c_wait_for_stat(struct udevice *dev, u8 mask, unsigned long timeout, int *status) { unsigned long start, stop;
/* Check current status */
- *status = tpm_tis_i2c_status(chip);
- *status = tpm_tis_i2c_status(dev); if ((*status & mask) == mask) return 0;
@@ -285,22 +321,23 @@ static int tpm_tis_i2c_wait_for_stat(struct tpm_chip *chip, u8 mask, stop = timeout; do { mdelay(TPM_TIMEOUT_MS);
*status = tpm_tis_i2c_status(chip);
if ((*status & mask) == mask) return 0; } while (get_timer(start) < stop);*status = tpm_tis_i2c_status(dev);
- return -ETIME;
- return -ETIMEDOUT; }
-static int tpm_tis_i2c_recv_data(struct tpm_chip *chip, u8 *buf, size_t count) +static int tpm_tis_i2c_recv_data(struct udevice *dev, u8 *buf, size_t count) {
struct tpm_chip *chip = dev_get_priv(dev); size_t size = 0; ssize_t burstcnt; int rc;
while (size < count) {
burstcnt = tpm_tis_i2c_get_burstcount(chip);
burstcnt = tpm_tis_i2c_get_burstcount(dev);
/* burstcount < 0 -> tpm is busy */ if (burstcnt < 0)
@@ -310,8 +347,8 @@ static int tpm_tis_i2c_recv_data(struct tpm_chip *chip, u8 *buf, size_t count) if (burstcnt > (count - size)) burstcnt = count - size;
rc = tpm_tis_i2c_read(TPM_DATA_FIFO(chip->locality),
&(buf[size]), burstcnt);
rc = tpm_tis_i2c_read(dev, TPM_DATA_FIFO(chip->locality),
if (rc == 0) size += burstcnt; }&(buf[size]), burstcnt);
@@ -319,61 +356,58 @@ static int tpm_tis_i2c_recv_data(struct tpm_chip *chip, u8 *buf, size_t count) return size; }
-static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) +static int tpm_tis_i2c_recv(struct udevice *dev, u8 *buf, size_t count) {
- struct tpm_chip *chip = dev_get_priv(dev); int size = 0; int expected, status;
- int rc;
- if (count < TPM_HEADER_SIZE) {
size = -EIO;
goto out;
- }
status = tpm_tis_i2c_status(dev);
if (status == TPM_STS_COMMAND_READY)
return -EINTR;
if ((status & (TPM_STS_DATA_AVAIL | TPM_STS_VALID)) !=
(TPM_STS_DATA_AVAIL | TPM_STS_VALID))
return -EAGAIN;
debug("...got it;\n");
/* Read first 10 bytes, including tag, paramsize, and result */
- size = tpm_tis_i2c_recv_data(chip, buf, TPM_HEADER_SIZE);
- size = tpm_tis_i2c_recv_data(dev, buf, TPM_HEADER_SIZE); if (size < TPM_HEADER_SIZE) {
error("Unable to read header\n");
goto out;
debug("Unable to read header\n");
return size < 0 ? size : -EIO;
}
expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE); if ((size_t)expected > count) {
error("Error size=%x, expected=%x, count=%x\n", size, expected,
debug("Error size=%x, expected=%x, count=%x\n", size, expected, count);
size = -EIO;
goto out;
}return -ENOSPC;
- size += tpm_tis_i2c_recv_data(chip, &buf[TPM_HEADER_SIZE],
- size += tpm_tis_i2c_recv_data(dev, &buf[TPM_HEADER_SIZE], expected - TPM_HEADER_SIZE); if (size < expected) {
error("Unable to read remainder of result\n");
size = -ETIME;
goto out;
debug("Unable to read remainder of result\n");
}return -ETIMEDOUT;
- tpm_tis_i2c_wait_for_stat(chip, TPM_STS_VALID, chip->timeout_c,
&status);
- rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID, chip->timeout_c,
&status);
- if (rc)
if (status & TPM_STS_DATA_AVAIL) { /* Retry? */return rc;
error("Error left over data\n");
size = -EIO;
goto out;
debug("Error left over data\n");
}return -EIO;
-out:
- tpm_tis_i2c_ready(chip);
- /*
* The TPM needs some time to clean up here,
* so we sleep rather than keeping the bus busy
*/
- mdelay(2);
- tpm_tis_i2c_release_locality(chip, chip->locality, 0);
- return size; }
-static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) +static int tpm_tis_i2c_send(struct udevice *dev, const u8 *buf, size_t len) {
- struct tpm_chip *chip = dev_get_priv(dev); int rc, status; size_t burstcnt; size_t count = 0;
@@ -384,20 +418,21 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) if (len > TPM_DEV_BUFSIZE) return -E2BIG; /* Command is too long for our tpm, sorry */
- if (tpm_tis_i2c_request_locality(chip, 0) < 0)
- if (tpm_tis_i2c_request_locality(dev, 0) < 0) return -EBUSY;
- status = tpm_tis_i2c_status(chip);
- status = tpm_tis_i2c_status(dev); if ((status & TPM_STS_COMMAND_READY) == 0) {
tpm_tis_i2c_ready(chip);
if (tpm_tis_i2c_wait_for_stat(chip, TPM_STS_COMMAND_READY,
chip->timeout_b, &status) < 0) {
rc = -ETIME;
goto out_err;
}
rc = tpm_tis_i2c_ready(dev);
if (rc)
return rc;
rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_COMMAND_READY,
chip->timeout_b, &status);
if (rc)
}return rc;
- burstcnt = tpm_tis_i2c_get_burstcount(chip);
burstcnt = tpm_tis_i2c_get_burstcount(dev);
/* burstcount < 0 -> tpm is busy */ if (burstcnt < 0)
@@ -409,98 +444,79 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = len - count;
#ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION
if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION)
burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION;
if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN)
#endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN;
rc = tpm_tis_i2c_write(TPM_DATA_FIFO(chip->locality),
&(buf[count]), burstcnt);
rc = tpm_tis_i2c_write(dev, TPM_DATA_FIFO(chip->locality),
if (rc == 0) count += burstcnt; else { debug("%s: error\n", __func__);&(buf[count]), burstcnt);
if (retry++ > 10) {
rc = -EIO;
goto out_err;
}
rc = tpm_tis_i2c_wait_for_stat(chip, TPM_STS_VALID,
if (retry++ > 10)
return -EIO;
rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID, chip->timeout_c, &status); if (rc)
goto out_err;
return rc;
if ((status & TPM_STS_DATA_EXPECT) == 0) {
rc = -EIO;
goto out_err;
}
if ((status & TPM_STS_DATA_EXPECT) == 0)
return -EIO;
} }
/* Go and do it */
- tpm_tis_i2c_write(TPM_STS(chip->locality), &sts, 1);
- debug("done\n");
rc = tpm_tis_i2c_write(dev, TPM_STS(chip->locality), &sts, 1);
if (rc < 0)
return rc;
debug("%s: done, rc=%d\n", __func__, rc);
return len;
+}
+static int tpm_tis_i2c_cleanup(struct udevice *dev) +{
- struct tpm_chip *chip = dev_get_priv(dev);
-out_err:
- debug("%s: out_err\n", __func__);
- tpm_tis_i2c_ready(chip);
- tpm_tis_i2c_ready(dev); /*
*/ mdelay(2);
- The TPM needs some time to clean up here,
- so we sleep rather than keeping the bus busy
- tpm_tis_i2c_release_locality(chip, chip->locality, 0);
- tpm_tis_i2c_release_locality(dev, chip->locality, 0);
- return rc;
-}
-static enum i2c_chip_type tpm_tis_i2c_chip_type(void) -{ -#if CONFIG_IS_ENABLED(OF_CONTROL)
- const void *blob = gd->fdt_blob;
- if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9645_TPM) >= 0)
return SLB9645;
- if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM) >= 0)
return SLB9635;
-#endif
- return UNKNOWN;
return 0; }
static int tpm_tis_i2c_init(struct udevice *dev) {
- struct tpm_chip *chip = &g_chip;
- struct tpm_chip *chip = dev_get_priv(dev); u32 vendor; u32 expected_did_vid;
- int rc;
g_chip.dev = dev;
g_chip.chip_type = tpm_tis_i2c_chip_type(); chip->is_open = 1;
/* Disable interrupts (not supported) */
chip->irq = 0;
/* Default timeouts - these could move to the device tree */ chip->timeout_a = TIS_SHORT_TIMEOUT_MS; chip->timeout_b = TIS_LONG_TIMEOUT_MS; chip->timeout_c = TIS_SHORT_TIMEOUT_MS; chip->timeout_d = TIS_SHORT_TIMEOUT_MS;
chip->req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID;
chip->req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID;
chip->req_canceled = TPM_STS_COMMAND_READY;
if (tpm_tis_i2c_request_locality(chip, 0) < 0)
return -ENODEV;
rc = tpm_tis_i2c_request_locality(dev, 0);
if (rc < 0)
return rc;
/* Read four bytes from DID_VID register */
- if (tpm_tis_i2c_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) {
tpm_tis_i2c_release_locality(chip, 0, 1);
- if (tpm_tis_i2c_read(dev, TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) {
return -EIO; }tpm_tis_i2c_release_locality(dev, 0, 1);
- if (g_chip.chip_type == SLB9635) {
- if (chip->chip_type == SLB9635) { vendor = be32_to_cpu(vendor); expected_did_vid = TPM_TIS_I2C_DID_VID_9635; } else {
@@ -508,13 +524,14 @@ static int tpm_tis_i2c_init(struct udevice *dev) expected_did_vid = TPM_TIS_I2C_DID_VID_9645; }
- if (g_chip.chip_type != UNKNOWN && vendor != expected_did_vid) {
if (chip->chip_type != UNKNOWN && vendor != expected_did_vid) { error("Vendor id did not match! ID was %08x\n", vendor); return -ENODEV; }
chip->vend_dev = vendor; debug("1.2 TPM (chip type %s device-id 0x%X)\n",
chip_name[g_chip.chip_type], vendor >> 16);
chip_name[chip->chip_type], vendor >> 16);
/*
- A timeout query to TPM can be placed here.
@@ -524,225 +541,83 @@ static int tpm_tis_i2c_init(struct udevice *dev) return 0; }
-/* Returns max number of milliseconds to wait */ -static unsigned long tpm_tis_i2c_calc_ordinal_duration(struct tpm_chip *chip,
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 = chip->duration[duration_idx];
- if (duration <= 0)
return 2 * 60 * HZ; /* Two minutes timeout */
- else
return duration;
-}
-static ssize_t tpm_tis_i2c_transmit(const unsigned char *buf, size_t bufsiz) +static int tpm_tis_i2c_open(struct udevice *dev) {
- struct tpm_chip *chip = dev_get_priv(dev); int rc;
u32 count, ordinal;
unsigned long start, stop;
struct tpm_chip *chip = &g_chip;
/* switch endianess: big->little */
count = get_unaligned_be32(buf + TPM_CMD_COUNT_BYTE);
ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE);
if (count == 0) {
error("no data\n");
return -ENODATA;
}
if (count > bufsiz) {
error("invalid count value %x %zx\n", count, bufsiz);
return -E2BIG;
}
debug("Calling send\n");
rc = tpm_tis_i2c_send(chip, (u8 *)buf, count);
debug(" ... done calling send\n");
if (rc < 0) {
error("tpm_transmit: tpm_send: error %d\n", rc);
goto out;
}
if (chip->irq)
goto out_recv;
start = get_timer(0);
stop = tpm_tis_i2c_calc_ordinal_duration(chip, ordinal);
do {
debug("waiting for status... %ld %ld\n", start, stop);
u8 status = tpm_tis_i2c_status(chip);
if ((status & chip->req_complete_mask) ==
chip->req_complete_val) {
debug("...got it;\n");
goto out_recv;
}
if (status == chip->req_canceled) {
error("Operation Canceled\n");
rc = -ECANCELED;
goto out;
}
mdelay(TPM_TIMEOUT_MS);
} while (get_timer(start) < stop);
tpm_tis_i2c_ready(chip);
error("Operation Timed out\n");
rc = -ETIME;
goto out;
-out_recv:
- debug("out_recv: reading response...\n");
- rc = tpm_tis_i2c_recv(chip, (u8 *)buf, TPM_BUFSIZE);
- debug("%s: start\n", __func__);
- if (chip->is_open)
return -EBUSY;
- rc = tpm_tis_i2c_init(dev); if (rc < 0)
error("tpm_transmit: tpm_recv: error %d\n", rc);
chip->is_open = 0;
-out: return rc; }
-/**
- Decode TPM configuration.
- @param dev Returns a configuration of TPM device
- @return 0 if ok, -1 on error
- */
-static int tpm_tis_i2c_decode_config(struct tpm_chip *chip) +static int tpm_tis_i2c_close(struct udevice *dev) {
- const void *blob = gd->fdt_blob;
- struct udevice *bus;
- int chip_addr;
- int parent;
- int node;
- int ret;
- node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM);
- if (node < 0) {
node = fdtdec_next_compatible(blob, 0,
COMPAT_INFINEON_SLB9645_TPM);
- }
- if (node < 0) {
debug("%s: Node not found\n", __func__);
return -1;
- }
- parent = fdt_parent_offset(blob, node);
- if (parent < 0) {
debug("%s: Cannot find node parent\n", __func__);
return -1;
- }
- struct tpm_chip *chip = dev_get_priv(dev);
- /*
* TODO(sjg@chromium.org): Remove this when driver model supports
* TPMs
*/
- ret = uclass_get_device_by_of_offset(UCLASS_I2C, parent, &bus);
- if (ret) {
debug("Cannot find bus for node '%s: ret=%d'\n",
fdt_get_name(blob, parent, NULL), ret);
return ret;
- }
- chip_addr = fdtdec_get_int(blob, node, "reg", -1);
- if (chip_addr == -1) {
debug("Cannot find reg property for node '%s: ret=%d'\n",
fdt_get_name(blob, node, NULL), ret);
return ret;
- }
- /*
* TODO(sjg@chromium.org): Older TPMs will need to use the older method
* in tpm_tis_i2c_read() so the offset length needs to be 0 here.
*/
- ret = i2c_get_chip(bus, chip_addr, 1, &chip->dev);
- if (ret) {
debug("Cannot find device for node '%s: ret=%d'\n",
fdt_get_name(blob, node, NULL), ret);
return ret;
if (chip->is_open) {
tpm_tis_i2c_release_locality(dev, chip->locality, 1);
chip->is_open = 0;
chip->vend_dev = 0;
}
return 0; }
-int tis_init(void) +static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size) {
- if (g_chip.inited)
return 0;
- if (tpm_tis_i2c_decode_config(&g_chip))
return -1;
- debug("%s: done\n", __func__);
- struct tpm_chip *chip = dev_get_priv(dev);
- g_chip.inited = 1;
- if (size < 50)
return -ENOSPC;
- return 0;
- return snprintf(buf, size, "1.2 TPM (%s, chip type %s device-id 0x%x)",
chip->is_open ? "open" : "closed",
chip_name[chip->chip_type],
}chip->vend_dev >> 16);
-int tis_open(void) +static int tpm_tis_i2c_probe(struct udevice *dev) {
- int rc;
- if (!g_chip.inited)
return -1;
- debug("%s: start\n", __func__);
- if (g_chip.is_open)
return -EBUSY;
- rc = tpm_tis_i2c_init(g_chip.dev);
- if (rc < 0)
g_chip.is_open = 0;
- return rc;
-}
- struct tpm_chip_priv *uc_priv = dev_get_uclass_priv(dev);
- struct tpm_chip *chip = dev_get_priv(dev);
-int tis_close(void) -{
- if (!g_chip.inited)
return -1;
- chip->chip_type = dev_get_driver_data(dev);
- if (g_chip.is_open) {
tpm_tis_i2c_release_locality(&g_chip, g_chip.locality, 1);
g_chip.is_open = 0;
- }
/* TODO: These need to be checked and tuned */
uc_priv->duration_ms[TPM_SHORT] = TIS_SHORT_TIMEOUT_MS;
uc_priv->duration_ms[TPM_MEDIUM] = TIS_LONG_TIMEOUT_MS;
uc_priv->duration_ms[TPM_LONG] = TIS_LONG_TIMEOUT_MS;
uc_priv->retry_time_ms = TPM_TIMEOUT_MS;
return 0; }
-int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
uint8_t *recvbuf, size_t *rbuf_len)
-{
- int len;
- uint8_t buf[4096];
- if (!g_chip.inited)
return -1;
- if (sizeof(buf) < sbuf_size)
return -1;
- memcpy(buf, sendbuf, sbuf_size);
- len = tpm_tis_i2c_transmit(buf, sbuf_size);
- if (len < 10) {
*rbuf_len = 0;
return -1;
- }
+static const struct tpm_ops tpm_tis_i2c_ops = {
- .open = tpm_tis_i2c_open,
- .close = tpm_tis_i2c_close,
- .get_desc = tpm_tis_get_desc,
- .send = tpm_tis_i2c_send,
- .recv = tpm_tis_i2c_recv,
- .cleanup = tpm_tis_i2c_cleanup,
+};
- memcpy(recvbuf, buf, len);
- *rbuf_len = len;
+static const struct udevice_id tpm_tis_i2c_ids[] = {
- { .compatible = "infineon,slb9635tt", .data = SLB9635 },
- { .compatible = "infineon,slb9645tt", .data = SLB9645 },
- { }
+};
- return 0;
-} +U_BOOT_DRIVER(tpm_tis_i2c) = {
- .name = "tpm_tis_i2c",
- .id = UCLASS_TPM,
- .of_match = tpm_tis_i2c_ids,
- .ops = &tpm_tis_i2c_ops,
- .probe = tpm_tis_i2c_probe,
- .priv_auto_alloc_size = sizeof(struct tpm_chip),
+}; diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_i2c.h index 02cc2eb..3b510d1 100644 --- a/drivers/tpm/tpm_tis_i2c.h +++ b/drivers/tpm/tpm_tis_i2c.h @@ -37,9 +37,6 @@ enum tpm_timeout { #define TPM_RSP_SIZE_BYTE 2 #define TPM_RSP_RC_BYTE 6
-/* Max buffer size supported by our tpm */ -#define TPM_DEV_BUFSIZE 1260
- enum i2c_chip_type { SLB9635, SLB9645,
@@ -47,17 +44,10 @@ enum i2c_chip_type { };
struct tpm_chip {
- bool inited; int is_open;
- u8 req_complete_mask;
- u8 req_complete_val;
- u8 req_canceled;
- int irq; int locality;
- u32 vend_dev; unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */
- unsigned long duration[3]; /* msec */
- struct udevice *dev;
- u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)]; /* Max buffer size + addr */ enum i2c_chip_type chip_type; };
@@ -129,8 +119,6 @@ struct tpm_cmd_t { */ #define MAX_COUNT_LONG 50
-#define TPM_HEADER_SIZE 10
- enum tis_access { TPM_ACCESS_VALID = 0x80, TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
@@ -155,10 +143,4 @@ enum tis_status { #define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) #define TPM_DID_VID(l) (0x0006 | ((l) << 4))
-/* Extended error numbers from linux (see errno.h) */ -#define ECANCELED 125 /* Operation Canceled */
-/* Timer frequency. Corresponds to msec timer resolution */ -#define HZ 1000
- #endif
diff --git a/include/fdtdec.h b/include/fdtdec.h index 0cb6fa0..3e23731 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -154,8 +154,6 @@ enum fdt_compat_id { COMPAT_MAXIM_MAX77686_PMIC, /* MAX77686 PMIC */ COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */ COMPAT_MAXIM_98095_CODEC, /* MAX98095 Codec */
- COMPAT_INFINEON_SLB9635_TPM, /* Infineon SLB9635 TPM */
- COMPAT_INFINEON_SLB9645_TPM, /* Infineon SLB9645 TPM */ COMPAT_SAMSUNG_EXYNOS5_I2C, /* Exynos5 High Speed I2C Controller */ COMPAT_SANDBOX_LCD_SDL, /* Sandbox LCD emulation with SDL */ COMPAT_SAMSUNG_EXYNOS_SYSMMU, /* Exynos sysmmu */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c index b65e1e6..197ef02 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -58,8 +58,6 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686"), COMPAT(GENERIC_SPI_FLASH, "spi-flash"), COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"),
- COMPAT(INFINEON_SLB9635_TPM, "infineon,slb9635-tpm"),
- COMPAT(INFINEON_SLB9645_TPM, "infineon,slb9645tt"), COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"), COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"), COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),

On 24 August 2015 at 14:22, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
This one looks good to me.
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

Convert the tpm_tis_lpc driver to use driver model and update boards which use it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Update driver for the new uclass interface
configs/chromebook_link_defconfig | 2 + configs/chromebox_panther_defconfig | 2 + configs/coreboot-x86_defconfig | 2 + drivers/tpm/tpm_tis_lpc.c | 286 +++++++++++++++++------------------- 4 files changed, 137 insertions(+), 155 deletions(-)
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index b0fc5ca..85752e4 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -11,12 +11,14 @@ CONFIG_HAVE_VGA_BIOS=y CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y +CONFIG_CMD_TPM=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index e7ef8fe..a6bafe3 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -11,12 +11,14 @@ CONFIG_HAVE_VGA_BIOS=y CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y +CONFIG_CMD_TPM=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y diff --git a/configs/coreboot-x86_defconfig b/configs/coreboot-x86_defconfig index 66b8caa..fda2b7e 100644 --- a/configs/coreboot-x86_defconfig +++ b/configs/coreboot-x86_defconfig @@ -9,11 +9,13 @@ CONFIG_TSC_CALIBRATION_BYPASS=y CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y +CONFIG_CMD_TPM=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_NETDEVICES=y CONFIG_E1000=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_LPC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c index 3109c50..b41c3ce 100644 --- a/drivers/tpm/tpm_tis_lpc.c +++ b/drivers/tpm/tpm_tis_lpc.c @@ -14,9 +14,11 @@ */
#include <common.h> -#include <asm/io.h> +#include <dm.h> +#include <mapmem.h> #include <tis.h> #include <tpm.h> +#include <asm/io.h>
#define PREFIX "lpc_tpm: "
@@ -37,13 +39,15 @@ struct tpm_locality { u8 padding4[251]; };
+struct tpm_tis_lpc_priv { + struct tpm_locality *regs; +}; + /* * This pointer refers to the TPM chip, 5 of its localities are mapped as an * array. */ #define TPM_TOTAL_LOCALITIES 5 -static struct tpm_locality *lpc_tpm_dev = - (struct tpm_locality *)CONFIG_TPM_TIS_BASE_ADDRESS;
/* Some registers' bit field definitions */ #define TIS_STS_VALID (1 << 7) /* 0x80 */ @@ -64,85 +68,45 @@ static struct tpm_locality *lpc_tpm_dev = #define TIS_STS_BURST_COUNT_MASK (0xffff) #define TIS_STS_BURST_COUNT_SHIFT (8)
-/* - * Error value returned if a tpm register does not enter the expected state - * after continuous polling. No actual TPM register reading ever returns -1, - * so this value is a safe error indication to be mixed with possible status - * register values. - */ -#define TPM_TIMEOUT_ERR (-1) - -/* Error value returned on various TPM driver errors. */ -#define TPM_DRIVER_ERR (1) - /* 1 second is plenty for anything TPM does. */ #define MAX_DELAY_US (1000 * 1000)
/* Retrieve burst count value out of the status register contents. */ static u16 burst_count(u32 status) { - return (status >> TIS_STS_BURST_COUNT_SHIFT) & TIS_STS_BURST_COUNT_MASK; + return (status >> TIS_STS_BURST_COUNT_SHIFT) & + TIS_STS_BURST_COUNT_MASK; }
-/* - * Structures defined below allow creating descriptions of TPM vendor/device - * ID information for run time discovery. The only device the system knows - * about at this time is Infineon slb9635. - */ -struct device_name { - u16 dev_id; - const char * const dev_name; -}; - -struct vendor_name { - u16 vendor_id; - const char *vendor_name; - const struct device_name *dev_names; -}; - -static const struct device_name infineon_devices[] = { - {0xb, "SLB9635 TT 1.2"}, - {0} -}; - -static const struct vendor_name vendor_names[] = { - {0x15d1, "Infineon", infineon_devices}, -}; - -/* - * Cached vendor/device ID pair to indicate that the device has been already - * discovered. - */ -static u32 vendor_dev_id; - /* TPM access wrappers to support tracing */ -static u8 tpm_read_byte(const u8 *ptr) +static u8 tpm_read_byte(struct tpm_tis_lpc_priv *priv, const u8 *ptr) { u8 ret = readb(ptr); debug(PREFIX "Read reg 0x%4.4x returns 0x%2.2x\n", - (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, ret); + (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, ret); return ret; }
-static u32 tpm_read_word(const u32 *ptr) +static u32 tpm_read_word(struct tpm_tis_lpc_priv *priv, const u32 *ptr) { u32 ret = readl(ptr); debug(PREFIX "Read reg 0x%4.4x returns 0x%8.8x\n", - (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, ret); + (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, ret); return ret; }
-static void tpm_write_byte(u8 value, u8 *ptr) +static void tpm_write_byte(struct tpm_tis_lpc_priv *priv, u8 value, u8 *ptr) { debug(PREFIX "Write reg 0x%4.4x with 0x%2.2x\n", - (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, value); + (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, value); writeb(value, ptr); }
-static void tpm_write_word(u32 value, u32 *ptr) +static void tpm_write_word(struct tpm_tis_lpc_priv *priv, u32 value, + u32 *ptr) { debug(PREFIX "Write reg 0x%4.4x with 0x%8.8x\n", - (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, value); + (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, value); writel(value, ptr); }
@@ -157,67 +121,51 @@ static void tpm_write_word(u32 value, u32 *ptr) * @expected - value the field(s) are supposed to be set to * * Returns the register contents in case the expected value was found in the - * appropriate register bits, or TPM_TIMEOUT_ERR on timeout. + * appropriate register bits, or -ETIMEDOUT on timeout. */ -static u32 tis_wait_reg(u32 *reg, u8 mask, u8 expected) +static int tis_wait_reg(struct tpm_tis_lpc_priv *priv, u32 *reg, u8 mask, + u8 expected) { u32 time_us = MAX_DELAY_US;
while (time_us > 0) { - u32 value = tpm_read_word(reg); + u32 value = tpm_read_word(priv, reg); if ((value & mask) == expected) return value; udelay(1); /* 1 us */ time_us--; } - return TPM_TIMEOUT_ERR; + + return -ETIMEDOUT; }
/* * Probe the TPM device and try determining its manufacturer/device name. * - * Returns 0 on success (the device is found or was found during an earlier - * invocation) or TPM_DRIVER_ERR if the device is not found. + * Returns 0 on success, -ve on error */ -int tis_init(void) +static int tpm_tis_lpc_probe(struct udevice *dev) { - u32 didvid = tpm_read_word(&lpc_tpm_dev[0].did_vid); - int i; - const char *device_name = "unknown"; - const char *vendor_name = device_name; - u16 vid, did; - - if (vendor_dev_id) - return 0; /* Already probed. */ - - if (!didvid || (didvid == 0xffffffff)) { - printf("%s: No TPM device found\n", __func__); - return TPM_DRIVER_ERR; - } + struct tpm_tis_lpc_priv *priv = dev_get_priv(dev); + u32 vid, did; + fdt_addr_t addr; + u32 didvid;
- vendor_dev_id = didvid; + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + priv->regs = map_sysmem(addr, 0); + didvid = tpm_read_word(priv, &priv->regs[0].did_vid);
vid = didvid & 0xffff; did = (didvid >> 16) & 0xffff; - for (i = 0; i < ARRAY_SIZE(vendor_names); i++) { - int j = 0; - u16 known_did; - - if (vid == vendor_names[i].vendor_id) - vendor_name = vendor_names[i].vendor_name; - - while ((known_did = vendor_names[i].dev_names[j].dev_id) != 0) { - if (known_did == did) { - device_name = - vendor_names[i].dev_names[j].dev_name; - break; - } - j++; - } - break; + if (vid != 0x15d1 || did != 0xb) { + debug("Invalid vendor/device ID %04x/%04x\n", vid, did); + return -ENOSYS; }
- printf("Found TPM %s by %s\n", device_name, vendor_name); + debug("Found TPM %s by %s\n", "SLB9635 TT 1.2", "Infineon"); + return 0; }
@@ -229,23 +177,25 @@ int tis_init(void) * @data - address of the data to send, byte by byte * @len - length of the data to send * - * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does - * not accept the entire command). + * Returns 0 on success, -ve on error (in case the device does not accept + * the entire command). */ -static u32 tis_senddata(const u8 * const data, u32 len) +static int tis_senddata(struct udevice *dev, const u8 *data, size_t len) { + struct tpm_tis_lpc_priv *priv = dev_get_priv(dev); + struct tpm_locality *regs = priv->regs; u32 offset = 0; u16 burst = 0; u32 max_cycles = 0; u8 locality = 0; u32 value;
- value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, + value = tis_wait_reg(priv, ®s[locality].tpm_status, TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY); - if (value == TPM_TIMEOUT_ERR) { + if (value == -ETIMEDOUT) { printf("%s:%d - failed to get 'command_ready' status\n", __FILE__, __LINE__); - return TPM_DRIVER_ERR; + return value; } burst = burst_count(value);
@@ -257,11 +207,11 @@ static u32 tis_senddata(const u8 * const data, u32 len) if (max_cycles++ == MAX_DELAY_US) { printf("%s:%d failed to feed %d bytes of %d\n", __FILE__, __LINE__, len - offset, len); - return TPM_DRIVER_ERR; + return -ETIMEDOUT; } udelay(1); - burst = burst_count(tpm_read_word(&lpc_tpm_dev - [locality].tpm_status)); + burst = burst_count(tpm_read_word(priv, + ®s[locality].tpm_status)); }
max_cycles = 0; @@ -277,16 +227,16 @@ static u32 tis_senddata(const u8 * const data, u32 len) */ count = min((u32)burst, len - offset - 1); while (count--) - tpm_write_byte(data[offset++], - &lpc_tpm_dev[locality].data); + tpm_write_byte(priv, data[offset++], + ®s[locality].data);
- value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, + value = tis_wait_reg(priv, ®s[locality].tpm_status, TIS_STS_VALID, TIS_STS_VALID);
- if ((value == TPM_TIMEOUT_ERR) || !(value & TIS_STS_EXPECT)) { + if ((value == -ETIMEDOUT) || !(value & TIS_STS_EXPECT)) { printf("%s:%d TPM command feed overflow\n", __FILE__, __LINE__); - return TPM_DRIVER_ERR; + return value == -ETIMEDOUT ? value : -EIO; }
burst = burst_count(value); @@ -301,21 +251,21 @@ static u32 tis_senddata(const u8 * const data, u32 len) }
/* Send the last byte. */ - tpm_write_byte(data[offset++], &lpc_tpm_dev[locality].data); + tpm_write_byte(priv, data[offset++], ®s[locality].data); /* * Verify that TPM does not expect any more data as part of this * command. */ - value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, + value = tis_wait_reg(priv, ®s[locality].tpm_status, TIS_STS_VALID, TIS_STS_VALID); - if ((value == TPM_TIMEOUT_ERR) || (value & TIS_STS_EXPECT)) { + if ((value == -ETIMEDOUT) || (value & TIS_STS_EXPECT)) { printf("%s:%d unexpected TPM status 0x%x\n", __FILE__, __LINE__, value); - return TPM_DRIVER_ERR; + return value == -ETIMEDOUT ? value : -EIO; }
/* OK, sitting pretty, let's start the command execution. */ - tpm_write_word(TIS_STS_TPM_GO, &lpc_tpm_dev[locality].tpm_status); + tpm_write_word(priv, TIS_STS_TPM_GO, ®s[locality].tpm_status); return 0; }
@@ -329,25 +279,27 @@ static u32 tis_senddata(const u8 * const data, u32 len) * * On success stores the number of received bytes to len and returns 0. On * errors (misformatted TPM data or synchronization problems) returns - * TPM_DRIVER_ERR. + * -ve value. */ -static u32 tis_readresponse(u8 *buffer, u32 *len) +static int tis_readresponse(struct udevice *dev, u8 *buffer, size_t len) { + struct tpm_tis_lpc_priv *priv = dev_get_priv(dev); + struct tpm_locality *regs = priv->regs; u16 burst; u32 value; u32 offset = 0; u8 locality = 0; const u32 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID; - u32 expected_count = *len; + u32 expected_count = len; int max_cycles = 0;
/* Wait for the TPM to process the command. */ - value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, + value = tis_wait_reg(priv, ®s[locality].tpm_status, has_data, has_data); - if (value == TPM_TIMEOUT_ERR) { + if (value == -ETIMEDOUT) { printf("%s:%d failed processing command\n", __FILE__, __LINE__); - return TPM_DRIVER_ERR; + return value; }
do { @@ -355,18 +307,17 @@ static u32 tis_readresponse(u8 *buffer, u32 *len) if (max_cycles++ == MAX_DELAY_US) { printf("%s:%d TPM stuck on read\n", __FILE__, __LINE__); - return TPM_DRIVER_ERR; + return -EIO; } udelay(1); - value = tpm_read_word(&lpc_tpm_dev - [locality].tpm_status); + value = tpm_read_word(priv, ®s[locality].tpm_status); }
max_cycles = 0;
while (burst-- && (offset < expected_count)) { - buffer[offset++] = tpm_read_byte(&lpc_tpm_dev - [locality].data); + buffer[offset++] = tpm_read_byte(priv, + ®s[locality].data);
if (offset == 6) { /* @@ -383,22 +334,22 @@ static u32 tis_readresponse(u8 *buffer, u32 *len) expected_count = be32_to_cpu(real_length);
if ((expected_count < offset) || - (expected_count > *len)) { + (expected_count > len)) { printf("%s:%d bad response size %d\n", __FILE__, __LINE__, expected_count); - return TPM_DRIVER_ERR; + return -ENOSPC; } } }
/* Wait for the next portion. */ - value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status, + value = tis_wait_reg(priv, ®s[locality].tpm_status, TIS_STS_VALID, TIS_STS_VALID); - if (value == TPM_TIMEOUT_ERR) { + if (value == -ETIMEDOUT) { printf("%s:%d failed to read response\n", __FILE__, __LINE__); - return TPM_DRIVER_ERR; + return value; }
if (offset == expected_count) @@ -413,65 +364,90 @@ static u32 tis_readresponse(u8 *buffer, u32 *len) if (value & TIS_STS_DATA_AVAILABLE) { printf("%s:%d wrong receive status %x\n", __FILE__, __LINE__, value); - return TPM_DRIVER_ERR; + return -EBADMSG; }
/* Tell the TPM that we are done. */ - tpm_write_word(TIS_STS_COMMAND_READY, &lpc_tpm_dev - [locality].tpm_status); - *len = offset; - return 0; + tpm_write_word(priv, TIS_STS_COMMAND_READY, + ®s[locality].tpm_status); + + return offset; }
-int tis_open(void) +static int tpm_tis_lpc_open(struct udevice *dev) { + struct tpm_tis_lpc_priv *priv = dev_get_priv(dev); + struct tpm_locality *regs = priv->regs; u8 locality = 0; /* we use locality zero for everything. */ + int ret;
/* now request access to locality. */ - tpm_write_word(TIS_ACCESS_REQUEST_USE, &lpc_tpm_dev[locality].access); + tpm_write_word(priv, TIS_ACCESS_REQUEST_USE, ®s[locality].access);
/* did we get a lock? */ - if (tis_wait_reg(&lpc_tpm_dev[locality].access, + ret = tis_wait_reg(priv, ®s[locality].access, TIS_ACCESS_ACTIVE_LOCALITY, - TIS_ACCESS_ACTIVE_LOCALITY) == TPM_TIMEOUT_ERR) { + TIS_ACCESS_ACTIVE_LOCALITY); + if (ret == -ETIMEDOUT) { printf("%s:%d - failed to lock locality %d\n", __FILE__, __LINE__, locality); - return TPM_DRIVER_ERR; + return ret; }
- tpm_write_word(TIS_STS_COMMAND_READY, - &lpc_tpm_dev[locality].tpm_status); + tpm_write_word(priv, TIS_STS_COMMAND_READY, + ®s[locality].tpm_status); return 0; }
-int tis_close(void) +static int tpm_tis_lpc_close(struct udevice *dev) { + struct tpm_tis_lpc_priv *priv = dev_get_priv(dev); + struct tpm_locality *regs = priv->regs; u8 locality = 0;
- if (tpm_read_word(&lpc_tpm_dev[locality].access) & + if (tpm_read_word(priv, ®s[locality].access) & TIS_ACCESS_ACTIVE_LOCALITY) { - tpm_write_word(TIS_ACCESS_ACTIVE_LOCALITY, - &lpc_tpm_dev[locality].access); + tpm_write_word(priv, TIS_ACCESS_ACTIVE_LOCALITY, + ®s[locality].access);
- if (tis_wait_reg(&lpc_tpm_dev[locality].access, - TIS_ACCESS_ACTIVE_LOCALITY, 0) == - TPM_TIMEOUT_ERR) { + if (tis_wait_reg(priv, ®s[locality].access, + TIS_ACCESS_ACTIVE_LOCALITY, 0) == -ETIMEDOUT) { printf("%s:%d - failed to release locality %d\n", __FILE__, __LINE__, locality); - return TPM_DRIVER_ERR; + return -ETIMEDOUT; } } return 0; }
-int tis_sendrecv(const u8 *sendbuf, size_t send_size, - u8 *recvbuf, size_t *recv_len) +static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size) { - if (tis_senddata(sendbuf, send_size)) { - printf("%s:%d failed sending data to TPM\n", - __FILE__, __LINE__); - return TPM_DRIVER_ERR; - } + if (size < 50) + return -ENOSPC;
- return tis_readresponse(recvbuf, (u32 *)recv_len); + return snprintf(buf, size, "1.2 TPM (vendor %s, chip %s)", + "Infineon", "SLB9635 TT 1.2"); } + + +static const struct tpm_ops tpm_tis_lpc_ops = { + .open = tpm_tis_lpc_open, + .close = tpm_tis_lpc_close, + .get_desc = tpm_tis_get_desc, + .send = tis_senddata, + .recv = tis_readresponse, +}; + +static const struct udevice_id tpm_tis_lpc_ids[] = { + { .compatible = "infineon,slb9635lpc" }, + { } +}; + +U_BOOT_DRIVER(tpm_tis_lpc) = { + .name = "tpm_tis_lpc", + .id = UCLASS_TPM, + .of_match = tpm_tis_lpc_ids, + .ops = &tpm_tis_lpc_ops, + .probe = tpm_tis_lpc_probe, + .priv_auto_alloc_size = sizeof(struct tpm_tis_lpc_priv), +};

Hi Simon,
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
Convert the tpm_tis_lpc driver to use driver model and update boards which use it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
Update driver for the new uclass interface
configs/chromebook_link_defconfig | 2 + configs/chromebox_panther_defconfig | 2 + configs/coreboot-x86_defconfig | 2 + drivers/tpm/tpm_tis_lpc.c | 286 +++++++++++++++++------------------- 4 files changed, 137 insertions(+), 155 deletions(-)
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index b0fc5ca..85752e4 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -11,12 +11,14 @@ CONFIG_HAVE_VGA_BIOS=y CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y +CONFIG_CMD_TPM=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index e7ef8fe..a6bafe3 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -11,12 +11,14 @@ CONFIG_HAVE_VGA_BIOS=y CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y +CONFIG_CMD_TPM=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y diff --git a/configs/coreboot-x86_defconfig b/configs/coreboot-x86_defconfig index 66b8caa..fda2b7e 100644 --- a/configs/coreboot-x86_defconfig +++ b/configs/coreboot-x86_defconfig @@ -9,11 +9,13 @@ CONFIG_TSC_CALIBRATION_BYPASS=y CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y +CONFIG_CMD_TPM=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_NETDEVICES=y CONFIG_E1000=y +CONFIG_DM_TPM=y CONFIG_TPM_TIS_LPC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c index 3109c50..b41c3ce 100644 --- a/drivers/tpm/tpm_tis_lpc.c +++ b/drivers/tpm/tpm_tis_lpc.c @@ -14,9 +14,11 @@ */
#include <common.h> -#include <asm/io.h> +#include <dm.h> +#include <mapmem.h> #include <tis.h> #include <tpm.h> +#include <asm/io.h>
#define PREFIX "lpc_tpm: "
@@ -37,13 +39,15 @@ struct tpm_locality { u8 padding4[251]; };
+struct tpm_tis_lpc_priv {
- struct tpm_locality *regs;
+};
- /*
*/ #define TPM_TOTAL_LOCALITIES 5
- This pointer refers to the TPM chip, 5 of its localities are mapped as an
- array.
-static struct tpm_locality *lpc_tpm_dev =
(struct tpm_locality *)CONFIG_TPM_TIS_BASE_ADDRESS;
/* Some registers' bit field definitions */ #define TIS_STS_VALID (1 << 7) /* 0x80 */
@@ -64,85 +68,45 @@ static struct tpm_locality *lpc_tpm_dev = #define TIS_STS_BURST_COUNT_MASK (0xffff) #define TIS_STS_BURST_COUNT_SHIFT (8)
-/*
- Error value returned if a tpm register does not enter the expected state
- after continuous polling. No actual TPM register reading ever returns -1,
- so this value is a safe error indication to be mixed with possible status
- register values.
- */
-#define TPM_TIMEOUT_ERR (-1)
-/* Error value returned on various TPM driver errors. */ -#define TPM_DRIVER_ERR (1)
/* 1 second is plenty for anything TPM does. */ #define MAX_DELAY_US (1000 * 1000)
/* Retrieve burst count value out of the status register contents. */ static u16 burst_count(u32 status) {
return (status >> TIS_STS_BURST_COUNT_SHIFT) & TIS_STS_BURST_COUNT_MASK;
- return (status >> TIS_STS_BURST_COUNT_SHIFT) &
}TIS_STS_BURST_COUNT_MASK;
-/*
- Structures defined below allow creating descriptions of TPM vendor/device
- ID information for run time discovery. The only device the system knows
- about at this time is Infineon slb9635.
- */
-struct device_name {
- u16 dev_id;
- const char * const dev_name;
-};
-struct vendor_name {
- u16 vendor_id;
- const char *vendor_name;
- const struct device_name *dev_names;
-};
-static const struct device_name infineon_devices[] = {
- {0xb, "SLB9635 TT 1.2"},
- {0}
-};
-static const struct vendor_name vendor_names[] = {
- {0x15d1, "Infineon", infineon_devices},
-};
-/*
- Cached vendor/device ID pair to indicate that the device has been already
- discovered.
- */
-static u32 vendor_dev_id;
- /* TPM access wrappers to support tracing */
-static u8 tpm_read_byte(const u8 *ptr) +static u8 tpm_read_byte(struct tpm_tis_lpc_priv *priv, const u8 *ptr) { u8 ret = readb(ptr); debug(PREFIX "Read reg 0x%4.4x returns 0x%2.2x\n",
(u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, ret);
return ret; }(u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, ret);
-static u32 tpm_read_word(const u32 *ptr) +static u32 tpm_read_word(struct tpm_tis_lpc_priv *priv, const u32 *ptr) { u32 ret = readl(ptr); debug(PREFIX "Read reg 0x%4.4x returns 0x%8.8x\n",
(u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, ret);
return ret; }(u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, ret);
-static void tpm_write_byte(u8 value, u8 *ptr) +static void tpm_write_byte(struct tpm_tis_lpc_priv *priv, u8 value, u8 *ptr) { debug(PREFIX "Write reg 0x%4.4x with 0x%2.2x\n",
(u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, value);
writeb(value, ptr); }(u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, value);
-static void tpm_write_word(u32 value, u32 *ptr) +static void tpm_write_word(struct tpm_tis_lpc_priv *priv, u32 value,
{ debug(PREFIX "Write reg 0x%4.4x with 0x%8.8x\n",u32 *ptr)
(u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, value);
writel(value, ptr); }(u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, value);
@@ -157,67 +121,51 @@ static void tpm_write_word(u32 value, u32 *ptr)
- @expected - value the field(s) are supposed to be set to
- Returns the register contents in case the expected value was found in the
- appropriate register bits, or TPM_TIMEOUT_ERR on timeout.
*/
- appropriate register bits, or -ETIMEDOUT on timeout.
-static u32 tis_wait_reg(u32 *reg, u8 mask, u8 expected) +static int tis_wait_reg(struct tpm_tis_lpc_priv *priv, u32 *reg, u8 mask,
u8 expected)
{ u32 time_us = MAX_DELAY_US;
while (time_us > 0) {
u32 value = tpm_read_word(reg);
if ((value & mask) == expected) return value; udelay(1); /* 1 us */ time_us--; }u32 value = tpm_read_word(priv, reg);
- return TPM_TIMEOUT_ERR;
return -ETIMEDOUT; }
/*
- Probe the TPM device and try determining its manufacturer/device name.
- Returns 0 on success (the device is found or was found during an earlier
- invocation) or TPM_DRIVER_ERR if the device is not found.
*/
- Returns 0 on success, -ve on error
-int tis_init(void) +static int tpm_tis_lpc_probe(struct udevice *dev) {
- u32 didvid = tpm_read_word(&lpc_tpm_dev[0].did_vid);
- int i;
- const char *device_name = "unknown";
- const char *vendor_name = device_name;
- u16 vid, did;
- if (vendor_dev_id)
return 0; /* Already probed. */
- if (!didvid || (didvid == 0xffffffff)) {
printf("%s: No TPM device found\n", __func__);
return TPM_DRIVER_ERR;
- }
- struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
- u32 vid, did;
- fdt_addr_t addr;
- u32 didvid;
- vendor_dev_id = didvid;
addr = dev_get_addr(dev);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
priv->regs = map_sysmem(addr, 0);
didvid = tpm_read_word(priv, &priv->regs[0].did_vid);
vid = didvid & 0xffff; did = (didvid >> 16) & 0xffff;
- for (i = 0; i < ARRAY_SIZE(vendor_names); i++) {
int j = 0;
u16 known_did;
if (vid == vendor_names[i].vendor_id)
vendor_name = vendor_names[i].vendor_name;
while ((known_did = vendor_names[i].dev_names[j].dev_id) != 0) {
if (known_did == did) {
device_name =
vendor_names[i].dev_names[j].dev_name;
break;
}
j++;
}
break;
- if (vid != 0x15d1 || did != 0xb) {
debug("Invalid vendor/device ID %04x/%04x\n", vid, did);
}return -ENOSYS;
- printf("Found TPM %s by %s\n", device_name, vendor_name);
- debug("Found TPM %s by %s\n", "SLB9635 TT 1.2", "Infineon");
- return 0; }
@@ -229,23 +177,25 @@ int tis_init(void)
- @data - address of the data to send, byte by byte
- @len - length of the data to send
- Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does
- not accept the entire command).
- Returns 0 on success, -ve on error (in case the device does not accept
*/
- the entire command).
-static u32 tis_senddata(const u8 * const data, u32 len) +static int tis_senddata(struct udevice *dev, const u8 *data, size_t len) {
- struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
- struct tpm_locality *regs = priv->regs; u32 offset = 0; u16 burst = 0; u32 max_cycles = 0; u8 locality = 0; u32 value;
- value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status,
- value = tis_wait_reg(priv, ®s[locality].tpm_status, TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY);
- if (value == TPM_TIMEOUT_ERR) {
- if (value == -ETIMEDOUT) { printf("%s:%d - failed to get 'command_ready' status\n", __FILE__, __LINE__);
return TPM_DRIVER_ERR;
} burst = burst_count(value);return value;
@@ -257,11 +207,11 @@ static u32 tis_senddata(const u8 * const data, u32 len) if (max_cycles++ == MAX_DELAY_US) { printf("%s:%d failed to feed %d bytes of %d\n", __FILE__, __LINE__, len - offset, len);
return TPM_DRIVER_ERR;
return -ETIMEDOUT; } udelay(1);
burst = burst_count(tpm_read_word(&lpc_tpm_dev
[locality].tpm_status));
burst = burst_count(tpm_read_word(priv,
®s[locality].tpm_status));
}
max_cycles = 0;
@@ -277,16 +227,16 @@ static u32 tis_senddata(const u8 * const data, u32 len) */ count = min((u32)burst, len - offset - 1); while (count--)
tpm_write_byte(data[offset++],
&lpc_tpm_dev[locality].data);
tpm_write_byte(priv, data[offset++],
®s[locality].data);
value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status,
value = tis_wait_reg(priv, ®s[locality].tpm_status, TIS_STS_VALID, TIS_STS_VALID);
if ((value == TPM_TIMEOUT_ERR) || !(value & TIS_STS_EXPECT)) {
if ((value == -ETIMEDOUT) || !(value & TIS_STS_EXPECT)) { printf("%s:%d TPM command feed overflow\n", __FILE__, __LINE__);
return TPM_DRIVER_ERR;
return value == -ETIMEDOUT ? value : -EIO;
}
burst = burst_count(value);
@@ -301,21 +251,21 @@ static u32 tis_senddata(const u8 * const data, u32 len) }
/* Send the last byte. */
- tpm_write_byte(data[offset++], &lpc_tpm_dev[locality].data);
- tpm_write_byte(priv, data[offset++], ®s[locality].data); /*
*/
- Verify that TPM does not expect any more data as part of this
- command.
- value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status,
- value = tis_wait_reg(priv, ®s[locality].tpm_status, TIS_STS_VALID, TIS_STS_VALID);
- if ((value == TPM_TIMEOUT_ERR) || (value & TIS_STS_EXPECT)) {
- if ((value == -ETIMEDOUT) || (value & TIS_STS_EXPECT)) { printf("%s:%d unexpected TPM status 0x%x\n", __FILE__, __LINE__, value);
return TPM_DRIVER_ERR;
return value == -ETIMEDOUT ? value : -EIO;
}
/* OK, sitting pretty, let's start the command execution. */
- tpm_write_word(TIS_STS_TPM_GO, &lpc_tpm_dev[locality].tpm_status);
- tpm_write_word(priv, TIS_STS_TPM_GO, ®s[locality].tpm_status); return 0; }
@@ -329,25 +279,27 @@ static u32 tis_senddata(const u8 * const data, u32 len)
- On success stores the number of received bytes to len and returns 0. On
- errors (misformatted TPM data or synchronization problems) returns
- TPM_DRIVER_ERR.
*/
- -ve value.
-static u32 tis_readresponse(u8 *buffer, u32 *len) +static int tis_readresponse(struct udevice *dev, u8 *buffer, size_t len) {
- struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
- struct tpm_locality *regs = priv->regs; u16 burst; u32 value; u32 offset = 0; u8 locality = 0; const u32 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
- u32 expected_count = *len;
u32 expected_count = len; int max_cycles = 0;
/* Wait for the TPM to process the command. */
- value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status,
- value = tis_wait_reg(priv, ®s[locality].tpm_status, has_data, has_data);
- if (value == TPM_TIMEOUT_ERR) {
- if (value == -ETIMEDOUT) { printf("%s:%d failed processing command\n", __FILE__, __LINE__);
return TPM_DRIVER_ERR;
return value;
}
do {
@@ -355,18 +307,17 @@ static u32 tis_readresponse(u8 *buffer, u32 *len) if (max_cycles++ == MAX_DELAY_US) { printf("%s:%d TPM stuck on read\n", __FILE__, __LINE__);
return TPM_DRIVER_ERR;
return -EIO; } udelay(1);
value = tpm_read_word(&lpc_tpm_dev
[locality].tpm_status);
value = tpm_read_word(priv, ®s[locality].tpm_status);
}
max_cycles = 0;
while (burst-- && (offset < expected_count)) {
buffer[offset++] = tpm_read_byte(&lpc_tpm_dev
[locality].data);
buffer[offset++] = tpm_read_byte(priv,
®s[locality].data); if (offset == 6) { /*
@@ -383,22 +334,22 @@ static u32 tis_readresponse(u8 *buffer, u32 *len) expected_count = be32_to_cpu(real_length);
if ((expected_count < offset) ||
(expected_count > *len)) {
(expected_count > len)) { printf("%s:%d bad response size %d\n", __FILE__, __LINE__, expected_count);
return TPM_DRIVER_ERR;
return -ENOSPC; } }
}
/* Wait for the next portion. */
value = tis_wait_reg(&lpc_tpm_dev[locality].tpm_status,
value = tis_wait_reg(priv, ®s[locality].tpm_status, TIS_STS_VALID, TIS_STS_VALID);
if (value == TPM_TIMEOUT_ERR) {
if (value == -ETIMEDOUT) { printf("%s:%d failed to read response\n", __FILE__, __LINE__);
return TPM_DRIVER_ERR;
return value;
}
if (offset == expected_count)
@@ -413,65 +364,90 @@ static u32 tis_readresponse(u8 *buffer, u32 *len) if (value & TIS_STS_DATA_AVAILABLE) { printf("%s:%d wrong receive status %x\n", __FILE__, __LINE__, value);
return TPM_DRIVER_ERR;
return -EBADMSG;
}
/* Tell the TPM that we are done. */
- tpm_write_word(TIS_STS_COMMAND_READY, &lpc_tpm_dev
[locality].tpm_status);
- *len = offset;
- return 0;
- tpm_write_word(priv, TIS_STS_COMMAND_READY,
®s[locality].tpm_status);
- return offset; }
-int tis_open(void) +static int tpm_tis_lpc_open(struct udevice *dev) {
struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
struct tpm_locality *regs = priv->regs; u8 locality = 0; /* we use locality zero for everything. */
int ret;
/* now request access to locality. */
- tpm_write_word(TIS_ACCESS_REQUEST_USE, &lpc_tpm_dev[locality].access);
tpm_write_word(priv, TIS_ACCESS_REQUEST_USE, ®s[locality].access);
/* did we get a lock? */
- if (tis_wait_reg(&lpc_tpm_dev[locality].access,
- ret = tis_wait_reg(priv, ®s[locality].access, TIS_ACCESS_ACTIVE_LOCALITY,
TIS_ACCESS_ACTIVE_LOCALITY) == TPM_TIMEOUT_ERR) {
TIS_ACCESS_ACTIVE_LOCALITY);
- if (ret == -ETIMEDOUT) { printf("%s:%d - failed to lock locality %d\n", __FILE__, __LINE__, locality);
return TPM_DRIVER_ERR;
}return ret;
- tpm_write_word(TIS_STS_COMMAND_READY,
&lpc_tpm_dev[locality].tpm_status);
- tpm_write_word(priv, TIS_STS_COMMAND_READY,
return 0; }®s[locality].tpm_status);
-int tis_close(void) +static int tpm_tis_lpc_close(struct udevice *dev) {
- struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
- struct tpm_locality *regs = priv->regs; u8 locality = 0;
- if (tpm_read_word(&lpc_tpm_dev[locality].access) &
- if (tpm_read_word(priv, ®s[locality].access) & TIS_ACCESS_ACTIVE_LOCALITY) {
tpm_write_word(TIS_ACCESS_ACTIVE_LOCALITY,
&lpc_tpm_dev[locality].access);
tpm_write_word(priv, TIS_ACCESS_ACTIVE_LOCALITY,
®s[locality].access);
if (tis_wait_reg(&lpc_tpm_dev[locality].access,
TIS_ACCESS_ACTIVE_LOCALITY, 0) ==
TPM_TIMEOUT_ERR) {
if (tis_wait_reg(priv, ®s[locality].access,
TIS_ACCESS_ACTIVE_LOCALITY, 0) == -ETIMEDOUT) { printf("%s:%d - failed to release locality %d\n", __FILE__, __LINE__, locality);
return TPM_DRIVER_ERR;
} } return 0; }return -ETIMEDOUT;
-int tis_sendrecv(const u8 *sendbuf, size_t send_size,
u8 *recvbuf, size_t *recv_len)
+static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size) {
- if (tis_senddata(sendbuf, send_size)) {
printf("%s:%d failed sending data to TPM\n",
__FILE__, __LINE__);
return TPM_DRIVER_ERR;
- }
- if (size < 50)
return -ENOSPC;
- return tis_readresponse(recvbuf, (u32 *)recv_len);
- return snprintf(buf, size, "1.2 TPM (vendor %s, chip %s)",
}"Infineon", "SLB9635 TT 1.2");
+static const struct tpm_ops tpm_tis_lpc_ops = {
- .open = tpm_tis_lpc_open,
- .close = tpm_tis_lpc_close,
- .get_desc = tpm_tis_get_desc,
- .send = tis_senddata,
- .recv = tis_readresponse,
+};
+static const struct udevice_id tpm_tis_lpc_ids[] = {
- { .compatible = "infineon,slb9635lpc" },
- { }
+};
+U_BOOT_DRIVER(tpm_tis_lpc) = {
- .name = "tpm_tis_lpc",
- .id = UCLASS_TPM,
- .of_match = tpm_tis_lpc_ids,
- .ops = &tpm_tis_lpc_ops,
- .probe = tpm_tis_lpc_probe,
- .priv_auto_alloc_size = sizeof(struct tpm_tis_lpc_priv),
+};

On 24 August 2015 at 14:23, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

Add a command to display basic information about a TPM such as the model and open/close state. This can be useful for debugging.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com ---
Changes in v2: - Use tpm_ prefix instead of tis_ for TPM functions
common/cmd_tpm.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index e9c6618..97501cc 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -456,6 +456,26 @@ static int get_tpm(struct udevice **devp)
return 0; } + +static int do_tpm_info(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct udevice *dev; + char buf[80]; + int rc; + + rc = get_tpm(&dev); + if (rc) + return rc; + rc = tpm_get_desc(dev, buf, sizeof(buf)); + if (rc < 0) { + printf("Couldn't get TPM info (%d)\n", rc); + return CMD_RET_FAILURE; + } + printf("%s\n", buf); + + return 0; +} #endif
static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, @@ -637,6 +657,9 @@ TPM_COMMAND_NO_ARG(tpm_end_oiap) U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")
static cmd_tbl_t tpm_commands[] = { +#ifdef CONFIG_DM_TPM + U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""), +#endif U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""), U_BOOT_CMD_MKENT(startup, 0, 1, @@ -707,6 +730,9 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, "cmd args...\n" " - Issue TPM command <cmd> with arguments <args...>.\n" "Admin Startup and State Commands:\n" +#ifdef CONFIG_DM_TPM +" info - Show information about the TPM\n" +#endif " init\n" " - Put TPM into a state where it waits for 'startup' command.\n" " startup mode\n"

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
Add a command to display basic information about a TPM such as the model and open/close state. This can be useful for debugging.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2:
- Use tpm_ prefix instead of tis_ for TPM functions
common/cmd_tpm.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
Applied to u-boot-dm.

Add a few new functions which will be used by the test command in a future patch.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add new patch with functions to access flags and permissions
include/tpm.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/tpm.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-)
diff --git a/include/tpm.h b/include/tpm.h index 445952b..086b672 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -49,6 +49,15 @@ enum tpm_nv_index { TPM_NV_INDEX_DIR = 0x10000001, };
+#define TPM_NV_PER_GLOBALLOCK (1U << 15) +#define TPM_NV_PER_PPWRITE (1U << 0) +#define TPM_NV_PER_READ_STCLEAR (1U << 31) +#define TPM_NV_PER_WRITE_STCLEAR (1U << 14) + +enum { + TPM_PUBEK_SIZE = 256, +}; + /** * TPM return codes as defined in the TCG Main specification * (TPM Main Part 2 Structures; Specification version 1.2) @@ -163,6 +172,30 @@ enum tpm_return_code { TPM_DEFEND_LOCK_RUNNING = TPM_BASE + TPM_NON_FATAL + 3, };
+struct tpm_permanent_flags { + __be16 tag; + u8 disable; + u8 ownership; + u8 deactivated; + u8 read_pubek; + u8 disable_owner_clear; + u8 allow_maintenance; + u8 physical_presence_lifetime_lock; + u8 physical_presence_hw_enable; + u8 physical_presence_cmd_enable; + u8 cekp_used; + u8 tpm_post; + u8 tpm_post_lock; + u8 fips; + u8 operator; + u8 enable_revoke_ek; + u8 nv_locked; + u8 read_srk_pub; + u8 tpm_established; + u8 maintenance_done; + u8 disable_full_da_logic_info; +} __packed; + #ifdef CONFIG_DM_TPM
/* Max buffer size supported by our tpm */ @@ -551,4 +584,20 @@ uint32_t tpm_load_key2_oiap(uint32_t parent_handle, uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth, void *pubkey, size_t *pubkey_len);
+/** + * Get the TPM permanent flags value + * + * @param pflags Place to put permanent flags + * @return return code of the operation + */ +uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags); + +/** + * Get the TPM permissions + * + * @param perm Returns permissions value + * @return return code of the operation + */ +uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm); + #endif /* __TPM_H */ diff --git a/lib/tpm.c b/lib/tpm.c index 19bf0b5..5d5f707 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -18,7 +18,6 @@ /* Useful constants */ enum { COMMAND_BUFFER_SIZE = 256, - TPM_PUBEK_SIZE = 256, TPM_REQUEST_HEADER_LENGTH = 10, TPM_RESPONSE_HEADER_LENGTH = 10, PCR_DIGEST_LENGTH = 20, @@ -610,6 +609,56 @@ uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap, return 0; }
+uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags) +{ + const uint8_t command[22] = { + 0x0, 0xc1, /* TPM_TAG */ + 0x0, 0x0, 0x0, 0x16, /* parameter size */ + 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */ + 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */ + 0x0, 0x0, 0x0, 0x4, /* subcap size */ + 0x0, 0x0, 0x1, 0x8, /* subcap value */ + }; + uint8_t response[COMMAND_BUFFER_SIZE]; + size_t response_length = sizeof(response); + uint32_t err; + + err = tpm_sendrecv_command(command, response, &response_length); + if (err) + return err; + memcpy(pflags, response + TPM_HEADER_SIZE, sizeof(*pflags)); + + return 0; +} + +uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm) +{ + const uint8_t command[22] = { + 0x0, 0xc1, /* TPM_TAG */ + 0x0, 0x0, 0x0, 0x16, /* parameter size */ + 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */ + 0x0, 0x0, 0x0, 0x11, + 0x0, 0x0, 0x0, 0x4, + }; + const size_t index_offset = 18; + const size_t perm_offset = 60; + uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + size_t response_length = sizeof(response); + uint32_t err; + + if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command), + index_offset, index)) + return TPM_LIB_ERROR; + err = tpm_sendrecv_command(buf, response, &response_length); + if (err) + return err; + if (unpack_byte_string(response, response_length, "d", + perm_offset, perm)) + return TPM_LIB_ERROR; + + return 0; +} + #ifdef CONFIG_TPM_AUTH_SESSIONS
/**

Acked-by: Christophe Ricardchristophe-h.ricard@st.com
On 23/08/2015 02:31, Simon Glass wrote:
Add a few new functions which will be used by the test command in a future patch.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
Add new patch with functions to access flags and permissions
include/tpm.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/tpm.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-)
diff --git a/include/tpm.h b/include/tpm.h index 445952b..086b672 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -49,6 +49,15 @@ enum tpm_nv_index { TPM_NV_INDEX_DIR = 0x10000001, };
+#define TPM_NV_PER_GLOBALLOCK (1U << 15) +#define TPM_NV_PER_PPWRITE (1U << 0) +#define TPM_NV_PER_READ_STCLEAR (1U << 31) +#define TPM_NV_PER_WRITE_STCLEAR (1U << 14)
+enum {
- TPM_PUBEK_SIZE = 256,
+};
- /**
- TPM return codes as defined in the TCG Main specification
- (TPM Main Part 2 Structures; Specification version 1.2)
@@ -163,6 +172,30 @@ enum tpm_return_code { TPM_DEFEND_LOCK_RUNNING = TPM_BASE + TPM_NON_FATAL + 3, };
+struct tpm_permanent_flags {
- __be16 tag;
- u8 disable;
- u8 ownership;
- u8 deactivated;
- u8 read_pubek;
- u8 disable_owner_clear;
- u8 allow_maintenance;
- u8 physical_presence_lifetime_lock;
- u8 physical_presence_hw_enable;
- u8 physical_presence_cmd_enable;
- u8 cekp_used;
- u8 tpm_post;
- u8 tpm_post_lock;
- u8 fips;
- u8 operator;
- u8 enable_revoke_ek;
- u8 nv_locked;
- u8 read_srk_pub;
- u8 tpm_established;
- u8 maintenance_done;
- u8 disable_full_da_logic_info;
+} __packed;
#ifdef CONFIG_DM_TPM
/* Max buffer size supported by our tpm */
@@ -551,4 +584,20 @@ uint32_t tpm_load_key2_oiap(uint32_t parent_handle, uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth, void *pubkey, size_t *pubkey_len);
+/**
- Get the TPM permanent flags value
- @param pflags Place to put permanent flags
- @return return code of the operation
- */
+uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags);
+/**
- Get the TPM permissions
- @param perm Returns permissions value
- @return return code of the operation
- */
+uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm);
- #endif /* __TPM_H */
diff --git a/lib/tpm.c b/lib/tpm.c index 19bf0b5..5d5f707 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -18,7 +18,6 @@ /* Useful constants */ enum { COMMAND_BUFFER_SIZE = 256,
- TPM_PUBEK_SIZE = 256, TPM_REQUEST_HEADER_LENGTH = 10, TPM_RESPONSE_HEADER_LENGTH = 10, PCR_DIGEST_LENGTH = 20,
@@ -610,6 +609,56 @@ uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap, return 0; }
+uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags) +{
- const uint8_t command[22] = {
0x0, 0xc1, /* TPM_TAG */
0x0, 0x0, 0x0, 0x16, /* parameter size */
0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
0x0, 0x0, 0x0, 0x4, /* subcap size */
0x0, 0x0, 0x1, 0x8, /* subcap value */
- };
- uint8_t response[COMMAND_BUFFER_SIZE];
- size_t response_length = sizeof(response);
- uint32_t err;
- err = tpm_sendrecv_command(command, response, &response_length);
- if (err)
return err;
- memcpy(pflags, response + TPM_HEADER_SIZE, sizeof(*pflags));
- return 0;
+}
+uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm) +{
- const uint8_t command[22] = {
0x0, 0xc1, /* TPM_TAG */
0x0, 0x0, 0x0, 0x16, /* parameter size */
0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
0x0, 0x0, 0x0, 0x11,
0x0, 0x0, 0x0, 0x4,
- };
- const size_t index_offset = 18;
- const size_t perm_offset = 60;
- uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
- size_t response_length = sizeof(response);
- uint32_t err;
- if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
index_offset, index))
return TPM_LIB_ERROR;
- err = tpm_sendrecv_command(buf, response, &response_length);
- if (err)
return err;
- if (unpack_byte_string(response, response_length, "d",
perm_offset, perm))
return TPM_LIB_ERROR;
- return 0;
+}
#ifdef CONFIG_TPM_AUTH_SESSIONS
/**

On 24 August 2015 at 14:23, Christophe Ricard christophe.ricard@gmail.com wrote:
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

These tests come from Chrome OS code. They are not particularly tidy but can be useful for checking that the TPM is behaving correctly. Some knowledge of TPM operation is required to use these.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add new patch with a 'tpmtest' command
common/Kconfig | 10 + common/Makefile | 1 + common/cmd_tpm_test.c | 565 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 576 insertions(+) create mode 100644 common/cmd_tpm_test.c
diff --git a/common/Kconfig b/common/Kconfig index bacc4e0..2c42b8e 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -635,6 +635,16 @@ config CMD_TPM command requires a suitable TPM on your board and the correct driver must be enabled.
+config CMD_TPM_TEST + bool "Enable the 'tpm test' command" + depends on CMD_TPM + help + This provides a a series of tests to confirm that the TPM is working + correctly. The tests cover initialisation, non-volatile RAM, extend, + global lock and checking that timing is within expectations. The + tests pass correctly on Infineon TPMs but may need to be adjusted + for other devices. + endmenu
endmenu diff --git a/common/Makefile b/common/Makefile index dc82433..f4ba878 100644 --- a/common/Makefile +++ b/common/Makefile @@ -169,6 +169,7 @@ obj-$(CONFIG_CMD_TIME) += cmd_time.o obj-$(CONFIG_CMD_TRACE) += cmd_trace.o obj-$(CONFIG_SYS_HUSH_PARSER) += cmd_test.o obj-$(CONFIG_CMD_TPM) += cmd_tpm.o +obj-$(CONFIG_CMD_TPM_TEST) += cmd_tpm_test.o obj-$(CONFIG_CMD_TSI148) += cmd_tsi148.o obj-$(CONFIG_CMD_UBI) += cmd_ubi.o obj-$(CONFIG_CMD_UBIFS) += cmd_ubifs.o diff --git a/common/cmd_tpm_test.c b/common/cmd_tpm_test.c new file mode 100644 index 0000000..2bef5a1 --- /dev/null +++ b/common/cmd_tpm_test.c @@ -0,0 +1,565 @@ +/* + * Copyright (c) 2015 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <environment.h> +#include <tpm.h> + +/* Prints error and returns on failure */ +#define TPM_CHECK(tpm_command) do { \ + uint32_t result; \ + \ + result = (tpm_command); \ + if (result != TPM_SUCCESS) { \ + printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \ + __LINE__, result); \ + return result; \ + } \ +} while (0) + +#define INDEX0 0xda70 +#define INDEX1 0xda71 +#define INDEX2 0xda72 +#define INDEX3 0xda73 +#define INDEX_INITIALISED 0xda80 +#define PHYS_PRESENCE 4 +#define PRESENCE 8 + +static uint32_t TlclStartupIfNeeded(void) +{ + uint32_t result = tpm_startup(TPM_ST_CLEAR); + + return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result; +} + +static int test_timer(void) +{ + printf("get_timer(0) = %lu\n", get_timer(0)); + return 0; +} + +static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated, + uint8_t *nvlocked) +{ + struct tpm_permanent_flags pflags; + uint32_t result; + + result = tpm_get_permanent_flags(&pflags); + if (result) + return result; + if (disable) + *disable = pflags.disable; + if (deactivated) + *deactivated = pflags.deactivated; + if (nvlocked) + *nvlocked = pflags.nv_locked; + debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n", + pflags.disable, pflags.deactivated, pflags.nv_locked); + + return 0; +} + +static uint32_t tpm_set_global_lock(void) +{ + uint32_t x; + + debug("TPM: Set global lock\n"); + return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0); +} + +static uint32_t tpm_nv_write_value_lock(uint32_t index) +{ + debug("TPM: Write lock 0x%x\n", index); + + return tpm_nv_write_value(index, NULL, 0); +} + +static uint32_t tpm_nv_set_locked(void) +{ + debug("TPM: Set NV locked\n"); + + return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0); +} + +static int tpm_is_owned(void) +{ + uint8_t response[TPM_PUBEK_SIZE]; + uint32_t result; + + result = tpm_read_pubek(response, sizeof(response)); + + return result != TPM_SUCCESS; +} + +static int test_early_extend(void) +{ + uint8_t value_in[20]; + uint8_t value_out[20]; + + printf("Testing earlyextend ..."); + tpm_init(); + TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); + TPM_CHECK(tpm_continue_self_test()); + TPM_CHECK(tpm_extend(1, value_in, value_out)); + printf("done\n"); + return 0; +} + +static int test_early_nvram(void) +{ + uint32_t x; + + printf("Testing earlynvram ..."); + tpm_init(); + TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); + TPM_CHECK(tpm_continue_self_test()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); + printf("done\n"); + return 0; +} + +static int test_early_nvram2(void) +{ + uint32_t x; + + printf("Testing earlynvram2 ..."); + tpm_init(); + TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); + TPM_CHECK(tpm_continue_self_test()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x))); + printf("done\n"); + return 0; +} + +static int test_enable(void) +{ + uint8_t disable = 0, deactivated = 0; + + printf("Testing enable ...\n"); + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_self_test_full()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); + printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); + TPM_CHECK(tpm_physical_enable()); + TPM_CHECK(tpm_physical_set_deactivated(0)); + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); + printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); + if (disable == 1 || deactivated == 1) + printf("\tfailed to enable or activate\n"); + printf("\tdone\n"); + return 0; +} + +#define reboot() do { \ + printf("\trebooting...\n"); \ + reset_cpu(0); \ +} while (0) + +static int test_fast_enable(void) +{ + uint8_t disable = 0, deactivated = 0; + int i; + + printf("Testing fastenable ...\n"); + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_self_test_full()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); + printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); + for (i = 0; i < 2; i++) { + TPM_CHECK(tpm_force_clear()); + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); + printf("\tdisable is %d, deactivated is %d\n", disable, + deactivated); + assert(disable == 1 && deactivated == 1); + TPM_CHECK(tpm_physical_enable()); + TPM_CHECK(tpm_physical_set_deactivated(0)); + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); + printf("\tdisable is %d, deactivated is %d\n", disable, + deactivated); + assert(disable == 0 && deactivated == 0); + } + printf("\tdone\n"); + return 0; +} + +static int test_global_lock(void) +{ + uint32_t zero = 0; + uint32_t result; + uint32_t x; + + printf("Testing globallock ...\n"); + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_self_test_full()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); + TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero, + sizeof(uint32_t))); + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); + TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero, + sizeof(uint32_t))); + TPM_CHECK(tpm_set_global_lock()); + /* Verifies that write to index0 fails */ + x = 1; + result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)); + assert(result == TPM_AREA_LOCKED); + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); + assert(x == 0); + /* Verifies that write to index1 is still possible */ + x = 2; + TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x))); + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); + assert(x == 2); + /* Turns off PP */ + tpm_tsc_physical_presence(PHYS_PRESENCE); + /* Verifies that write to index1 fails */ + x = 3; + result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)); + assert(result == TPM_BAD_PRESENCE); + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); + assert(x == 2); + printf("\tdone\n"); + return 0; +} + +static int test_lock(void) +{ + printf("Testing lock ...\n"); + tpm_init(); + tpm_startup(TPM_ST_CLEAR); + tpm_self_test_full(); + tpm_tsc_physical_presence(PRESENCE); + tpm_nv_write_value_lock(INDEX0); + printf("\tLocked 0x%x\n", INDEX0); + printf("\tdone\n"); + return 0; +} + +static void initialise_spaces(void) +{ + uint32_t zero = 0; + uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE; + + printf("\tInitialising spaces\n"); + tpm_nv_set_locked(); /* useful only the first time */ + tpm_nv_define_space(INDEX0, perm, 4); + tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4); + tpm_nv_define_space(INDEX1, perm, 4); + tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4); + tpm_nv_define_space(INDEX2, perm, 4); + tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4); + tpm_nv_define_space(INDEX3, perm, 4); + tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4); + perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR | + TPM_NV_PER_PPWRITE; + tpm_nv_define_space(INDEX_INITIALISED, perm, 1); +} + +static int test_readonly(void) +{ + uint8_t c; + uint32_t index_0, index_1, index_2, index_3; + int read0, read1, read2, read3; + + printf("Testing readonly ...\n"); + tpm_init(); + tpm_startup(TPM_ST_CLEAR); + tpm_self_test_full(); + tpm_tsc_physical_presence(PRESENCE); + /* + * Checks if initialisation has completed by trying to read-lock a + * space that's created at the end of initialisation + */ + if (tpm_nv_read_value(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) { + /* The initialisation did not complete */ + initialise_spaces(); + } + + /* Checks if spaces are OK or messed up */ + read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)); + read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1)); + read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2)); + read3 = tpm_nv_read_value(INDEX3, (uint8_t *)&index_3, sizeof(index_3)); + if (read0 || read1 || read2 || read3) { + printf("Invalid contents\n"); + return 0; + } + + /* + * Writes space, and locks it. Then attempts to write again. + * I really wish I could use the imperative. + */ + index_0 += 1; + if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0) != + TPM_SUCCESS)) { + error("\tcould not write index 0\n"); + } + tpm_nv_write_value_lock(INDEX0); + if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) == + TPM_SUCCESS) + error("\tindex 0 is not locked\n"); + + printf("\tdone\n"); + return 0; +} + +static int test_redefine_unowned(void) +{ + uint32_t perm; + uint32_t result; + uint32_t x; + + printf("Testing redefine_unowned ..."); + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_self_test_full()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + assert(!tpm_is_owned()); + + /* Ensures spaces exist. */ + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); + + /* Redefines spaces a couple of times. */ + perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK; + TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t))); + TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t))); + perm = TPM_NV_PER_PPWRITE; + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t))); + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t))); + + /* Sets the global lock */ + tpm_set_global_lock(); + + /* Verifies that index0 cannot be redefined */ + result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)); + assert(result == TPM_AREA_LOCKED); + + /* Checks that index1 can */ + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t))); + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t))); + + /* Turns off PP */ + tpm_tsc_physical_presence(PHYS_PRESENCE); + + /* Verifies that neither index0 nor index1 can be redefined */ + result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)); + assert(result == TPM_BAD_PRESENCE); + result = tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)); + assert(result == TPM_BAD_PRESENCE); + + printf("done\n"); + return 0; +} + +#define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK) +#define PERMPP TPM_NV_PER_PPWRITE + +static int test_space_perm(void) +{ + uint32_t perm; + + printf("Testing spaceperm ..."); + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_continue_self_test()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_get_permissions(INDEX0, &perm)); + assert((perm & PERMPPGL) == PERMPPGL); + TPM_CHECK(tpm_get_permissions(INDEX1, &perm)); + assert((perm & PERMPP) == PERMPP); + printf("done\n"); + return 0; +} + +static int test_startup(void) +{ + uint32_t result; + printf("Testing startup ...\n"); + + tpm_init(); + result = tpm_startup(TPM_ST_CLEAR); + if (result != 0 && result != TPM_INVALID_POSTINIT) + printf("\ttpm startup failed with 0x%x\n", result); + result = tpm_get_flags(NULL, NULL, NULL); + if (result != 0) + printf("\ttpm getflags failed with 0x%x\n", result); + printf("\texecuting SelfTestFull\n"); + tpm_self_test_full(); + result = tpm_get_flags(NULL, NULL, NULL); + if (result != 0) + printf("\ttpm getflags failed with 0x%x\n", result); + printf("\tdone\n"); + return 0; +} + +/* + * Runs [op] and ensures it returns success and doesn't run longer than + * [time_limit] in milliseconds. + */ +#define TTPM_CHECK(op, time_limit) do { \ + ulong start, time; \ + uint32_t __result; \ + \ + start = get_timer(0); \ + __result = op; \ + if (__result != TPM_SUCCESS) { \ + printf("\t" #op ": error 0x%x\n", __result); \ + return -1; \ + } \ + time = get_timer(start); \ + printf("\t" #op ": %lu ms\n", time); \ + if (time > (ulong)time_limit) { \ + printf("\t" #op " exceeded " #time_limit " ms\n"); \ + } \ +} while (0) + + +static int test_timing(void) +{ + uint32_t x; + uint8_t in[20], out[20]; + + printf("Testing timing ..."); + tpm_init(); + TTPM_CHECK(TlclStartupIfNeeded(), 50); + TTPM_CHECK(tpm_continue_self_test(), 100); + TTPM_CHECK(tpm_self_test_full(), 1000); + TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100); + TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100); + TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100); + TTPM_CHECK(tpm_extend(0, in, out), 200); + TTPM_CHECK(tpm_set_global_lock(), 50); + TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100); + printf("done\n"); + return 0; +} + +#define TPM_MAX_NV_WRITES_NOOWNER 64 + +static int test_write_limit(void) +{ + printf("Testing writelimit ...\n"); + int i; + uint32_t result; + + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_self_test_full()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_force_clear()); + TPM_CHECK(tpm_physical_enable()); + TPM_CHECK(tpm_physical_set_deactivated(0)); + + for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) { + printf("\twriting %d\n", i); + result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)); + switch (result) { + case TPM_SUCCESS: + break; + case TPM_MAXNVWRITES: + assert(i >= TPM_MAX_NV_WRITES_NOOWNER); + default: + error("\tunexpected error code %d (0x%x)\n", + result, result); + } + } + + /* Reset write count */ + TPM_CHECK(tpm_force_clear()); + TPM_CHECK(tpm_physical_enable()); + TPM_CHECK(tpm_physical_set_deactivated(0)); + + /* Try writing again. */ + TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i))); + printf("\tdone\n"); + return 0; +} + +#define VOIDTEST(XFUNC) \ + int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \ + char * const argv[]) \ + { \ + return test_##XFUNC(); \ + } + +#define VOIDENT(XNAME) \ + U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""), + +VOIDTEST(early_extend) +VOIDTEST(early_nvram) +VOIDTEST(early_nvram2) +VOIDTEST(enable) +VOIDTEST(fast_enable) +VOIDTEST(global_lock) +VOIDTEST(lock) +VOIDTEST(readonly) +VOIDTEST(redefine_unowned) +VOIDTEST(space_perm) +VOIDTEST(startup) +VOIDTEST(timing) +VOIDTEST(write_limit) +VOIDTEST(timer) + +static cmd_tbl_t cmd_cros_tpm_sub[] = { + VOIDENT(early_extend) + VOIDENT(early_nvram) + VOIDENT(early_nvram2) + VOIDENT(enable) + VOIDENT(fast_enable) + VOIDENT(global_lock) + VOIDENT(lock) + VOIDENT(readonly) + VOIDENT(redefine_unowned) + VOIDENT(space_perm) + VOIDENT(startup) + VOIDENT(timing) + VOIDENT(write_limit) + VOIDENT(timer) +}; + +static int do_tpmtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *c; + + printf("argc = %d, argv = ", argc); + do { + int i = 0; + + for (i = 0; i < argc; i++) + printf(" %s", argv[i]); + printf("\n------\n"); + } while (0); + argc--; + argv++; + c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub, + ARRAY_SIZE(cmd_cros_tpm_sub)); + return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp); +} + +U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests", + "\n\tearly_extend\n" + "\tearly_nvram\n" + "\tearly_nvram2\n" + "\tenable\n" + "\tfast_enable\n" + "\tglobal_lock\n" + "\tlock\n" + "\treadonly\n" + "\tredefine_unowned\n" + "\tspace_perm\n" + "\tstartup\n" + "\ttiming\n" + "\twrite_limit\n"); +

Hi Simon,
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
I will try those tpm tests.
Best Regards Christophe
On 23/08/2015 02:31, Simon Glass wrote:
These tests come from Chrome OS code. They are not particularly tidy but can be useful for checking that the TPM is behaving correctly. Some knowledge of TPM operation is required to use these.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
Add new patch with a 'tpmtest' command
common/Kconfig | 10 + common/Makefile | 1 + common/cmd_tpm_test.c | 565 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 576 insertions(+) create mode 100644 common/cmd_tpm_test.c
diff --git a/common/Kconfig b/common/Kconfig index bacc4e0..2c42b8e 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -635,6 +635,16 @@ config CMD_TPM command requires a suitable TPM on your board and the correct driver must be enabled.
+config CMD_TPM_TEST
bool "Enable the 'tpm test' command"
depends on CMD_TPM
help
This provides a a series of tests to confirm that the TPM is working
correctly. The tests cover initialisation, non-volatile RAM, extend,
global lock and checking that timing is within expectations. The
tests pass correctly on Infineon TPMs but may need to be adjusted
for other devices.
endmenu
endmenu
diff --git a/common/Makefile b/common/Makefile index dc82433..f4ba878 100644 --- a/common/Makefile +++ b/common/Makefile @@ -169,6 +169,7 @@ obj-$(CONFIG_CMD_TIME) += cmd_time.o obj-$(CONFIG_CMD_TRACE) += cmd_trace.o obj-$(CONFIG_SYS_HUSH_PARSER) += cmd_test.o obj-$(CONFIG_CMD_TPM) += cmd_tpm.o +obj-$(CONFIG_CMD_TPM_TEST) += cmd_tpm_test.o obj-$(CONFIG_CMD_TSI148) += cmd_tsi148.o obj-$(CONFIG_CMD_UBI) += cmd_ubi.o obj-$(CONFIG_CMD_UBIFS) += cmd_ubifs.o diff --git a/common/cmd_tpm_test.c b/common/cmd_tpm_test.c new file mode 100644 index 0000000..2bef5a1 --- /dev/null +++ b/common/cmd_tpm_test.c @@ -0,0 +1,565 @@ +/*
- Copyright (c) 2015 Google, Inc
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <command.h> +#include <environment.h> +#include <tpm.h>
+/* Prints error and returns on failure */ +#define TPM_CHECK(tpm_command) do { \
- uint32_t result; \
- \
- result = (tpm_command); \
- if (result != TPM_SUCCESS) { \
printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \
__LINE__, result); \
return result; \
- } \
+} while (0)
+#define INDEX0 0xda70 +#define INDEX1 0xda71 +#define INDEX2 0xda72 +#define INDEX3 0xda73 +#define INDEX_INITIALISED 0xda80 +#define PHYS_PRESENCE 4 +#define PRESENCE 8
+static uint32_t TlclStartupIfNeeded(void) +{
- uint32_t result = tpm_startup(TPM_ST_CLEAR);
- return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result;
+}
+static int test_timer(void) +{
- printf("get_timer(0) = %lu\n", get_timer(0));
- return 0;
+}
+static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated,
uint8_t *nvlocked)
+{
- struct tpm_permanent_flags pflags;
- uint32_t result;
- result = tpm_get_permanent_flags(&pflags);
- if (result)
return result;
- if (disable)
*disable = pflags.disable;
- if (deactivated)
*deactivated = pflags.deactivated;
- if (nvlocked)
*nvlocked = pflags.nv_locked;
- debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n",
pflags.disable, pflags.deactivated, pflags.nv_locked);
- return 0;
+}
+static uint32_t tpm_set_global_lock(void) +{
- uint32_t x;
- debug("TPM: Set global lock\n");
- return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0);
+}
+static uint32_t tpm_nv_write_value_lock(uint32_t index) +{
- debug("TPM: Write lock 0x%x\n", index);
- return tpm_nv_write_value(index, NULL, 0);
+}
+static uint32_t tpm_nv_set_locked(void) +{
- debug("TPM: Set NV locked\n");
- return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0);
+}
+static int tpm_is_owned(void) +{
- uint8_t response[TPM_PUBEK_SIZE];
- uint32_t result;
- result = tpm_read_pubek(response, sizeof(response));
- return result != TPM_SUCCESS;
+}
+static int test_early_extend(void) +{
- uint8_t value_in[20];
- uint8_t value_out[20];
- printf("Testing earlyextend ...");
- tpm_init();
- TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
- TPM_CHECK(tpm_continue_self_test());
- TPM_CHECK(tpm_extend(1, value_in, value_out));
- printf("done\n");
- return 0;
+}
+static int test_early_nvram(void) +{
- uint32_t x;
- printf("Testing earlynvram ...");
- tpm_init();
- TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
- TPM_CHECK(tpm_continue_self_test());
- TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
- TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
- printf("done\n");
- return 0;
+}
+static int test_early_nvram2(void) +{
- uint32_t x;
- printf("Testing earlynvram2 ...");
- tpm_init();
- TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
- TPM_CHECK(tpm_continue_self_test());
- TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
- TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)));
- printf("done\n");
- return 0;
+}
+static int test_enable(void) +{
- uint8_t disable = 0, deactivated = 0;
- printf("Testing enable ...\n");
- tpm_init();
- TPM_CHECK(TlclStartupIfNeeded());
- TPM_CHECK(tpm_self_test_full());
- TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
- TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
- printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
- TPM_CHECK(tpm_physical_enable());
- TPM_CHECK(tpm_physical_set_deactivated(0));
- TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
- printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
- if (disable == 1 || deactivated == 1)
printf("\tfailed to enable or activate\n");
- printf("\tdone\n");
- return 0;
+}
+#define reboot() do { \
- printf("\trebooting...\n"); \
- reset_cpu(0); \
+} while (0)
+static int test_fast_enable(void) +{
- uint8_t disable = 0, deactivated = 0;
- int i;
- printf("Testing fastenable ...\n");
- tpm_init();
- TPM_CHECK(TlclStartupIfNeeded());
- TPM_CHECK(tpm_self_test_full());
- TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
- TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
- printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
- for (i = 0; i < 2; i++) {
TPM_CHECK(tpm_force_clear());
TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
printf("\tdisable is %d, deactivated is %d\n", disable,
deactivated);
assert(disable == 1 && deactivated == 1);
TPM_CHECK(tpm_physical_enable());
TPM_CHECK(tpm_physical_set_deactivated(0));
TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
printf("\tdisable is %d, deactivated is %d\n", disable,
deactivated);
assert(disable == 0 && deactivated == 0);
- }
- printf("\tdone\n");
- return 0;
+}
+static int test_global_lock(void) +{
- uint32_t zero = 0;
- uint32_t result;
- uint32_t x;
- printf("Testing globallock ...\n");
- tpm_init();
- TPM_CHECK(TlclStartupIfNeeded());
- TPM_CHECK(tpm_self_test_full());
- TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
- TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
- TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero,
sizeof(uint32_t)));
- TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
- TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero,
sizeof(uint32_t)));
- TPM_CHECK(tpm_set_global_lock());
- /* Verifies that write to index0 fails */
- x = 1;
- result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x));
- assert(result == TPM_AREA_LOCKED);
- TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
- assert(x == 0);
- /* Verifies that write to index1 is still possible */
- x = 2;
- TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)));
- TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
- assert(x == 2);
- /* Turns off PP */
- tpm_tsc_physical_presence(PHYS_PRESENCE);
- /* Verifies that write to index1 fails */
- x = 3;
- result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x));
- assert(result == TPM_BAD_PRESENCE);
- TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
- assert(x == 2);
- printf("\tdone\n");
- return 0;
+}
+static int test_lock(void) +{
- printf("Testing lock ...\n");
- tpm_init();
- tpm_startup(TPM_ST_CLEAR);
- tpm_self_test_full();
- tpm_tsc_physical_presence(PRESENCE);
- tpm_nv_write_value_lock(INDEX0);
- printf("\tLocked 0x%x\n", INDEX0);
- printf("\tdone\n");
- return 0;
+}
+static void initialise_spaces(void) +{
- uint32_t zero = 0;
- uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
- printf("\tInitialising spaces\n");
- tpm_nv_set_locked(); /* useful only the first time */
- tpm_nv_define_space(INDEX0, perm, 4);
- tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4);
- tpm_nv_define_space(INDEX1, perm, 4);
- tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4);
- tpm_nv_define_space(INDEX2, perm, 4);
- tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4);
- tpm_nv_define_space(INDEX3, perm, 4);
- tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4);
- perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
TPM_NV_PER_PPWRITE;
- tpm_nv_define_space(INDEX_INITIALISED, perm, 1);
+}
+static int test_readonly(void) +{
- uint8_t c;
- uint32_t index_0, index_1, index_2, index_3;
- int read0, read1, read2, read3;
- printf("Testing readonly ...\n");
- tpm_init();
- tpm_startup(TPM_ST_CLEAR);
- tpm_self_test_full();
- tpm_tsc_physical_presence(PRESENCE);
- /*
* Checks if initialisation has completed by trying to read-lock a
* space that's created at the end of initialisation
*/
- if (tpm_nv_read_value(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
/* The initialisation did not complete */
initialise_spaces();
- }
- /* Checks if spaces are OK or messed up */
- read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0));
- read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1));
- read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2));
- read3 = tpm_nv_read_value(INDEX3, (uint8_t *)&index_3, sizeof(index_3));
- if (read0 || read1 || read2 || read3) {
printf("Invalid contents\n");
return 0;
- }
- /*
* Writes space, and locks it. Then attempts to write again.
* I really wish I could use the imperative.
*/
- index_0 += 1;
- if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0) !=
TPM_SUCCESS)) {
error("\tcould not write index 0\n");
- }
- tpm_nv_write_value_lock(INDEX0);
- if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) ==
TPM_SUCCESS)
error("\tindex 0 is not locked\n");
- printf("\tdone\n");
- return 0;
+}
+static int test_redefine_unowned(void) +{
- uint32_t perm;
- uint32_t result;
- uint32_t x;
- printf("Testing redefine_unowned ...");
- tpm_init();
- TPM_CHECK(TlclStartupIfNeeded());
- TPM_CHECK(tpm_self_test_full());
- TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
- assert(!tpm_is_owned());
- /* Ensures spaces exist. */
- TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
- TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
- /* Redefines spaces a couple of times. */
- perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
- TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t)));
- TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)));
- perm = TPM_NV_PER_PPWRITE;
- TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
- TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
- /* Sets the global lock */
- tpm_set_global_lock();
- /* Verifies that index0 cannot be redefined */
- result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
- assert(result == TPM_AREA_LOCKED);
- /* Checks that index1 can */
- TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
- TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
- /* Turns off PP */
- tpm_tsc_physical_presence(PHYS_PRESENCE);
- /* Verifies that neither index0 nor index1 can be redefined */
- result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
- assert(result == TPM_BAD_PRESENCE);
- result = tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t));
- assert(result == TPM_BAD_PRESENCE);
- printf("done\n");
- return 0;
+}
+#define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK) +#define PERMPP TPM_NV_PER_PPWRITE
+static int test_space_perm(void) +{
- uint32_t perm;
- printf("Testing spaceperm ...");
- tpm_init();
- TPM_CHECK(TlclStartupIfNeeded());
- TPM_CHECK(tpm_continue_self_test());
- TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
- TPM_CHECK(tpm_get_permissions(INDEX0, &perm));
- assert((perm & PERMPPGL) == PERMPPGL);
- TPM_CHECK(tpm_get_permissions(INDEX1, &perm));
- assert((perm & PERMPP) == PERMPP);
- printf("done\n");
- return 0;
+}
+static int test_startup(void) +{
- uint32_t result;
- printf("Testing startup ...\n");
- tpm_init();
- result = tpm_startup(TPM_ST_CLEAR);
- if (result != 0 && result != TPM_INVALID_POSTINIT)
printf("\ttpm startup failed with 0x%x\n", result);
- result = tpm_get_flags(NULL, NULL, NULL);
- if (result != 0)
printf("\ttpm getflags failed with 0x%x\n", result);
- printf("\texecuting SelfTestFull\n");
- tpm_self_test_full();
- result = tpm_get_flags(NULL, NULL, NULL);
- if (result != 0)
printf("\ttpm getflags failed with 0x%x\n", result);
- printf("\tdone\n");
- return 0;
+}
+/*
- Runs [op] and ensures it returns success and doesn't run longer than
- [time_limit] in milliseconds.
- */
+#define TTPM_CHECK(op, time_limit) do { \
- ulong start, time; \
- uint32_t __result; \
- \
- start = get_timer(0); \
- __result = op; \
- if (__result != TPM_SUCCESS) { \
printf("\t" #op ": error 0x%x\n", __result); \
return -1; \
- } \
- time = get_timer(start); \
- printf("\t" #op ": %lu ms\n", time); \
- if (time > (ulong)time_limit) { \
printf("\t" #op " exceeded " #time_limit " ms\n"); \
- } \
+} while (0)
+static int test_timing(void) +{
- uint32_t x;
- uint8_t in[20], out[20];
- printf("Testing timing ...");
- tpm_init();
- TTPM_CHECK(TlclStartupIfNeeded(), 50);
- TTPM_CHECK(tpm_continue_self_test(), 100);
- TTPM_CHECK(tpm_self_test_full(), 1000);
- TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100);
- TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
- TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
- TTPM_CHECK(tpm_extend(0, in, out), 200);
- TTPM_CHECK(tpm_set_global_lock(), 50);
- TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100);
- printf("done\n");
- return 0;
+}
+#define TPM_MAX_NV_WRITES_NOOWNER 64
+static int test_write_limit(void) +{
- printf("Testing writelimit ...\n");
- int i;
- uint32_t result;
- tpm_init();
- TPM_CHECK(TlclStartupIfNeeded());
- TPM_CHECK(tpm_self_test_full());
- TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
- TPM_CHECK(tpm_force_clear());
- TPM_CHECK(tpm_physical_enable());
- TPM_CHECK(tpm_physical_set_deactivated(0));
- for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
printf("\twriting %d\n", i);
result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i));
switch (result) {
case TPM_SUCCESS:
break;
case TPM_MAXNVWRITES:
assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
default:
error("\tunexpected error code %d (0x%x)\n",
result, result);
}
- }
- /* Reset write count */
- TPM_CHECK(tpm_force_clear());
- TPM_CHECK(tpm_physical_enable());
- TPM_CHECK(tpm_physical_set_deactivated(0));
- /* Try writing again. */
- TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)));
- printf("\tdone\n");
- return 0;
+}
+#define VOIDTEST(XFUNC) \
- int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \
- char * const argv[]) \
- { \
return test_##XFUNC(); \
- }
+#define VOIDENT(XNAME) \
- U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""),
+VOIDTEST(early_extend) +VOIDTEST(early_nvram) +VOIDTEST(early_nvram2) +VOIDTEST(enable) +VOIDTEST(fast_enable) +VOIDTEST(global_lock) +VOIDTEST(lock) +VOIDTEST(readonly) +VOIDTEST(redefine_unowned) +VOIDTEST(space_perm) +VOIDTEST(startup) +VOIDTEST(timing) +VOIDTEST(write_limit) +VOIDTEST(timer)
+static cmd_tbl_t cmd_cros_tpm_sub[] = {
- VOIDENT(early_extend)
- VOIDENT(early_nvram)
- VOIDENT(early_nvram2)
- VOIDENT(enable)
- VOIDENT(fast_enable)
- VOIDENT(global_lock)
- VOIDENT(lock)
- VOIDENT(readonly)
- VOIDENT(redefine_unowned)
- VOIDENT(space_perm)
- VOIDENT(startup)
- VOIDENT(timing)
- VOIDENT(write_limit)
- VOIDENT(timer)
+};
+static int do_tpmtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{
- cmd_tbl_t *c;
- printf("argc = %d, argv = ", argc);
- do {
int i = 0;
for (i = 0; i < argc; i++)
printf(" %s", argv[i]);
printf("\n------\n");
} while (0);
- argc--;
- argv++;
- c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
ARRAY_SIZE(cmd_cros_tpm_sub));
- return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp);
+}
+U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests",
- "\n\tearly_extend\n"
- "\tearly_nvram\n"
- "\tearly_nvram2\n"
- "\tenable\n"
- "\tfast_enable\n"
- "\tglobal_lock\n"
- "\tlock\n"
- "\treadonly\n"
- "\tredefine_unowned\n"
- "\tspace_perm\n"
- "\tstartup\n"
- "\ttiming\n"
- "\twrite_limit\n");

On 24 August 2015 at 14:23, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
I will try those tpm tests.
Applied to u-boot-dm.

This command provides a few useful tests so enable it for common boards.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
configs/chromebook_link_defconfig | 1 + configs/chromebox_panther_defconfig | 1 + configs/coreboot-x86_defconfig | 1 + configs/peach-pi_defconfig | 1 + configs/peach-pit_defconfig | 1 + configs/sandbox_defconfig | 1 + configs/snow_defconfig | 1 + configs/spring_defconfig | 1 + 8 files changed, 8 insertions(+)
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index 85752e4..9855736 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -12,6 +12,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index a6bafe3..c75b20d 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -12,6 +12,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y diff --git a/configs/coreboot-x86_defconfig b/configs/coreboot-x86_defconfig index fda2b7e..ebaf86b 100644 --- a/configs/coreboot-x86_defconfig +++ b/configs/coreboot-x86_defconfig @@ -10,6 +10,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y diff --git a/configs/peach-pi_defconfig b/configs/peach-pi_defconfig index 6416f16..56a5185 100644 --- a/configs/peach-pi_defconfig +++ b/configs/peach-pi_defconfig @@ -8,6 +8,7 @@ CONFIG_SPL=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y diff --git a/configs/peach-pit_defconfig b/configs/peach-pit_defconfig index d0646ab..1934bf3 100644 --- a/configs/peach-pit_defconfig +++ b/configs/peach-pit_defconfig @@ -8,6 +8,7 @@ CONFIG_SPL=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 2600bf7..4034a2e 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -12,6 +12,7 @@ CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_OF_CONTROL=y CONFIG_OF_HOSTFILE=y CONFIG_CLK=y diff --git a/configs/snow_defconfig b/configs/snow_defconfig index 7624ad2..32c7c5d 100644 --- a/configs/snow_defconfig +++ b/configs/snow_defconfig @@ -9,6 +9,7 @@ CONFIG_CMD_SOUND=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y diff --git a/configs/spring_defconfig b/configs/spring_defconfig index 3b109fa..b20bfed 100644 --- a/configs/spring_defconfig +++ b/configs/spring_defconfig @@ -9,6 +9,7 @@ CONFIG_CMD_SOUND=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y

Acked-by: Christophe Ricardchristophe-h.ricard@st.com
On 23/08/2015 02:31, Simon Glass wrote:
This command provides a few useful tests so enable it for common boards.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
configs/chromebook_link_defconfig | 1 + configs/chromebox_panther_defconfig | 1 + configs/coreboot-x86_defconfig | 1 + configs/peach-pi_defconfig | 1 + configs/peach-pit_defconfig | 1 + configs/sandbox_defconfig | 1 + configs/snow_defconfig | 1 + configs/spring_defconfig | 1 + 8 files changed, 8 insertions(+)
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index 85752e4..9855736 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -12,6 +12,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index a6bafe3..c75b20d 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -12,6 +12,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y diff --git a/configs/coreboot-x86_defconfig b/configs/coreboot-x86_defconfig index fda2b7e..ebaf86b 100644 --- a/configs/coreboot-x86_defconfig +++ b/configs/coreboot-x86_defconfig @@ -10,6 +10,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y diff --git a/configs/peach-pi_defconfig b/configs/peach-pi_defconfig index 6416f16..56a5185 100644 --- a/configs/peach-pi_defconfig +++ b/configs/peach-pi_defconfig @@ -8,6 +8,7 @@ CONFIG_SPL=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y diff --git a/configs/peach-pit_defconfig b/configs/peach-pit_defconfig index d0646ab..1934bf3 100644 --- a/configs/peach-pit_defconfig +++ b/configs/peach-pit_defconfig @@ -8,6 +8,7 @@ CONFIG_SPL=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 2600bf7..4034a2e 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -12,6 +12,7 @@ CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_OF_CONTROL=y CONFIG_OF_HOSTFILE=y CONFIG_CLK=y diff --git a/configs/snow_defconfig b/configs/snow_defconfig index 7624ad2..32c7c5d 100644 --- a/configs/snow_defconfig +++ b/configs/snow_defconfig @@ -9,6 +9,7 @@ CONFIG_CMD_SOUND=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y diff --git a/configs/spring_defconfig b/configs/spring_defconfig index 3b109fa..b20bfed 100644 --- a/configs/spring_defconfig +++ b/configs/spring_defconfig @@ -9,6 +9,7 @@ CONFIG_CMD_SOUND=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y

On 24 August 2015 at 14:23, Christophe Ricard christophe.ricard@gmail.com wrote:
Acked-by: Christophe Ricardchristophe-h.ricard@st.com
Applied to u-boot-dm.

The TPM is listed in the device tree. Enable the driver and 'tpm' command so that it can be used.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com ---
Changes in v2: - Enable 'tpmtest' command for nyan - Update cover letter to mention panther and the tpmtest command.
configs/nyan-big_defconfig | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig index 274e955..6464c37 100644 --- a/configs/nyan-big_defconfig +++ b/configs/nyan-big_defconfig @@ -9,16 +9,21 @@ CONFIG_DEFAULT_DEVICE_TREE="tegra124-nyan-big" # CONFIG_CMD_FPGA is not set # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_NFS is not set +CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y CONFIG_SPL_DM=y CONFIG_SPI_FLASH=y CONFIG_CMD_CROS_EC=y CONFIG_CROS_EC=y CONFIG_CROS_EC_SPI=y CONFIG_CROS_EC_KEYB=y +CONFIG_DM_TPM=y +CONFIG_TPM_TIS_I2C=y CONFIG_TEGRA114_SPI=y CONFIG_DISPLAY_PORT=y CONFIG_VIDEO_TEGRA124=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_TPM=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_PROMPT="Tegra124 (Nyan-big) # "

On 22 August 2015 at 18:31, Simon Glass sjg@chromium.org wrote:
The TPM is listed in the device tree. Enable the driver and 'tpm' command so that it can be used.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Christophe Ricard christophe-h.ricard@st.com
Changes in v2:
- Enable 'tpmtest' command for nyan
- Update cover letter to mention panther and the tpmtest command.
configs/nyan-big_defconfig | 5 +++++ 1 file changed, 5 insertions(+)
Applied to u-boot-dm.

Hi Simon,
I like your updates but i have few comments: - I believe tpm_tis_i2c should be renamed as tpm_tis_infineon to be aligned with Linux naming. Also as there is no standard for i2c for tpm, every vendor does have their own low level transport protocol. I believe this is confusing.
- I think atmel tpm driver can be easily move to driver model with this new tpm class. I would cleanup some few #ifdef and make the code even clearer. May be i can try to send an update when sending ST33ZP24 TPM driver ?
Other than that, i looks pretty good.
Thanks a lot. Christophe
On 23/08/2015 02:31, Simon Glass wrote:
This series adds driver model support for Trusted Platform Modules (TPMs). These have a very simple interface and are configured via the device tree.
Two bus types are supported at present: I2C and LPC (Intel Low-Pin-Count).
Most drivers and users are converted over to driver model. The exception is the Atmel TPM and its users.
The I2C driver has been cleaned up and simplified. It was ported from Linux and was pretty hard to follow. This series includes patches to unify the code, remove duplicated data structures and drop unnecessary indirection.
Also this series enables the TPM on all Chromebooks supported by upstream U-Boot (snow, spring, nyan-big, pit, pi, link, panther) since some did not have it fully enabled.
As before, the 'tpm' command can be used to implement TPM functionality. In addition a 'tpmtest' command provides some basic TPM tests taken from Chrome OS U-Boot. These are fairly rudimentary but are useful if you know what you are doing.
Changes in v2:
- Add a 'TPM' menu in Kconfig
- Add new patch with a 'tpmtest' command
- Add new patch with functions to access flags and permissions
- Add tpm device tree node for panther also
- Correct error checking code in tpm_sendrecv_command()
- Correct error-checking code in report_return_code()
- Enable 'tpmtest' command for nyan
- Enhance uclass to support timeouts with new send()/recv() methods
- Implement the get_desc() method
- Include tpm.h header file instead of tis.h
- Move the timeout definitions into a new tpm_internal.h header
- Update cover letter to mention panther and the tpmtest command.
- Update driver for the new uclass interface
- Update driver for v2 TPM uclass which supports timeouts
- Use tpm_ prefix instead of tis_ for TPM functions
Simon Glass (28): tpm: Remove old pre-driver-model I2C code tpm: Drop two unused options tpm: Add Kconfig options for TPMs tpm: Convert board config TPM options to Kconfig tpm: Convert drivers to use SPDX tpm: Move the I2C TPM code into one file tpm: tpm_tis_i2c: Drop unnecessary methods tpm: tpm_tis_i2c: Drop struct tpm_vendor_specific tpm: tpm_tis_i2c: Merge struct tpm_dev into tpm_chip tpm: tpm_tis_i2c: Merge struct tpm into tpm_chip tpm: tpm_tis_i2c: Move definitions into the header file tpm: tpm_tis_i2c: Simplify init code tpm: tpm_tis_i2c: Use a consistent tpm_tis_i2c_ prefix tpm: tpm_tis_i2c: Tidy up delays dm: tpm: Add a uclass for Trusted Platform Modules dm: tpm: Convert the TPM command and library to driver model dm: i2c: Add a command to adjust the offset length tpm: Report tpm errors on the command line dm: tpm: sandbox: Convert TPM driver to driver model tpm: Check that parse_byte_string() has data to parse exynos: x86: dts: Add tpm nodes to the device tree for Chrome OS devices dm: tpm: Convert I2C driver to driver model dm: tpm: Convert LPC driver to driver model tpm: Add a 'tpm info' command tpm: Add functions to access flags and permissions dm: tpm: Add a 'tpmtest' command tpm: Enable 'tpmtest' command for Chrome OS boards with TPMs tegra: nyan: Enable TPM command and driver
README | 6 - arch/arm/dts/exynos5250-snow.dts | 9 + arch/arm/dts/exynos5250-spring.dts | 8 + arch/arm/dts/exynos5420-peach-pit.dts | 6 +- arch/arm/dts/exynos5800-peach-pi.dts | 6 +- arch/sandbox/dts/sandbox.dts | 4 + arch/x86/dts/chromebook_link.dts | 5 + arch/x86/dts/chromebox_panther.dts | 5 + common/Kconfig | 22 + common/Makefile | 1 + common/cmd_i2c.c | 33 + common/cmd_tpm.c | 100 ++- common/cmd_tpm_test.c | 565 +++++++++++++++++ configs/chromebook_link_defconfig | 5 + configs/chromebox_panther_defconfig | 5 + .../controlcenterd_36BIT_SDCARD_DEVELOP_defconfig | 4 + configs/controlcenterd_36BIT_SDCARD_defconfig | 4 + .../controlcenterd_TRAILBLAZER_DEVELOP_defconfig | 4 + configs/controlcenterd_TRAILBLAZER_defconfig | 4 + configs/coreboot-x86_defconfig | 5 + configs/nyan-big_defconfig | 5 + configs/peach-pi_defconfig | 5 + configs/peach-pit_defconfig | 5 + configs/sandbox_defconfig | 4 + configs/snow_defconfig | 5 + configs/spring_defconfig | 5 + drivers/tpm/Kconfig | 69 ++ drivers/tpm/Makefile | 4 +- drivers/tpm/tpm-uclass.c | 133 ++++ drivers/tpm/tpm.c | 694 --------------------- drivers/tpm/tpm_atmel_twi.c | 15 +- drivers/tpm/tpm_internal.h | 287 +++++++++ drivers/tpm/tpm_tis_i2c.c | 572 ++++++++--------- drivers/tpm/{tpm_private.h => tpm_tis_i2c.h} | 88 +-- drivers/tpm/tpm_tis_lpc.c | 290 ++++----- drivers/tpm/tpm_tis_sandbox.c | 57 +- include/configs/controlcenterd.h | 7 - include/configs/efi-x86.h | 2 - include/configs/exynos5-common.h | 7 - include/configs/x86-common.h | 2 - include/dm/uclass-id.h | 1 + include/fdtdec.h | 2 - include/tis.h | 3 + include/tpm.h | 243 +++++++- lib/Kconfig | 10 + lib/fdtdec.c | 2 - lib/tpm.c | 82 ++- 47 files changed, 2102 insertions(+), 1298 deletions(-) create mode 100644 common/cmd_tpm_test.c create mode 100644 drivers/tpm/tpm-uclass.c delete mode 100644 drivers/tpm/tpm.c create mode 100644 drivers/tpm/tpm_internal.h rename drivers/tpm/{tpm_private.h => tpm_tis_i2c.h} (54%)

Hi Christophe,
On 24 August 2015 at 14:20, Christophe Ricard christophe.ricard@gmail.com wrote:
Hi Simon,
I like your updates but i have few comments:
- I believe tpm_tis_i2c should be renamed as tpm_tis_infineon to be aligned
with Linux naming. Also as there is no standard for i2c for tpm, every vendor does have their own low level transport protocol. I believe this is confusing.
Yes agreed, but I thought you had a patch for that so I was planning on picking that up. I haven't checked if it will still apply though, so perhaps it needs a new version.
- I think atmel tpm driver can be easily move to driver model with this new
tpm class. I would cleanup some few #ifdef and make the code even clearer. May be i can try to send an update when sending ST33ZP24 TPM driver ?
That would be great!
Other than that, i looks pretty good.
Thanks a lot. Christophe
Regards, Simon
On 23/08/2015 02:31, Simon Glass wrote:
This series adds driver model support for Trusted Platform Modules (TPMs). These have a very simple interface and are configured via the device tree.
Two bus types are supported at present: I2C and LPC (Intel Low-Pin-Count).
Most drivers and users are converted over to driver model. The exception is the Atmel TPM and its users.
The I2C driver has been cleaned up and simplified. It was ported from Linux and was pretty hard to follow. This series includes patches to unify the code, remove duplicated data structures and drop unnecessary indirection.
Also this series enables the TPM on all Chromebooks supported by upstream U-Boot (snow, spring, nyan-big, pit, pi, link, panther) since some did not have it fully enabled.
As before, the 'tpm' command can be used to implement TPM functionality. In addition a 'tpmtest' command provides some basic TPM tests taken from Chrome OS U-Boot. These are fairly rudimentary but are useful if you know what you are doing.
Changes in v2:
- Add a 'TPM' menu in Kconfig
- Add new patch with a 'tpmtest' command
- Add new patch with functions to access flags and permissions
- Add tpm device tree node for panther also
- Correct error checking code in tpm_sendrecv_command()
- Correct error-checking code in report_return_code()
- Enable 'tpmtest' command for nyan
- Enhance uclass to support timeouts with new send()/recv() methods
- Implement the get_desc() method
- Include tpm.h header file instead of tis.h
- Move the timeout definitions into a new tpm_internal.h header
- Update cover letter to mention panther and the tpmtest command.
- Update driver for the new uclass interface
- Update driver for v2 TPM uclass which supports timeouts
- Use tpm_ prefix instead of tis_ for TPM functions
Simon Glass (28): tpm: Remove old pre-driver-model I2C code tpm: Drop two unused options tpm: Add Kconfig options for TPMs tpm: Convert board config TPM options to Kconfig tpm: Convert drivers to use SPDX tpm: Move the I2C TPM code into one file tpm: tpm_tis_i2c: Drop unnecessary methods tpm: tpm_tis_i2c: Drop struct tpm_vendor_specific tpm: tpm_tis_i2c: Merge struct tpm_dev into tpm_chip tpm: tpm_tis_i2c: Merge struct tpm into tpm_chip tpm: tpm_tis_i2c: Move definitions into the header file tpm: tpm_tis_i2c: Simplify init code tpm: tpm_tis_i2c: Use a consistent tpm_tis_i2c_ prefix tpm: tpm_tis_i2c: Tidy up delays dm: tpm: Add a uclass for Trusted Platform Modules dm: tpm: Convert the TPM command and library to driver model dm: i2c: Add a command to adjust the offset length tpm: Report tpm errors on the command line dm: tpm: sandbox: Convert TPM driver to driver model tpm: Check that parse_byte_string() has data to parse exynos: x86: dts: Add tpm nodes to the device tree for Chrome OS devices dm: tpm: Convert I2C driver to driver model dm: tpm: Convert LPC driver to driver model tpm: Add a 'tpm info' command tpm: Add functions to access flags and permissions dm: tpm: Add a 'tpmtest' command tpm: Enable 'tpmtest' command for Chrome OS boards with TPMs tegra: nyan: Enable TPM command and driver
README | 6 - arch/arm/dts/exynos5250-snow.dts | 9 + arch/arm/dts/exynos5250-spring.dts | 8 + arch/arm/dts/exynos5420-peach-pit.dts | 6 +- arch/arm/dts/exynos5800-peach-pi.dts | 6 +- arch/sandbox/dts/sandbox.dts | 4 + arch/x86/dts/chromebook_link.dts | 5 + arch/x86/dts/chromebox_panther.dts | 5 + common/Kconfig | 22 + common/Makefile | 1 + common/cmd_i2c.c | 33 + common/cmd_tpm.c | 100 ++- common/cmd_tpm_test.c | 565 +++++++++++++++++ configs/chromebook_link_defconfig | 5 + configs/chromebox_panther_defconfig | 5 + .../controlcenterd_36BIT_SDCARD_DEVELOP_defconfig | 4 + configs/controlcenterd_36BIT_SDCARD_defconfig | 4 + .../controlcenterd_TRAILBLAZER_DEVELOP_defconfig | 4 + configs/controlcenterd_TRAILBLAZER_defconfig | 4 + configs/coreboot-x86_defconfig | 5 + configs/nyan-big_defconfig | 5 + configs/peach-pi_defconfig | 5 + configs/peach-pit_defconfig | 5 + configs/sandbox_defconfig | 4 + configs/snow_defconfig | 5 + configs/spring_defconfig | 5 + drivers/tpm/Kconfig | 69 ++ drivers/tpm/Makefile | 4 +- drivers/tpm/tpm-uclass.c | 133 ++++ drivers/tpm/tpm.c | 694
drivers/tpm/tpm_atmel_twi.c | 15 +- drivers/tpm/tpm_internal.h | 287 +++++++++ drivers/tpm/tpm_tis_i2c.c | 572 ++++++++--------- drivers/tpm/{tpm_private.h => tpm_tis_i2c.h} | 88 +-- drivers/tpm/tpm_tis_lpc.c | 290 ++++----- drivers/tpm/tpm_tis_sandbox.c | 57 +- include/configs/controlcenterd.h | 7 - include/configs/efi-x86.h | 2 - include/configs/exynos5-common.h | 7 - include/configs/x86-common.h | 2 - include/dm/uclass-id.h | 1 + include/fdtdec.h | 2 - include/tis.h | 3 + include/tpm.h | 243 +++++++- lib/Kconfig | 10 + lib/fdtdec.c | 2 - lib/tpm.c | 82 ++- 47 files changed, 2102 insertions(+), 1298 deletions(-) create mode 100644 common/cmd_tpm_test.c create mode 100644 drivers/tpm/tpm-uclass.c delete mode 100644 drivers/tpm/tpm.c create mode 100644 drivers/tpm/tpm_internal.h rename drivers/tpm/{tpm_private.h => tpm_tis_i2c.h} (54%)
participants (3)
-
Christophe Ricard
-
Heiko Schocher
-
Simon Glass