aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2015-02-04 09:21:09 -0500
committerPeter Huewe <peterhuewe@gmx.de>2015-02-15 10:59:15 -0500
commit4d5f2051cd24adc19a645e920344e05afe8d69b9 (patch)
treec6397680572adf9968f4839e290bf2e048596e01
parent74d6b3ceaa17d111220c3f09f50f901bf955d7c8 (diff)
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);
435extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); 435extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
436extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); 436extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
437extern int tpm2_do_selftest(struct tpm_chip *chip); 437extern int tpm2_do_selftest(struct tpm_chip *chip);
438extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet); 438extern int tpm2_gen_interrupt(struct tpm_chip *chip);
439extern 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);
601/** 601/**
602 * tpm2_gen_interrupt() - generate an interrupt 602 * tpm2_gen_interrupt() - generate an interrupt
603 * @chip: TPM chip to use 603 * @chip: TPM chip to use
604 * @quiet: surpress the error message
605 * 604 *
606 * 0 is returned when the operation is successful. If a negative number is 605 * 0 is returned when the operation is successful. If a negative number is
607 * returned it remarks a POSIX error code. If a positive number is returned 606 * returned it remarks a POSIX error code. If a positive number is returned
608 * it remarks a TPM error. 607 * it remarks a TPM error.
609 */ 608 */
610int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet) 609int tpm2_gen_interrupt(struct tpm_chip *chip)
611{ 610{
612 const char *desc = NULL;
613 u32 dummy; 611 u32 dummy;
614 612
615 if (!quiet) 613 return tpm2_get_tpm_pt(chip, 0x100, &dummy,
616 desc = "attempting to generate an interrupt"; 614 "attempting to generate an interrupt");
617
618 return tpm2_get_tpm_pt(chip, TPM2_CAP_TPM_PROPERTIES, &dummy, desc);
619} 615}
620EXPORT_SYMBOL_GPL(tpm2_gen_interrupt); 616EXPORT_SYMBOL_GPL(tpm2_gen_interrupt);
617
618/**
619 * tpm2_probe() - probe TPM 2.0
620 * @chip: TPM chip to use
621 *
622 * Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based on
623 * the reply tag.
624 */
625int tpm2_probe(struct tpm_chip *chip)
626{
627 struct tpm2_cmd cmd;
628 int rc;
629
630 cmd.header.in = tpm2_get_tpm_pt_header;
631 cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
632 cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
633 cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
634
635 rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd));
636 if (rc < 0)
637 return rc;
638 else if (rc < TPM_HEADER_SIZE)
639 return -EFAULT;
640
641 if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS)
642 chip->flags |= TPM_CHIP_FLAG_TPM2;
643
644 return 0;
645}
646EXPORT_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,
642 goto out_err; 642 goto out_err;
643 } 643 }
644 644
645 /* Every TPM 2.x command has a higher ordinal than TPM 1.x commands. 645 rc = tpm2_probe(chip);
646 * Therefore, we can use an idempotent TPM 2.x command to probe TPM 2.x. 646 if (rc)
647 */ 647 goto out_err;
648 rc = tpm2_gen_interrupt(chip, true);
649 if (rc == 0 || rc == TPM2_RC_INITIALIZE)
650 chip->flags |= TPM_CHIP_FLAG_TPM2;
651 648
652 vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); 649 vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
653 chip->vendor.manufacturer_id = vendor; 650 chip->vendor.manufacturer_id = vendor;
@@ -750,7 +747,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
750 747
751 /* Generate Interrupts */ 748 /* Generate Interrupts */
752 if (chip->flags & TPM_CHIP_FLAG_TPM2) 749 if (chip->flags & TPM_CHIP_FLAG_TPM2)
753 tpm2_gen_interrupt(chip, false); 750 tpm2_gen_interrupt(chip);
754 else 751 else
755 tpm_gen_interrupt(chip); 752 tpm_gen_interrupt(chip);
756 753