summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2015-02-04 16:21:09 +0200
committerPeter Huewe <peterhuewe@gmx.de>2015-02-15 16:59:15 +0100
commit4d5f2051cd24adc19a645e920344e05afe8d69b9 (patch)
treec6397680572adf9968f4839e290bf2e048596e01
parent74d6b3ceaa17d111220c3f09f50f901bf955d7c8 (diff)
downloadlinux-4d5f2051cd24adc19a645e920344e05afe8d69b9.tar.bz2
tpm, tpm_tis: fix TPM 2.0 probing
If during transmission system error was returned, the logic was to incorrectly deduce that chip is a TPM 1.x chip. This patch fixes this issue. Also, this patch changes probing so that message tag is used as the measure for TPM 2.x, which should be much more stable. A separate function called tpm2_probe() is encapsulated because it can be used with any chipset. Fixes: aec04cbdf723 ("tpm: TPM 2.0 FIFO Interface") Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Reviewed-by: Peter Huewe <peterhuewe@gmx.de> Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
-rw-r--r--drivers/char/tpm/tpm.h3
-rw-r--r--drivers/char/tpm/tpm2-cmd.c40
-rw-r--r--drivers/char/tpm/tpm_tis.c11
3 files changed, 39 insertions, 15 deletions
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index a2ce3797e3e0..f8319a0860fd 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -435,4 +435,5 @@ extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type);
extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
extern int tpm2_do_selftest(struct tpm_chip *chip);
-extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet);
+extern int tpm2_gen_interrupt(struct tpm_chip *chip);
+extern int tpm2_probe(struct tpm_chip *chip);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index f2f38a5ee632..011909a9be96 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -601,20 +601,46 @@ EXPORT_SYMBOL_GPL(tpm2_do_selftest);
/**
* tpm2_gen_interrupt() - generate an interrupt
* @chip: TPM chip to use
- * @quiet: surpress the error message
*
* 0 is returned when the operation is successful. If a negative number is
* returned it remarks a POSIX error code. If a positive number is returned
* it remarks a TPM error.
*/
-int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet)
+int tpm2_gen_interrupt(struct tpm_chip *chip)
{
- const char *desc = NULL;
u32 dummy;
- if (!quiet)
- desc = "attempting to generate an interrupt";
-
- return tpm2_get_tpm_pt(chip, TPM2_CAP_TPM_PROPERTIES, &dummy, desc);
+ return tpm2_get_tpm_pt(chip, 0x100, &dummy,
+ "attempting to generate an interrupt");
}
EXPORT_SYMBOL_GPL(tpm2_gen_interrupt);
+
+/**
+ * tpm2_probe() - probe TPM 2.0
+ * @chip: TPM chip to use
+ *
+ * Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based on
+ * the reply tag.
+ */
+int tpm2_probe(struct tpm_chip *chip)
+{
+ struct tpm2_cmd cmd;
+ int rc;
+
+ cmd.header.in = tpm2_get_tpm_pt_header;
+ cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
+ cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
+ cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
+
+ rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd));
+ if (rc < 0)
+ return rc;
+ else if (rc < TPM_HEADER_SIZE)
+ return -EFAULT;
+
+ if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS)
+ chip->flags |= TPM_CHIP_FLAG_TPM2;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tpm2_probe);
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index e12b3ab215cf..f2dffa770b8e 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -642,12 +642,9 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
goto out_err;
}
- /* Every TPM 2.x command has a higher ordinal than TPM 1.x commands.
- * Therefore, we can use an idempotent TPM 2.x command to probe TPM 2.x.
- */
- rc = tpm2_gen_interrupt(chip, true);
- if (rc == 0 || rc == TPM2_RC_INITIALIZE)
- chip->flags |= TPM_CHIP_FLAG_TPM2;
+ rc = tpm2_probe(chip);
+ if (rc)
+ goto out_err;
vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
chip->vendor.manufacturer_id = vendor;
@@ -750,7 +747,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
/* Generate Interrupts */
if (chip->flags & TPM_CHIP_FLAG_TPM2)
- tpm2_gen_interrupt(chip, false);
+ tpm2_gen_interrupt(chip);
else
tpm_gen_interrupt(chip);