diff options
-rw-r--r-- | src/drivers/crb/tis.c | 6 | ||||
-rw-r--r-- | src/drivers/i2c/tpm/cr50.c | 5 | ||||
-rw-r--r-- | src/drivers/i2c/tpm/tis.c | 4 | ||||
-rw-r--r-- | src/drivers/i2c/tpm/tis_atmel.c | 14 | ||||
-rw-r--r-- | src/drivers/i2c/tpm/tpm.c | 18 | ||||
-rw-r--r-- | src/drivers/i2c/tpm/tpm.h | 3 | ||||
-rw-r--r-- | src/drivers/pc80/tpm/tis.c | 39 | ||||
-rw-r--r-- | src/drivers/spi/tpm/tis.c | 6 | ||||
-rw-r--r-- | src/security/tpm/tis.h | 15 | ||||
-rw-r--r-- | src/security/tpm/tss/tcg-1.2/tss.c | 9 | ||||
-rw-r--r-- | src/security/tpm/tss/tcg-2.0/tss.c | 11 |
11 files changed, 99 insertions, 31 deletions
diff --git a/src/drivers/crb/tis.c b/src/drivers/crb/tis.c index a5d7dcc7ed..766ee25d95 100644 --- a/src/drivers/crb/tis.c +++ b/src/drivers/crb/tis.c @@ -46,7 +46,7 @@ static tpm_result_t crb_tpm_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, u return TPM_SUCCESS; } -tis_sendrecv_fn tis_probe(void) +tis_sendrecv_fn tis_probe(enum tpm_family *family) { struct tpm2_info info; @@ -54,6 +54,10 @@ tis_sendrecv_fn tis_probe(void) if (tpm2_init()) return NULL; + /* CRB interface exists only in TPM2 */ + if (family != NULL) + *family = TPM_2; + tpm2_get_info(&info); printk(BIOS_INFO, "Initialized TPM device %s revision %d\n", tis_get_dev_name(&info), diff --git a/src/drivers/i2c/tpm/cr50.c b/src/drivers/i2c/tpm/cr50.c index 8462198410..b58fbc8a67 100644 --- a/src/drivers/i2c/tpm/cr50.c +++ b/src/drivers/i2c/tpm/cr50.c @@ -424,8 +424,11 @@ static void cr50_vendor_init(struct tpm_chip *chip) chip->cancel = &cr50_i2c_tis_ready; } -tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr) +tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr, enum tpm_family *family) { + /* cr50 is TPM2 */ + if (family != NULL) + *family = TPM_2; return TPM_SUCCESS; } diff --git a/src/drivers/i2c/tpm/tis.c b/src/drivers/i2c/tpm/tis.c index 6cb05f0dd7..fd09240494 100644 --- a/src/drivers/i2c/tpm/tis.c +++ b/src/drivers/i2c/tpm/tis.c @@ -118,9 +118,9 @@ static tpm_result_t i2c_tpm_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, return TPM_SUCCESS; } -tis_sendrecv_fn tis_probe(void) +tis_sendrecv_fn tis_probe(enum tpm_family *family) { - if (tpm_vendor_probe(CONFIG_DRIVER_TPM_I2C_BUS, CONFIG_DRIVER_TPM_I2C_ADDR)) + if (tpm_vendor_probe(CONFIG_DRIVER_TPM_I2C_BUS, CONFIG_DRIVER_TPM_I2C_ADDR, family)) return NULL; if (tpm_vendor_init(&chip, CONFIG_DRIVER_TPM_I2C_BUS, CONFIG_DRIVER_TPM_I2C_ADDR)) diff --git a/src/drivers/i2c/tpm/tis_atmel.c b/src/drivers/i2c/tpm/tis_atmel.c index 0a29049d95..a0bbf33fc4 100644 --- a/src/drivers/i2c/tpm/tis_atmel.c +++ b/src/drivers/i2c/tpm/tis_atmel.c @@ -107,7 +107,19 @@ static tpm_result_t i2c_tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, return TPM_SUCCESS; } -tis_sendrecv_fn tis_probe(void) +tis_sendrecv_fn tis_probe(enum tpm_family *family) { + /* + * Can't query version or really anything as the device doesn't support + * much through this interface (can't specify address on accesses). + * + * Hence the assumption is that whatever TPM version is enabled at + * compile-time defines what the device supports. The check is written + * in a way to give TPM 1 preference even if support for both versions + * is compiled in. + */ + if (family != NULL) + *family = CONFIG(TPM1) ? TPM_1 : TPM_2; + return &i2c_tis_sendrecv; } diff --git a/src/drivers/i2c/tpm/tpm.c b/src/drivers/i2c/tpm/tpm.c index 541eb3aaa0..eb279844e8 100644 --- a/src/drivers/i2c/tpm/tpm.c +++ b/src/drivers/i2c/tpm/tpm.c @@ -451,13 +451,29 @@ out_err: /* Initialization of I2C TPM */ -tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr) +tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr, enum tpm_family *family) { struct stopwatch sw; uint8_t buf = 0; int ret; long sw_run_duration = SLEEP_DURATION_PROBE_MS; + /* + * Infineon "I2C Protocol Stack Specification v0.20" is supposedly a + * simple adoption of the LPC TIS Protocol to the I2C Bus, but looking + * at "TCG PC Client Specific TIS" doesn't confirm that and Infineon's + * specification isn't publicly available. + * + * Because it's unknown how to access information about TPM version of + * the device in this case, the assumption is that whatever TPM version + * is enabled at compile-time defines what the device supports. And + * since this driver doesn't appear to be used with TPM 2 devices, the + * check is written in a way to give TPM 1 preference even if support + * for both versions is compiled in. + */ + if (family != NULL) + *family = CONFIG(TPM1) ? TPM_1 : TPM_2; + tpm_dev.chip_type = UNKNOWN; tpm_dev.bus = bus; tpm_dev.addr = addr; diff --git a/src/drivers/i2c/tpm/tpm.h b/src/drivers/i2c/tpm/tpm.h index 628ad4dc69..46935e2495 100644 --- a/src/drivers/i2c/tpm/tpm.h +++ b/src/drivers/i2c/tpm/tpm.h @@ -12,6 +12,7 @@ #ifndef __DRIVERS_TPM_SLB9635_I2C_TPM_H__ #define __DRIVERS_TPM_SLB9635_I2C_TPM_H__ +#include <security/tpm/tis.h> #include <security/tpm/tss_errors.h> #include <stdint.h> @@ -51,7 +52,7 @@ struct tpm_chip { /* ---------- Interface for TPM vendor ------------ */ -tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr); +tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr, enum tpm_family *family); tpm_result_t tpm_vendor_init(struct tpm_chip *chip, unsigned int bus, uint32_t dev_addr); diff --git a/src/drivers/pc80/tpm/tis.c b/src/drivers/pc80/tpm/tis.c index 90fa32e318..da443d3a09 100644 --- a/src/drivers/pc80/tpm/tis.c +++ b/src/drivers/pc80/tpm/tis.c @@ -78,12 +78,6 @@ /* 1 second is plenty for anything TPM does.*/ #define MAX_DELAY_US USECS_PER_SEC -enum tpm_family { - TPM_UNKNOWN = 0, - TPM_1 = 1, - TPM_2 = 2, -}; - /* * Structures defined below allow creating descriptions of TPM vendor/device * ID information for run time discovery. @@ -380,8 +374,10 @@ static tpm_result_t tis_command_ready(u8 locality) * Returns TPM_SUCCESS on success (the device is found or was found during * an earlier invocation) or TPM_CB_FAIL if the device is not found. */ -static tpm_result_t pc80_tis_probe(void) +static tpm_result_t pc80_tis_probe(enum tpm_family *family) { + static enum tpm_family tpm_family; + const char *device_name = NULL; const char *vendor_name = NULL; const struct device_name *dev; @@ -389,11 +385,13 @@ static tpm_result_t pc80_tis_probe(void) u16 vid, did; u8 locality = 0, intf_type; int i; - enum tpm_family family; const char *family_str; - if (vendor_dev_id) + if (vendor_dev_id) { + if (family != NULL) + *family = tpm_family; return TPM_SUCCESS; /* Already probed. */ + } didvid = tpm_read_did_vid(0); if (!didvid || (didvid == 0xffffffff)) { @@ -409,10 +407,10 @@ static tpm_result_t pc80_tis_probe(void) switch (intf_version) { case 0: case 2: - family = TPM_1; + tpm_family = TPM_1; break; case 3: - family = TPM_2; + tpm_family = TPM_2; break; default: printf("%s: Unexpected TPM interface version: %d\n", __func__, @@ -420,7 +418,7 @@ static tpm_result_t pc80_tis_probe(void) return TPM_CB_PROBE_FAILURE; } } else if (intf_type == 0) { - family = TPM_2; + tpm_family = TPM_2; } else { printf("%s: Unexpected TPM interface type: %d\n", __func__, intf_type); return TPM_CB_PROBE_FAILURE; @@ -439,7 +437,7 @@ static tpm_result_t pc80_tis_probe(void) } dev = &vendor_names[i].dev_names[j]; while (dev->dev_id != 0xffff) { - if (dev->dev_id == did && dev->family == family) { + if (dev->dev_id == did && dev->family == tpm_family) { device_name = dev->dev_name; break; } @@ -449,7 +447,7 @@ static tpm_result_t pc80_tis_probe(void) break; } - family_str = (family == TPM_1 ? "TPM 1.2" : "TPM 2.0"); + family_str = (tpm_family == TPM_1 ? "TPM 1.2" : "TPM 2.0"); if (vendor_name == NULL) { printk(BIOS_INFO, "Found %s 0x%04x by 0x%04x\n", family_str, did, vid); } else if (device_name == NULL) { @@ -460,6 +458,8 @@ static tpm_result_t pc80_tis_probe(void) device_name, did, vendor_name, vid); } + if (family != NULL) + *family = tpm_family; return TPM_SUCCESS; } @@ -720,12 +720,15 @@ static tpm_result_t pc80_tpm_sendrecv(const uint8_t *sendbuf, size_t send_size, /* * tis_probe() * - * Probe for the TPM device and set it up for use within locality 0. Returns - * pointer to send-receive function on success or NULL on failure. + * Probe for the TPM device and set it up for use within locality 0. + * + * @tpm_family - pointer to tpm_family which is set to TPM family of the device. + * + * Returns pointer to send-receive function on success or NULL on failure. */ -tis_sendrecv_fn tis_probe(void) +tis_sendrecv_fn tis_probe(enum tpm_family *family) { - if (pc80_tis_probe()) + if (pc80_tis_probe(family)) return NULL; if (pc80_tis_open()) diff --git a/src/drivers/spi/tpm/tis.c b/src/drivers/spi/tpm/tis.c index 90d7f59ba9..89ea985da8 100644 --- a/src/drivers/spi/tpm/tis.c +++ b/src/drivers/spi/tpm/tis.c @@ -40,7 +40,7 @@ static tpm_result_t tpm_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, return TPM_SUCCESS; } -tis_sendrecv_fn tis_probe(void) +tis_sendrecv_fn tis_probe(enum tpm_family *family) { struct spi_slave spi; struct tpm2_info info; @@ -56,6 +56,10 @@ tis_sendrecv_fn tis_probe(void) return NULL; } + /* tpm2_process_command() is used unconditionally in tpm_sendrecv() */ + if (family != NULL) + *family = TPM_2; + tpm2_get_info(&info); printk(BIOS_INFO, "Initialized TPM device %s revision %d\n", diff --git a/src/security/tpm/tis.h b/src/security/tpm/tis.h index ac07bfb5c6..4a8dc14c31 100644 --- a/src/security/tpm/tis.h +++ b/src/security/tpm/tis.h @@ -32,6 +32,12 @@ enum tis_status { TPM_STS_RESPONSE_RETRY = (1 << 1), }; +enum tpm_family { + TPM_UNKNOWN = 0, + TPM_1 = 1, + TPM_2 = 2, +}; + /* * tis_sendrecv() * @@ -50,13 +56,16 @@ typedef tpm_result_t (*tis_sendrecv_fn)(const u8 *sendbuf, size_t send_size, u8 /* * tis_probe() * - * Probe for the TPM device and set it up for use within locality 0. Returns - * pointer to send-receive function on success or NULL on failure. + * Probe for the TPM device and set it up for use within locality 0. + * + * @family - pointer which is set to TPM family of the device + * + * Returns pointer to send-receive function on success or NULL on failure. * * Do not call this explicitly, it's meant to be used exclusively by TSS * implementation (tlcl_lib_init() function to be specific). */ -tis_sendrecv_fn tis_probe(void); +tis_sendrecv_fn tis_probe(enum tpm_family *family); /* * tis_vendor_write() diff --git a/src/security/tpm/tss/tcg-1.2/tss.c b/src/security/tpm/tss/tcg-1.2/tss.c index f0d28dfe3f..913f79b106 100644 --- a/src/security/tpm/tss/tcg-1.2/tss.c +++ b/src/security/tpm/tss/tcg-1.2/tss.c @@ -153,13 +153,20 @@ static tpm_result_t send(const uint8_t *command) tpm_result_t tlcl_lib_init(void) { + enum tpm_family family; + if (tis_sendrecv != NULL) return TPM_SUCCESS; - tis_sendrecv = tis_probe(); + tis_sendrecv = tis_probe(&family); if (tis_sendrecv == NULL) return TPM_CB_NO_DEVICE; + if (family != TPM_1) { + tis_sendrecv = NULL; + return TPM_CB_INTERNAL_INCONSISTENCY; + } + return TPM_SUCCESS; } diff --git a/src/security/tpm/tss/tcg-2.0/tss.c b/src/security/tpm/tss/tcg-2.0/tss.c index 135d2964e6..27390a78ab 100644 --- a/src/security/tpm/tss/tcg-2.0/tss.c +++ b/src/security/tpm/tss/tcg-2.0/tss.c @@ -211,15 +211,24 @@ tpm_result_t tlcl_clear_control(bool disable) /* This function is called directly by vboot, uses vboot return types. */ tpm_result_t tlcl_lib_init(void) { + enum tpm_family family; + if (tis_sendrecv != NULL) return TPM_SUCCESS; - tis_sendrecv = tis_probe(); + tis_sendrecv = tis_probe(&family); if (tis_sendrecv == NULL) { printk(BIOS_ERR, "%s: tis_probe returned error\n", __func__); return TPM_CB_NO_DEVICE; } + if (family != TPM_2) { + tis_sendrecv = NULL; + printk(BIOS_ERR, "%s: tis_probe returned unsupported TPM family: %d\n", + __func__, family); + return TPM_CB_INTERNAL_INCONSISTENCY; + } + return TPM_SUCCESS; } |