diff options
Diffstat (limited to 'drivers/tpm')
-rw-r--r-- | drivers/tpm/Kconfig | 69 | ||||
-rw-r--r-- | drivers/tpm/Makefile | 3 | ||||
-rw-r--r-- | drivers/tpm/tpm-uclass.c | 6 | ||||
-rw-r--r-- | drivers/tpm/tpm2_tis_sandbox.c | 625 | ||||
-rw-r--r-- | drivers/tpm/tpm2_tis_spi.c | 679 | ||||
-rw-r--r-- | drivers/tpm/tpm_atmel_twi.c | 2 | ||||
-rw-r--r-- | drivers/tpm/tpm_tis.h | 1 | ||||
-rw-r--r-- | drivers/tpm/tpm_tis_infineon.c | 2 | ||||
-rw-r--r-- | drivers/tpm/tpm_tis_lpc.c | 2 | ||||
-rw-r--r-- | drivers/tpm/tpm_tis_sandbox.c | 2 | ||||
-rw-r--r-- | drivers/tpm/tpm_tis_st33zp24_i2c.c | 2 | ||||
-rw-r--r-- | drivers/tpm/tpm_tis_st33zp24_spi.c | 2 |
12 files changed, 1377 insertions, 18 deletions
diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig index 2a64bc49c3..93264ddd34 100644 --- a/drivers/tpm/Kconfig +++ b/drivers/tpm/Kconfig @@ -4,18 +4,31 @@ menu "TPM support" +comment "Please select only one TPM revision" + depends on TPM_V1 && TPM_V2 + +config TPM_V1 + bool "TPMv1.x support" + depends on TPM + default y + help + Major TPM versions are not compatible at all, choose either + one or the other. This option enables TPMv1.x drivers/commands. + +if TPM_V1 && !TPM_V2 + config TPM_TIS_SANDBOX bool "Enable sandbox TPM driver" - depends on SANDBOX + depends on TPM_V1 && SANDBOX help - This driver emulates a TPM, providing access to base functions + This driver emulates a TPMv1.x, 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 + depends on TPM_V1 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 @@ -24,7 +37,7 @@ config TPM_ATMEL_TWI config TPM_TIS_INFINEON bool "Enable support for Infineon SLB9635/45 TPMs on I2C" - depends on TPM && DM_I2C + depends on TPM_V1 && 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 @@ -48,7 +61,8 @@ config TPM_TIS_I2C_BURST_LIMITATION_LEN config TPM_TIS_LPC bool "Enable support for Infineon SLB9635/45 TPMs on LPC" - depends on TPM && X86 + depends on TPM_V1 && X86 + select TPM_DRIVER_SELECTED help This driver supports Infineon TPM devices connected on the LPC bus. The usual tpm operations and the 'tpm' command can be used to talk @@ -57,7 +71,7 @@ config TPM_TIS_LPC config TPM_AUTH_SESSIONS bool "Enable TPM authentication session support" - depends on TPM + depends on TPM_V1 help Enable support for authorised (AUTH1) commands as specified in the TCG Main Specification 1.2. OIAP-authorised versions of the commands @@ -66,7 +80,7 @@ config TPM_AUTH_SESSIONS config TPM_ST33ZP24_I2C bool "STMicroelectronics ST33ZP24 I2C TPM" - depends on TPM && DM_I2C + depends on TPM_V1 && DM_I2C ---help--- This driver supports STMicroelectronics TPM devices connected on the I2C bus. The usual tpm operations and the 'tpm' command can be used to talk @@ -75,7 +89,7 @@ config TPM_ST33ZP24_I2C config TPM_ST33ZP24_SPI bool "STMicroelectronics ST33ZP24 SPI TPM" - depends on TPM && DM_SPI + depends on TPM_V1 && DM_SPI ---help--- This driver supports STMicroelectronics TPM devices connected on the SPI bus. The usual tpm operations and the 'tpm' command can be used to talk @@ -84,14 +98,14 @@ config TPM_ST33ZP24_SPI config TPM_FLUSH_RESOURCES bool "Enable TPM resource flushing support" - depends on TPM + depends on TPM_V1 help Enable support to flush specific resources (e.g. keys) from the TPM. The functionality is available via the 'tpm' command as well. config TPM_LOAD_KEY_BY_SHA1 bool "Enable TPM key loading by SHA1 support" - depends on TPM + depends on TPM_V1 help Enable support to load keys into the TPM by identifying their parent via the public key's SHA1 hash. @@ -99,8 +113,41 @@ config TPM_LOAD_KEY_BY_SHA1 config TPM_LIST_RESOURCES bool "Enable TPM resource listing support" - depends on TPM + depends on TPM_V1 help Enable support to list specific resources (e.g. keys) within the TPM. The functionality is available via the 'tpm' command as well. + +endif # TPM_V1 + +config TPM_V2 + bool "TPMv2.x support" + depends on TPM + help + Major TPM versions are not compatible at all, choose either + one or the other. This option enables TPMv2.x drivers/commands. + +if TPM_V2 && !TPM_V1 + +config TPM2_TIS_SANDBOX + bool "Enable sandbox TPMv2.x driver" + depends on TPM_V2 && SANDBOX + select TPM_DRIVER_SELECTED + help + This driver emulates a TPMv2.x, providing access to base functions + such as basic configuration, PCR extension and PCR read. Extended + functionalities are not implemented. + +config TPM2_TIS_SPI + bool "Enable support for TPMv2.x SPI chips" + depends on TPM_V2 && DM_SPI + select TPM_DRIVER_SELECTED + help + This driver supports TPMv2.x devices connected on the SPI 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. + +endif # TPM_V2 + endmenu diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index e5fc86ff95..af473ef662 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -9,3 +9,6 @@ obj-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o obj-$(CONFIG_TPM_TIS_SANDBOX) += tpm_tis_sandbox.o obj-$(CONFIG_TPM_ST33ZP24_I2C) += tpm_tis_st33zp24_i2c.o obj-$(CONFIG_TPM_ST33ZP24_SPI) += tpm_tis_st33zp24_spi.o + +obj-$(CONFIG_TPM2_TIS_SANDBOX) += tpm2_tis_sandbox.o +obj-$(CONFIG_TPM2_TIS_SPI) += tpm2_tis_spi.o diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c index e71545235c..412697eedc 100644 --- a/drivers/tpm/tpm-uclass.c +++ b/drivers/tpm/tpm-uclass.c @@ -6,8 +6,12 @@ #include <common.h> #include <dm.h> -#include <tpm.h> #include <linux/unaligned/be_byteshift.h> +#if defined(CONFIG_TPM_V1) +#include <tpm-v1.h> +#elif defined(CONFIG_TPM_V2) +#include <tpm-v2.h> +#endif #include "tpm_internal.h" int tpm_open(struct udevice *dev) diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c new file mode 100644 index 0000000000..3240cc5dba --- /dev/null +++ b/drivers/tpm/tpm2_tis_sandbox.c @@ -0,0 +1,625 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2018, Bootlin + * Author: Miquel Raynal <miquel.raynal@bootlin.com> + */ + +#include <common.h> +#include <dm.h> +#include <tpm-v2.h> +#include <asm/state.h> +#include <asm/unaligned.h> +#include <linux/crc8.h> + +/* Hierarchies */ +enum tpm2_hierarchy { + TPM2_HIERARCHY_LOCKOUT = 0, + TPM2_HIERARCHY_ENDORSEMENT, + TPM2_HIERARCHY_PLATFORM, + TPM2_HIERARCHY_NB, +}; + +/* Subset of supported capabilities */ +enum tpm2_capability { + TPM_CAP_TPM_PROPERTIES = 0x6, +}; + +/* Subset of supported properties */ +#define TPM2_PROPERTIES_OFFSET 0x0000020E + +enum tpm2_cap_tpm_property { + TPM2_FAIL_COUNTER = 0, + TPM2_PROP_MAX_TRIES, + TPM2_RECOVERY_TIME, + TPM2_LOCKOUT_RECOVERY, + TPM2_PROPERTY_NB, +}; + +#define SANDBOX_TPM_PCR_NB 1 + +static const u8 sandbox_extended_once_pcr[] = { + 0xf5, 0xa5, 0xfd, 0x42, 0xd1, 0x6a, 0x20, 0x30, + 0x27, 0x98, 0xef, 0x6e, 0xd3, 0x09, 0x97, 0x9b, + 0x43, 0x00, 0x3d, 0x23, 0x20, 0xd9, 0xf0, 0xe8, + 0xea, 0x98, 0x31, 0xa9, 0x27, 0x59, 0xfb, 0x4b, +}; + +struct sandbox_tpm2 { + /* TPM internal states */ + bool init_done; + bool startup_done; + bool tests_done; + /* TPM password per hierarchy */ + char pw[TPM2_HIERARCHY_NB][TPM2_DIGEST_LEN + 1]; + int pw_sz[TPM2_HIERARCHY_NB]; + /* TPM properties */ + u32 properties[TPM2_PROPERTY_NB]; + /* TPM PCRs */ + u8 pcr[SANDBOX_TPM_PCR_NB][TPM2_DIGEST_LEN]; + /* TPM PCR extensions */ + u32 pcr_extensions[SANDBOX_TPM_PCR_NB]; +}; + +/* + * Check the tag validity depending on the command (authentication required or + * not). If authentication is required, check it is valid. Update the auth + * pointer to point to the next chunk of data to process if needed. + */ +static int sandbox_tpm2_check_session(struct udevice *dev, u32 command, u16 tag, + const u8 **auth, + enum tpm2_hierarchy *hierarchy) +{ + struct sandbox_tpm2 *tpm = dev_get_priv(dev); + u32 handle, auth_sz, session_handle; + u16 nonce_sz, pw_sz; + const char *pw; + + switch (command) { + case TPM2_CC_STARTUP: + case TPM2_CC_SELF_TEST: + case TPM2_CC_GET_CAPABILITY: + case TPM2_CC_PCR_READ: + if (tag != TPM2_ST_NO_SESSIONS) { + printf("No session required for command 0x%x\n", + command); + return TPM2_RC_BAD_TAG; + } + + return 0; + + case TPM2_CC_CLEAR: + case TPM2_CC_HIERCHANGEAUTH: + case TPM2_CC_DAM_RESET: + case TPM2_CC_DAM_PARAMETERS: + case TPM2_CC_PCR_EXTEND: + if (tag != TPM2_ST_SESSIONS) { + printf("Session required for command 0x%x\n", command); + return TPM2_RC_AUTH_CONTEXT; + } + + handle = get_unaligned_be32(*auth); + *auth += sizeof(handle); + + /* + * PCR_Extend had a different protection mechanism and does not + * use the same standards as other commands. + */ + if (command == TPM2_CC_PCR_EXTEND) + break; + + switch (handle) { + case TPM2_RH_LOCKOUT: + *hierarchy = TPM2_HIERARCHY_LOCKOUT; + break; + case TPM2_RH_ENDORSEMENT: + if (command == TPM2_CC_CLEAR) { + printf("Endorsement hierarchy unsupported\n"); + return TPM2_RC_AUTH_MISSING; + } + *hierarchy = TPM2_HIERARCHY_ENDORSEMENT; + break; + case TPM2_RH_PLATFORM: + *hierarchy = TPM2_HIERARCHY_PLATFORM; + break; + default: + printf("Wrong handle 0x%x\n", handle); + return TPM2_RC_VALUE; + } + + break; + + default: + printf("Command code not recognized: 0x%x\n", command); + return TPM2_RC_COMMAND_CODE; + } + + auth_sz = get_unaligned_be32(*auth); + *auth += sizeof(auth_sz); + + session_handle = get_unaligned_be32(*auth); + *auth += sizeof(session_handle); + if (session_handle != TPM2_RS_PW) { + printf("Wrong session handle 0x%x\n", session_handle); + return TPM2_RC_VALUE; + } + + nonce_sz = get_unaligned_be16(*auth); + *auth += sizeof(nonce_sz); + if (nonce_sz) { + printf("Nonces not supported in Sandbox, aborting\n"); + return TPM2_RC_HANDLE; + } + + /* Ignore attributes */ + *auth += sizeof(u8); + + pw_sz = get_unaligned_be16(*auth); + *auth += sizeof(pw_sz); + if (auth_sz != (9 + nonce_sz + pw_sz)) { + printf("Authentication size (%d) do not match %d\n", + auth_sz, 9 + nonce_sz + pw_sz); + return TPM2_RC_SIZE; + } + + /* No passwork is acceptable */ + if (!pw_sz && !tpm->pw_sz[*hierarchy]) + return TPM2_RC_SUCCESS; + + /* Password is too long */ + if (pw_sz > TPM2_DIGEST_LEN) { + printf("Password should not be more than %dB\n", + TPM2_DIGEST_LEN); + return TPM2_RC_AUTHSIZE; + } + + pw = (const char *)*auth; + *auth += pw_sz; + + /* Password is wrong */ + if (pw_sz != tpm->pw_sz[*hierarchy] || + strncmp(pw, tpm->pw[*hierarchy], tpm->pw_sz[*hierarchy])) { + printf("Authentication failed: wrong password.\n"); + return TPM2_RC_BAD_AUTH; + } + + return TPM2_RC_SUCCESS; +} + +static int sandbox_tpm2_check_readyness(struct udevice *dev, int command) +{ + struct sandbox_tpm2 *tpm = dev_get_priv(dev); + + switch (command) { + case TPM2_CC_STARTUP: + if (!tpm->init_done || tpm->startup_done) + return TPM2_RC_INITIALIZE; + + break; + case TPM2_CC_GET_CAPABILITY: + if (!tpm->init_done || !tpm->startup_done) + return TPM2_RC_INITIALIZE; + + break; + case TPM2_CC_SELF_TEST: + if (!tpm->startup_done) + return TPM2_RC_INITIALIZE; + + break; + default: + if (!tpm->tests_done) + return TPM2_RC_NEEDS_TEST; + + break; + } + + return 0; +} + +static int sandbox_tpm2_fill_buf(u8 **recv, size_t *recv_len, u16 tag, u32 rc) +{ + *recv_len = sizeof(tag) + sizeof(u32) + sizeof(rc); + + /* Write tag */ + put_unaligned_be16(tag, *recv); + *recv += sizeof(tag); + + /* Write length */ + put_unaligned_be32(*recv_len, *recv); + *recv += sizeof(u32); + + /* Write return code */ + put_unaligned_be32(rc, *recv); + *recv += sizeof(rc); + + /* Add trailing \0 */ + *recv = '\0'; + + return 0; +} + +static int sandbox_tpm2_extend(struct udevice *dev, int pcr_index, + const u8 *extension) +{ + struct sandbox_tpm2 *tpm = dev_get_priv(dev); + int i; + + /* Only simulate the first extensions from all '0' with only '0' */ + for (i = 0; i < TPM2_DIGEST_LEN; i++) + if (tpm->pcr[pcr_index][i] || extension[i]) + return TPM2_RC_FAILURE; + + memcpy(tpm->pcr[pcr_index], sandbox_extended_once_pcr, + TPM2_DIGEST_LEN); + tpm->pcr_extensions[pcr_index]++; + + return 0; +}; + +static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, + size_t send_size, u8 *recvbuf, + size_t *recv_len) +{ + struct sandbox_tpm2 *tpm = dev_get_priv(dev); + enum tpm2_hierarchy hierarchy = 0; + const u8 *sent = sendbuf; + u8 *recv = recvbuf; + u32 length, command, rc = 0; + u16 tag, mode, new_pw_sz; + u8 yes_no; + int i, j; + + /* TPM2_GetProperty */ + u32 capability, property, property_count; + + /* TPM2_PCR_Read/Extend variables */ + int pcr_index; + u64 pcr_map = 0; + u32 selections, pcr_nb; + u16 alg; + u8 pcr_array_sz; + + tag = get_unaligned_be16(sent); + sent += sizeof(tag); + + length = get_unaligned_be32(sent); + sent += sizeof(length); + if (length != send_size) { + printf("TPM2: Unmatching length, received: %ld, expected: %d\n", + send_size, length); + rc = TPM2_RC_SIZE; + sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + return 0; + } + + command = get_unaligned_be32(sent); + sent += sizeof(command); + rc = sandbox_tpm2_check_readyness(dev, command); + if (rc) { + sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + return 0; + } + + rc = sandbox_tpm2_check_session(dev, command, tag, &sent, &hierarchy); + if (rc) { + sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + return 0; + } + + switch (command) { + case TPM2_CC_STARTUP: + mode = get_unaligned_be16(sent); + sent += sizeof(mode); + switch (mode) { + case TPM2_SU_CLEAR: + case TPM2_SU_STATE: + break; + default: + rc = TPM2_RC_VALUE; + } + + tpm->startup_done = true; + + sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + break; + + case TPM2_CC_SELF_TEST: + yes_no = *sent; + sent += sizeof(yes_no); + switch (yes_no) { + case TPMI_YES: + case TPMI_NO: + break; + default: + rc = TPM2_RC_VALUE; + } + + tpm->tests_done = true; + + sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + break; + + case TPM2_CC_CLEAR: + /* Reset this hierarchy password */ + tpm->pw_sz[hierarchy] = 0; + + /* Reset all password if thisis the PLATFORM hierarchy */ + if (hierarchy == TPM2_HIERARCHY_PLATFORM) + for (i = 0; i < TPM2_HIERARCHY_NB; i++) + tpm->pw_sz[i] = 0; + + /* Reset the properties */ + for (i = 0; i < TPM2_PROPERTY_NB; i++) + tpm->properties[i] = 0; + + /* Reset the PCRs and their number of extensions */ + for (i = 0; i < SANDBOX_TPM_PCR_NB; i++) { + tpm->pcr_extensions[i] = 0; + for (j = 0; j < TPM2_DIGEST_LEN; j++) + tpm->pcr[i][j] = 0; + } + + sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + break; + + case TPM2_CC_HIERCHANGEAUTH: + new_pw_sz = get_unaligned_be16(sent); + sent += sizeof(new_pw_sz); + if (new_pw_sz > TPM2_DIGEST_LEN) { + rc = TPM2_RC_SIZE; + } else if (new_pw_sz) { + tpm->pw_sz[hierarchy] = new_pw_sz; + memcpy(tpm->pw[hierarchy], sent, new_pw_sz); + sent += new_pw_sz; + } + + sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + break; + + case TPM2_CC_GET_CAPABILITY: + capability = get_unaligned_be32(sent); + sent += sizeof(capability); + if (capability != TPM_CAP_TPM_PROPERTIES) { + printf("Sandbox TPM only support TPM_CAPABILITIES\n"); + return TPM2_RC_HANDLE; + } + + property = get_unaligned_be32(sent); + sent += sizeof(property); + property -= TPM2_PROPERTIES_OFFSET; + + property_count = get_unaligned_be32(sent); + sent += sizeof(property_count); + if (!property_count || + property + property_count > TPM2_PROPERTY_NB) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + } + + /* Write tag */ + put_unaligned_be16(tag, recv); + recv += sizeof(tag); + + /* Ignore length for now */ + recv += sizeof(u32); + + /* Write return code */ + put_unaligned_be32(rc, recv); + recv += sizeof(rc); + + /* Tell there is more data to read */ + *recv = TPMI_YES; + recv += sizeof(yes_no); + + /* Repeat the capability */ + put_unaligned_be32(capability, recv); + recv += sizeof(capability); + + /* Give the number of properties that follow */ + put_unaligned_be32(property_count, recv); + recv += sizeof(property_count); + + /* Fill with the properties */ + for (i = 0; i < property_count; i++) { + put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property + + i, recv); + recv += sizeof(property); + put_unaligned_be32(tpm->properties[property + i], + recv); + recv += sizeof(property); + } + + /* Add trailing \0 */ + *recv = '\0'; + + /* Write response length */ + *recv_len = recv - recvbuf; + put_unaligned_be32(*recv_len, recvbuf + sizeof(tag)); + + break; + + case TPM2_CC_DAM_PARAMETERS: + tpm->properties[TPM2_PROP_MAX_TRIES] = get_unaligned_be32(sent); + sent += sizeof(*tpm->properties); + tpm->properties[TPM2_RECOVERY_TIME] = get_unaligned_be32(sent); + sent += sizeof(*tpm->properties); + tpm->properties[TPM2_LOCKOUT_RECOVERY] = get_unaligned_be32(sent); + sent += sizeof(*tpm->properties); + + sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + break; + + case TPM2_CC_PCR_READ: + selections = get_unaligned_be32(sent); + sent += sizeof(selections); + if (selections != 1) { + printf("Sandbox cannot handle more than one PCR\n"); + rc = TPM2_RC_VALUE; + return sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + } + + alg = get_unaligned_be16(sent); + sent += sizeof(alg); + if (alg != TPM2_ALG_SHA256) { + printf("Sandbox TPM only handle SHA256 algorithm\n"); + rc = TPM2_RC_VALUE; + return sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + } + + pcr_array_sz = *sent; + sent += sizeof(pcr_array_sz); + if (!pcr_array_sz || pcr_array_sz > 8) { + printf("Sandbox TPM cannot handle so much PCRs\n"); + rc = TPM2_RC_VALUE; + return sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + } + + for (i = 0; i < pcr_array_sz; i++) + pcr_map += (u64)sent[i] << (i * 8); + + if (pcr_map >> SANDBOX_TPM_PCR_NB) { + printf("Sandbox TPM handles up to %d PCR(s)\n", + SANDBOX_TPM_PCR_NB); + rc = TPM2_RC_VALUE; + return sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + } + + if (pcr_map >> SANDBOX_TPM_PCR_NB) { + printf("Wrong PCR map.\n"); + rc = TPM2_RC_VALUE; + return sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + } + + for (i = 0; i < SANDBOX_TPM_PCR_NB; i++) + if (pcr_map & BIT(i)) + pcr_index = i; + + /* Write tag */ + put_unaligned_be16(tag, recv); + recv += sizeof(tag); + + /* Ignore length for now */ + recv += sizeof(u32); + + /* Write return code */ + put_unaligned_be32(rc, recv); + recv += sizeof(rc); + + /* Number of extensions */ + put_unaligned_be32(tpm->pcr_extensions[pcr_index], recv); + recv += sizeof(u32); + + /* Copy the PCR */ + memcpy(recv, tpm->pcr[pcr_index], TPM2_DIGEST_LEN); + recv += TPM2_DIGEST_LEN; + + /* Add trailing \0 */ + *recv = '\0'; + + /* Write response length */ + *recv_len = recv - recvbuf; + put_unaligned_be32(*recv_len, recvbuf + sizeof(tag)); + + break; + + case TPM2_CC_PCR_EXTEND: + /* Get the PCR index */ + pcr_index = get_unaligned_be32(sendbuf + sizeof(tag) + + sizeof(length) + + sizeof(command)); + if (pcr_index > SANDBOX_TPM_PCR_NB) { + printf("Sandbox TPM handles up to %d PCR(s)\n", + SANDBOX_TPM_PCR_NB); + rc = TPM2_RC_VALUE; + } + + /* Check the number of hashes */ + pcr_nb = get_unaligned_be32(sent); + sent += sizeof(pcr_nb); + if (pcr_nb != 1) { + printf("Sandbox cannot handle more than one PCR\n"); + rc = TPM2_RC_VALUE; + return sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + } + + /* Check the hash algorithm */ + alg = get_unaligned_be16(sent); + sent += sizeof(alg); + if (alg != TPM2_ALG_SHA256) { + printf("Sandbox TPM only handle SHA256 algorithm\n"); + rc = TPM2_RC_VALUE; + return sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + } + + /* Extend the PCR */ + rc = sandbox_tpm2_extend(dev, pcr_index, sent); + + sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + break; + + default: + printf("TPM2 command %02x unknown in Sandbox\n", command); + rc = TPM2_RC_COMMAND_CODE; + sandbox_tpm2_fill_buf(&recv, recv_len, tag, rc); + } + + return 0; +} + +static int sandbox_tpm2_get_desc(struct udevice *dev, char *buf, int size) +{ + if (size < 15) + return -ENOSPC; + + return snprintf(buf, size, "Sandbox TPM2.x"); +} + +static int sandbox_tpm2_open(struct udevice *dev) +{ + struct sandbox_tpm2 *tpm = dev_get_priv(dev); + + if (tpm->init_done) + return -EIO; + + tpm->init_done = true; + + return 0; +} + +static int sandbox_tpm2_probe(struct udevice *dev) +{ + struct sandbox_tpm2 *tpm = dev_get_priv(dev); + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); + + memset(tpm, 0, sizeof(*tpm)); + + priv->pcr_count = 32; + priv->pcr_select_min = 2; + + return 0; +} + +static int sandbox_tpm2_close(struct udevice *dev) +{ + return 0; +} + +static const struct tpm_ops sandbox_tpm2_ops = { + .open = sandbox_tpm2_open, + .close = sandbox_tpm2_close, + .get_desc = sandbox_tpm2_get_desc, + .xfer = sandbox_tpm2_xfer, +}; + +static const struct udevice_id sandbox_tpm2_ids[] = { + { .compatible = "sandbox,tpm2" }, + { } +}; + +U_BOOT_DRIVER(sandbox_tpm2) = { + .name = "sandbox_tpm2", + .id = UCLASS_TPM, + .of_match = sandbox_tpm2_ids, + .ops = &sandbox_tpm2_ops, + .probe = sandbox_tpm2_probe, + .priv_auto_alloc_size = sizeof(struct sandbox_tpm2), +}; diff --git a/drivers/tpm/tpm2_tis_spi.c b/drivers/tpm/tpm2_tis_spi.c new file mode 100644 index 0000000000..c5d17a679d --- /dev/null +++ b/drivers/tpm/tpm2_tis_spi.c @@ -0,0 +1,679 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Author: + * Miquel Raynal <miquel.raynal@bootlin.com> + * + * Description: + * SPI-level driver for TCG/TIS TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * This device driver implements the TPM interface as defined in + * the TCG SPI protocol stack version 2.0. + * + * It is based on the U-Boot driver tpm_tis_infineon_i2c.c. + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <log.h> +#include <spi.h> +#include <tpm-v2.h> +#include <linux/errno.h> +#include <linux/compiler.h> +#include <linux/types.h> +#include <linux/unaligned/be_byteshift.h> +#include <asm-generic/gpio.h> + +#include "tpm_tis.h" +#include "tpm_internal.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define TPM_ACCESS(l) (0x0000 | ((l) << 12)) +#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) +#define TPM_STS(l) (0x0018 | ((l) << 12)) +#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) +#define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) +#define TPM_RID(l) (0x0F04 | ((l) << 12)) + +#define MAX_SPI_FRAMESIZE 64 + +/* Number of wait states to wait for */ +#define TPM_WAIT_STATES 100 + +/** + * struct tpm_tis_chip_data - Non-discoverable TPM information + * + * @pcr_count: Number of PCR per bank + * @pcr_select_min: Size in octets of the pcrSelect array + */ +struct tpm_tis_chip_data { + unsigned int pcr_count; + unsigned int pcr_select_min; + unsigned int time_before_first_cmd_ms; +}; + +/** + * tpm_tis_spi_read() - Read from TPM register + * + * @addr: register address to read from + * @buffer: provided by caller + * @len: number of bytes to read + * + * Read len bytes from TPM register and put them into + * buffer (little-endian format, i.e. first byte is put into buffer[0]). + * + * NOTE: TPM is big-endian for multi-byte values. Multi-byte + * values have to be swapped. + * + * @return -EIO on error, 0 on success. + */ +static int tpm_tis_spi_xfer(struct udevice *dev, u32 addr, const u8 *out, + u8 *in, u16 len) +{ + struct spi_slave *slave = dev_get_parent_priv(dev); + int transfer_len, ret; + u8 tx_buf[MAX_SPI_FRAMESIZE]; + u8 rx_buf[MAX_SPI_FRAMESIZE]; + + if (in && out) { + log(LOGC_NONE, LOGL_ERR, "%s: can't do full duplex\n", + __func__); + return -EINVAL; + } + + ret = spi_claim_bus(slave); + if (ret < 0) { + log(LOGC_NONE, LOGL_ERR, "%s: could not claim bus\n", __func__); + return ret; + } + + while (len) { + /* Request */ + transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); + tx_buf[0] = (in ? BIT(7) : 0) | (transfer_len - 1); + tx_buf[1] = 0xD4; + tx_buf[2] = addr >> 8; + tx_buf[3] = addr; + + ret = spi_xfer(slave, 4 * 8, tx_buf, rx_buf, SPI_XFER_BEGIN); + if (ret < 0) { + log(LOGC_NONE, LOGL_ERR, + "%s: spi request transfer failed (err: %d)\n", + __func__, ret); + goto release_bus; + } + + /* Wait state */ + if (!(rx_buf[3] & 0x1)) { + int i; + + for (i = 0; i < TPM_WAIT_STATES; i++) { + ret = spi_xfer(slave, 1 * 8, NULL, rx_buf, 0); + if (ret) { + log(LOGC_NONE, LOGL_ERR, + "%s: wait state failed: %d\n", + __func__, ret); + goto release_bus; + } + + if (rx_buf[0] & 0x1) + break; + } + + if (i == TPM_WAIT_STATES) { + log(LOGC_NONE, LOGL_ERR, + "%s: timeout on wait state\n", __func__); + ret = -ETIMEDOUT; + goto release_bus; + } + } + + /* Read/Write */ + if (out) { + memcpy(tx_buf, out, transfer_len); + out += transfer_len; + } + + ret = spi_xfer(slave, transfer_len * 8, + out ? tx_buf : NULL, + in ? rx_buf : NULL, + SPI_XFER_END); + if (ret) { + log(LOGC_NONE, LOGL_ERR, + "%s: spi read transfer failed (err: %d)\n", + __func__, ret); + goto release_bus; + } + + if (in) { + memcpy(in, rx_buf, transfer_len); + in += transfer_len; + } + + len -= transfer_len; + } + +release_bus: + /* If an error occurred, release the chip by deasserting the CS */ + if (ret < 0) + spi_xfer(slave, 0, NULL, NULL, SPI_XFER_END); + + spi_release_bus(slave); + + return ret; +} + +static int tpm_tis_spi_read(struct udevice *dev, u16 addr, u8 *in, u16 len) +{ + return tpm_tis_spi_xfer(dev, addr, NULL, in, len); +} + +static int tpm_tis_spi_read32(struct udevice *dev, u32 addr, u32 *result) +{ + __le32 result_le; + int ret; + + ret = tpm_tis_spi_read(dev, addr, (u8 *)&result_le, sizeof(u32)); + if (!ret) + *result = le32_to_cpu(result_le); + + return ret; +} + +static int tpm_tis_spi_write(struct udevice *dev, u16 addr, const u8 *out, + u16 len) +{ + return tpm_tis_spi_xfer(dev, addr, out, NULL, len); +} + +static int tpm_tis_spi_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 ret; + + ret = tpm_tis_spi_read(dev, TPM_ACCESS(loc), &buf, 1); + if (ret) + return ret; + + if ((buf & mask) == mask) { + chip->locality = loc; + return 0; + } + + return -ENOENT; +} + +static void tpm_tis_spi_release_locality(struct udevice *dev, int loc, + bool force) +{ + const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID; + u8 buf; + + if (tpm_tis_spi_read(dev, TPM_ACCESS(loc), &buf, 1) < 0) + return; + + if (force || (buf & mask) == mask) { + buf = TPM_ACCESS_ACTIVE_LOCALITY; + tpm_tis_spi_write(dev, TPM_ACCESS(loc), &buf, 1); + } +} + +static int tpm_tis_spi_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 ret; + + ret = tpm_tis_spi_check_locality(dev, loc); + if (!ret) + return 0; + + if (ret != -ENOENT) { + log(LOGC_NONE, LOGL_ERR, "%s: Failed to get locality: %d\n", + __func__, ret); + return ret; + } + + ret = tpm_tis_spi_write(dev, TPM_ACCESS(loc), &buf, 1); + if (ret) { + log(LOGC_NONE, LOGL_ERR, "%s: Failed to write to TPM: %d\n", + __func__, ret); + return ret; + } + + start = get_timer(0); + stop = chip->timeout_a; + do { + ret = tpm_tis_spi_check_locality(dev, loc); + if (!ret) + return 0; + + if (ret != -ENOENT) { + log(LOGC_NONE, LOGL_ERR, + "%s: Failed to get locality: %d\n", __func__, ret); + return ret; + } + + mdelay(TPM_TIMEOUT_MS); + } while (get_timer(start) < stop); + + log(LOGC_NONE, LOGL_ERR, "%s: Timeout getting locality: %d\n", __func__, + ret); + + return ret; +} + +static u8 tpm_tis_spi_status(struct udevice *dev, u8 *status) +{ + struct tpm_chip *chip = dev_get_priv(dev); + + return tpm_tis_spi_read(dev, TPM_STS(chip->locality), status, 1); +} + +static int tpm_tis_spi_wait_for_stat(struct udevice *dev, u8 mask, + unsigned long timeout, u8 *status) +{ + unsigned long start = get_timer(0); + unsigned long stop = timeout; + int ret; + + do { + mdelay(TPM_TIMEOUT_MS); + ret = tpm_tis_spi_status(dev, status); + if (ret) + return ret; + + if ((*status & mask) == mask) + return 0; + } while (get_timer(start) < stop); + + return -ETIMEDOUT; +} + +static int tpm_tis_spi_get_burstcount(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + unsigned long start, stop; + u32 burstcount, ret; + + /* wait for burstcount */ + start = get_timer(0); + stop = chip->timeout_d; + do { + ret = tpm_tis_spi_read32(dev, TPM_STS(chip->locality), + &burstcount); + if (ret) + return -EBUSY; + + burstcount = (burstcount >> 8) & 0xFFFF; + if (burstcount) + return burstcount; + + mdelay(TPM_TIMEOUT_MS); + } while (get_timer(start) < stop); + + return -EBUSY; +} + +static int tpm_tis_spi_cancel(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + u8 data = TPM_STS_COMMAND_READY; + + return tpm_tis_spi_write(dev, TPM_STS(chip->locality), &data, 1); +} + +static int tpm_tis_spi_recv_data(struct udevice *dev, u8 *buf, size_t count) +{ + struct tpm_chip *chip = dev_get_priv(dev); + int size = 0, burstcnt, len, ret; + u8 status; + + while (size < count && + tpm_tis_spi_wait_for_stat(dev, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, + chip->timeout_c, &status) == 0) { + burstcnt = tpm_tis_spi_get_burstcount(dev); + if (burstcnt < 0) + return burstcnt; + + len = min_t(int, burstcnt, count - size); + ret = tpm_tis_spi_read(dev, TPM_DATA_FIFO(chip->locality), + buf + size, len); + if (ret < 0) + return ret; + + size += len; + } + + return size; +} + +static int tpm_tis_spi_recv(struct udevice *dev, u8 *buf, size_t count) +{ + struct tpm_chip *chip = dev_get_priv(dev); + int size, expected; + + if (!chip) + return -ENODEV; + + if (count < TPM_HEADER_SIZE) { + size = -EIO; + goto out; + } + + size = tpm_tis_spi_recv_data(dev, buf, TPM_HEADER_SIZE); + if (size < TPM_HEADER_SIZE) { + log(LOGC_NONE, LOGL_ERR, "TPM error, unable to read header\n"); + goto out; + } + + expected = get_unaligned_be32(buf + 2); + if (expected > count) { + size = -EIO; + goto out; + } + + size += tpm_tis_spi_recv_data(dev, &buf[TPM_HEADER_SIZE], + expected - TPM_HEADER_SIZE); + if (size < expected) { + log(LOGC_NONE, LOGL_ERR, + "TPM error, unable to read remaining bytes of result\n"); + size = -EIO; + goto out; + } + +out: + tpm_tis_spi_cancel(dev); + tpm_tis_spi_release_locality(dev, chip->locality, false); + + return size; +} + +static int tpm_tis_spi_send(struct udevice *dev, const u8 *buf, size_t len) +{ + struct tpm_chip *chip = dev_get_priv(dev); + u32 i, size; + u8 status; + int burstcnt, ret; + u8 data; + + if (!chip) + return -ENODEV; + + if (len > TPM_DEV_BUFSIZE) + return -E2BIG; /* Command is too long for our tpm, sorry */ + + ret = tpm_tis_spi_request_locality(dev, 0); + if (ret < 0) + return -EBUSY; + + /* + * Check if the TPM is ready. If not, if not, cancel the pending command + * and poll on the status to be finally ready. + */ + ret = tpm_tis_spi_status(dev, &status); + if (ret) + return ret; + + if (!(status & TPM_STS_COMMAND_READY)) { + /* Force the transition, usually this will be done at startup */ + ret = tpm_tis_spi_cancel(dev); + if (ret) { + log(LOGC_NONE, LOGL_ERR, + "%s: Could not cancel previous operation\n", + __func__); + goto out_err; + } + + ret = tpm_tis_spi_wait_for_stat(dev, TPM_STS_COMMAND_READY, + chip->timeout_b, &status); + if (ret < 0 || !(status & TPM_STS_COMMAND_READY)) { + log(LOGC_NONE, LOGL_ERR, + "status %d after wait for stat returned %d\n", + status, ret); + goto out_err; + } + } + + for (i = 0; i < len - 1;) { + burstcnt = tpm_tis_spi_get_burstcount(dev); + if (burstcnt < 0) + return burstcnt; + + size = min_t(int, len - i - 1, burstcnt); + ret = tpm_tis_spi_write(dev, TPM_DATA_FIFO(chip->locality), + buf + i, size); + if (ret < 0) + goto out_err; + + i += size; + } + + ret = tpm_tis_spi_status(dev, &status); + if (ret) + goto out_err; + + if ((status & TPM_STS_DATA_EXPECT) == 0) { + ret = -EIO; + goto out_err; + } + + ret = tpm_tis_spi_write(dev, TPM_DATA_FIFO(chip->locality), + buf + len - 1, 1); + if (ret) + goto out_err; + + ret = tpm_tis_spi_status(dev, &status); + if (ret) + goto out_err; + + if ((status & TPM_STS_DATA_EXPECT) != 0) { + ret = -EIO; + goto out_err; + } + + data = TPM_STS_GO; + ret = tpm_tis_spi_write(dev, TPM_STS(chip->locality), &data, 1); + if (ret) + goto out_err; + + return len; + +out_err: + tpm_tis_spi_cancel(dev); + tpm_tis_spi_release_locality(dev, chip->locality, false); + + return ret; +} + +static int tpm_tis_spi_cleanup(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + + tpm_tis_spi_cancel(dev); + /* + * The TPM needs some time to clean up here, + * so we sleep rather than keeping the bus busy + */ + mdelay(2); + tpm_tis_spi_release_locality(dev, chip->locality, false); + + return 0; +} + +static int tpm_tis_spi_open(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + + if (chip->is_open) + return -EBUSY; + + chip->is_open = 1; + + return 0; +} + +static int tpm_tis_spi_close(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + + if (chip->is_open) { + tpm_tis_spi_release_locality(dev, chip->locality, true); + chip->is_open = 0; + } + + return 0; +} + +static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size) +{ + struct tpm_chip *chip = dev_get_priv(dev); + + if (size < 80) + return -ENOSPC; + + return snprintf(buf, size, + "%s v2.0: VendorID 0x%04x, DeviceID 0x%04x, RevisionID 0x%02x [%s]", + dev->name, chip->vend_dev & 0xFFFF, + chip->vend_dev >> 16, chip->rid, + (chip->is_open ? "open" : "closed")); +} + +static int tpm_tis_wait_init(struct udevice *dev, int loc) +{ + struct tpm_chip *chip = dev_get_priv(dev); + unsigned long start, stop; + u8 status; + int ret; + + start = get_timer(0); + stop = chip->timeout_b; + do { + mdelay(TPM_TIMEOUT_MS); + + ret = tpm_tis_spi_read(dev, TPM_ACCESS(loc), &status, 1); + if (ret) + break; + + if (status & TPM_ACCESS_VALID) + return 0; + } while (get_timer(start) < stop); + + return -EIO; +} + +static int tpm_tis_spi_probe(struct udevice *dev) +{ + struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev); + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); + struct tpm_chip *chip = dev_get_priv(dev); + int ret; + + if (IS_ENABLED(CONFIG_DM_GPIO)) { + struct gpio_desc reset_gpio; + + ret = gpio_request_by_name(dev, "gpio-reset", 0, + &reset_gpio, GPIOD_IS_OUT); + if (ret) { + log(LOGC_NONE, LOGL_NOTICE, "%s: missing reset GPIO\n", + __func__); + } else { + dm_gpio_set_value(&reset_gpio, 0); + mdelay(1); + dm_gpio_set_value(&reset_gpio, 1); + } + } + + /* Ensure a minimum amount of time elapsed since reset of the TPM */ + mdelay(drv_data->time_before_first_cmd_ms); + + chip->locality = 0; + 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; + priv->pcr_count = drv_data->pcr_count; + priv->pcr_select_min = drv_data->pcr_select_min; + + ret = tpm_tis_wait_init(dev, chip->locality); + if (ret) { + log(LOGC_DM, LOGL_ERR, "%s: no device found\n", __func__); + return ret; + } + + ret = tpm_tis_spi_request_locality(dev, chip->locality); + if (ret) { + log(LOGC_NONE, LOGL_ERR, "%s: could not request locality %d\n", + __func__, chip->locality); + return ret; + } + + ret = tpm_tis_spi_read32(dev, TPM_DID_VID(chip->locality), + &chip->vend_dev); + if (ret) { + log(LOGC_NONE, LOGL_ERR, + "%s: could not retrieve VendorID/DeviceID\n", __func__); + return ret; + } + + ret = tpm_tis_spi_read(dev, TPM_RID(chip->locality), &chip->rid, 1); + if (ret) { + log(LOGC_NONE, LOGL_ERR, "%s: could not retrieve RevisionID\n", + __func__); + return ret; + } + + log(LOGC_NONE, LOGL_ERR, + "SPI TPMv2.0 found (vid:%04x, did:%04x, rid:%02x)\n", + chip->vend_dev & 0xFFFF, chip->vend_dev >> 16, chip->rid); + + return 0; +} + +static int tpm_tis_spi_remove(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + + tpm_tis_spi_release_locality(dev, chip->locality, true); + + return 0; +} + +static const struct tpm_ops tpm_tis_spi_ops = { + .open = tpm_tis_spi_open, + .close = tpm_tis_spi_close, + .get_desc = tpm_tis_get_desc, + .send = tpm_tis_spi_send, + .recv = tpm_tis_spi_recv, + .cleanup = tpm_tis_spi_cleanup, +}; + +static const struct tpm_tis_chip_data tpm_tis_std_chip_data = { + .pcr_count = 24, + .pcr_select_min = 3, + .time_before_first_cmd_ms = 30, +}; + +static const struct udevice_id tpm_tis_spi_ids[] = { + { + .compatible = "tis,tpm2-spi", + .data = (ulong)&tpm_tis_std_chip_data, + }, + { } +}; + +U_BOOT_DRIVER(tpm_tis_spi) = { + .name = "tpm_tis_spi", + .id = UCLASS_TPM, + .of_match = tpm_tis_spi_ids, + .ops = &tpm_tis_spi_ops, + .probe = tpm_tis_spi_probe, + .remove = tpm_tis_spi_remove, + .priv_auto_alloc_size = sizeof(struct tpm_chip), +}; diff --git a/drivers/tpm/tpm_atmel_twi.c b/drivers/tpm/tpm_atmel_twi.c index 8547580c24..2079ea913e 100644 --- a/drivers/tpm/tpm_atmel_twi.c +++ b/drivers/tpm/tpm_atmel_twi.c @@ -7,7 +7,7 @@ #include <common.h> #include <dm.h> -#include <tpm.h> +#include <tpm-v1.h> #include <i2c.h> #include <asm/unaligned.h> diff --git a/drivers/tpm/tpm_tis.h b/drivers/tpm/tpm_tis.h index a899bc0b46..947585f8e3 100644 --- a/drivers/tpm/tpm_tis.h +++ b/drivers/tpm/tpm_tis.h @@ -40,6 +40,7 @@ struct tpm_chip { int is_open; int locality; u32 vend_dev; + u8 rid; unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ ulong chip_type; }; diff --git a/drivers/tpm/tpm_tis_infineon.c b/drivers/tpm/tpm_tis_infineon.c index 9b2a0250e1..b5fe43ee50 100644 --- a/drivers/tpm/tpm_tis_infineon.c +++ b/drivers/tpm/tpm_tis_infineon.c @@ -23,7 +23,7 @@ #include <dm.h> #include <fdtdec.h> #include <i2c.h> -#include <tpm.h> +#include <tpm-v1.h> #include <linux/errno.h> #include <linux/compiler.h> #include <linux/types.h> diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c index 572926382e..7664bb1a60 100644 --- a/drivers/tpm/tpm_tis_lpc.c +++ b/drivers/tpm/tpm_tis_lpc.c @@ -15,7 +15,7 @@ #include <common.h> #include <dm.h> #include <mapmem.h> -#include <tpm.h> +#include <tpm-v1.h> #include <asm/io.h> #define PREFIX "lpc_tpm: " diff --git a/drivers/tpm/tpm_tis_sandbox.c b/drivers/tpm/tpm_tis_sandbox.c index 44157542a1..8816d55759 100644 --- a/drivers/tpm/tpm_tis_sandbox.c +++ b/drivers/tpm/tpm_tis_sandbox.c @@ -5,7 +5,7 @@ #include <common.h> #include <dm.h> -#include <tpm.h> +#include <tpm-v1.h> #include <asm/state.h> #include <asm/unaligned.h> #include <linux/crc8.h> diff --git a/drivers/tpm/tpm_tis_st33zp24_i2c.c b/drivers/tpm/tpm_tis_st33zp24_i2c.c index 9cf302caff..0d380375eb 100644 --- a/drivers/tpm/tpm_tis_st33zp24_i2c.c +++ b/drivers/tpm/tpm_tis_st33zp24_i2c.c @@ -16,7 +16,7 @@ #include <dm.h> #include <fdtdec.h> #include <i2c.h> -#include <tpm.h> +#include <tpm-v1.h> #include <errno.h> #include <linux/types.h> #include <asm/unaligned.h> diff --git a/drivers/tpm/tpm_tis_st33zp24_spi.c b/drivers/tpm/tpm_tis_st33zp24_spi.c index d5fde11a83..f6087e7633 100644 --- a/drivers/tpm/tpm_tis_st33zp24_spi.c +++ b/drivers/tpm/tpm_tis_st33zp24_spi.c @@ -16,7 +16,7 @@ #include <dm.h> #include <fdtdec.h> #include <spi.h> -#include <tpm.h> +#include <tpm-v1.h> #include <errno.h> #include <linux/types.h> #include <asm/unaligned.h> |