diff mbox

[tpmdd-devel,v9,8/8] tpm: TPM 2.0 FIFO Interface

Message ID 1417672518-4530-9-git-send-email-jarkko.sakkinen@linux.intel.com
State Superseded, archived
Headers show

Commit Message

Jarkko Sakkinen Dec. 4, 2014, 5:55 a.m. UTC
From: Will Arthur <will.c.arthur@intel.com>

Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
instead of calling tpm_get_timeouts(), assign duration and timeout
values defined in the TPM 2.0 PTP specification.

Signed-off-by: Will Arthur <will.c.arthur@intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/char/tpm/tpm_tis.c | 80 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 67 insertions(+), 13 deletions(-)

Comments

Scot Doyle Dec. 4, 2014, 3:25 p.m. UTC | #1
Hi Jarkko,

On Thu, 4 Dec 2014, Jarkko Sakkinen wrote:
> From: Will Arthur <will.c.arthur@intel.com>
> 
> Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
> instead of calling tpm_get_timeouts(), assign duration and timeout
> values defined in the TPM 2.0 PTP specification.
> 
> Signed-off-by: Will Arthur <will.c.arthur@intel.com>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> ---
>  drivers/char/tpm/tpm_tis.c | 80 ++++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 67 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> index 89e1abb..71cbb2d 100644
> --- a/drivers/char/tpm/tpm_tis.c
> +++ b/drivers/char/tpm/tpm_tis.c
> @@ -1,5 +1,6 @@
>  /*
>   * Copyright (C) 2005, 2006 IBM Corporation
> + * Copyright (C) 2014 Intel Corporation
>   *
>   * Authors:
>   * Leendert van Doorn <leendert@watson.ibm.com>
> @@ -44,6 +45,10 @@ enum tis_status {
>  	TPM_STS_DATA_EXPECT = 0x08,
>  };
>  
> +enum tis_status3 {
> +	TPM_STS3_TPM2_FAM = 0x04,
> +};
> +
>  enum tis_int_flags {
>  	TPM_GLOBAL_INT_ENABLE = 0x80000000,
>  	TPM_INTF_BURST_COUNT_STATIC = 0x100,
> @@ -70,6 +75,7 @@ enum tis_defaults {
>  #define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
>  #define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
>  #define	TPM_STS(l)			(0x0018 | ((l) << 12))
> +#define	TPM_STS3(l)			(0x001b | ((l) << 12))
>  #define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
>  
>  #define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
> @@ -363,6 +369,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
>  {
>  	int rc;
>  	u32 ordinal;
> +	unsigned long dur;
>  
>  	rc = tpm_tis_send_data(chip, buf, len);
>  	if (rc < 0)
> @@ -374,9 +381,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
>  
>  	if (chip->vendor.irq) {
>  		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
> +
> +		if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +			dur = tpm2_calc_ordinal_duration(chip, ordinal);
> +		else
> +			dur = tpm_calc_ordinal_duration(chip, ordinal);
> +
>  		if (wait_for_tpm_stat
> -		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> -		     tpm_calc_ordinal_duration(chip, ordinal),
> +		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
>  		     &chip->vendor.read_queue, false) < 0) {
>  			rc = -ETIME;
>  			goto out_err;
> @@ -588,6 +600,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
>  	int rc, i, irq_s, irq_e, probe;
>  	struct tpm_chip *chip;
>  	struct priv_data *priv;
> +	u8 sts3;
>  
>  	priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
>  	if (priv == NULL)
> @@ -604,11 +617,28 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
>  	if (!chip->vendor.iobase)
>  		return -EIO;
>  
> +	sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1));
> +	if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM)
> +		chip->flags = TPM_CHIP_FLAG_TPM2;
> +
>  	/* Default timeouts */
> -	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> -	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
> -	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> -	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> +		chip->vendor.timeout_a = usecs_to_jiffies(TPM2_TIMEOUT_A);
> +		chip->vendor.timeout_b = usecs_to_jiffies(TPM2_TIMEOUT_B);
> +		chip->vendor.timeout_c = usecs_to_jiffies(TPM2_TIMEOUT_C);
> +		chip->vendor.timeout_d = usecs_to_jiffies(TPM2_TIMEOUT_D);
> +		chip->vendor.duration[TPM_SHORT] =
> +			usecs_to_jiffies(TPM2_DURATION_SHORT);
> +		chip->vendor.duration[TPM_MEDIUM] =
> +			usecs_to_jiffies(TPM2_DURATION_MEDIUM);
> +		chip->vendor.duration[TPM_LONG] =
> +			usecs_to_jiffies(TPM2_DURATION_LONG);
> +	} else {
> +		chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +		chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
> +		chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +		chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +	}
>  
>  	if (wait_startup(chip, 0) != 0) {
>  		rc = -ENODEV;
> @@ -623,8 +653,8 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
>  	vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
>  	chip->vendor.manufacturer_id = vendor;
>  
> -	dev_info(dev,
> -		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
> +	dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
> +		 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
>  		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
>  
>  	if (!itpm) {
> @@ -665,6 +695,23 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
>  	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
>  		dev_dbg(dev, "\tData Avail Int Support\n");
>  
> +	/* get the timeouts before testing for irqs */
> +	if (!(chip->flags & TPM_CHIP_FLAG_TPM2) && tpm_get_timeouts(chip)) {
> +		dev_err(dev, "Could not get TPM timeouts and durations\n");
> +		rc = -ENODEV;
> +		goto out_err;
> +	}
> +
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +		rc = tpm2_do_selftest(chip);
> +	else
> +		rc = tpm_do_selftest(chip);
> +	if (rc) {
> +		dev_err(dev, "TPM self test failed\n");
> +		rc = -ENODEV;
> +		goto out_err;
> +	}
> +
>  	/* INTERRUPT Setup */
>  	init_waitqueue_head(&chip->vendor.read_queue);
>  	init_waitqueue_head(&chip->vendor.int_queue);

In Peter's for-james branch, commit 0e6cb01, the v1.2 calls to
tpm_get_timeouts and tpm_do_selftest were moved toward the end of 
tpm_tis_init.


> @@ -720,7 +767,10 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
>  			chip->vendor.probed_irq = 0;
>  
>  			/* Generate Interrupts */
> -			tpm_gen_interrupt(chip);
> +			if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +				tpm2_gen_interrupt(chip);
> +			else
> +				tpm_gen_interrupt(chip);
>  
>  			chip->vendor.irq = chip->vendor.probed_irq;
>  
> @@ -808,14 +858,18 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
>  static int tpm_tis_resume(struct device *dev)
>  {
>  	struct tpm_chip *chip = dev_get_drvdata(dev);
> -	int ret;
> +	int ret = 0;
>  
>  	if (chip->vendor.irq)
>  		tpm_tis_reenable_interrupts(chip);
>  
> -	ret = tpm_pm_resume(dev);
> -	if (!ret)
> -		tpm_do_selftest(chip);
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +		tpm2_do_selftest(chip);
> +	else {
> +		ret = tpm_pm_resume(dev);
> +		if (!ret)
> +			tpm_do_selftest(chip);
> +	}
>  
>  	return ret;
>  }
> -- 
> 2.1.0
> 

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Peter Hüwe Dec. 4, 2014, 9:46 p.m. UTC | #2
Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen:
> From: Will Arthur <will.c.arthur@intel.com>
> 
> Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
> instead of calling tpm_get_timeouts(), assign duration and timeout
> values defined in the TPM 2.0 PTP specification.
> 
> Signed-off-by: Will Arthur <will.c.arthur@intel.com>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> ---
Should we change the KConfig string?
 TPM Interface Specification 1.2 Interface
is not quite accurate anymore after applying this patch.

Thanks,
Peter

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Peter Hüwe Dec. 4, 2014, 10:18 p.m. UTC | #3
Hi Jarkko,

Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen:
> From: Will Arthur <will.c.arthur@intel.com>
> 
> Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
> instead of calling tpm_get_timeouts(), assign duration and timeout
> values defined in the TPM 2.0 PTP specification.
> 
> Signed-off-by: Will Arthur <will.c.arthur@intel.com>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> ---
>  drivers/char/tpm/tpm_tis.c | 80
> ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 67
> insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> index 89e1abb..71cbb2d 100644
> --- a/drivers/char/tpm/tpm_tis.c
> +++ b/drivers/char/tpm/tpm_tis.c
> @@ -1,5 +1,6 @@
>  /*
>   * Copyright (C) 2005, 2006 IBM Corporation
> + * Copyright (C) 2014 Intel Corporation
>   *
>   * Authors:
>   * Leendert van Doorn <leendert@watson.ibm.com>
> @@ -44,6 +45,10 @@ enum tis_status {
>  	TPM_STS_DATA_EXPECT = 0x08,
>  };
> 
> +enum tis_status3 {
> +	TPM_STS3_TPM2_FAM = 0x04,
> +};
> +
>  enum tis_int_flags {
>  	TPM_GLOBAL_INT_ENABLE = 0x80000000,
>  	TPM_INTF_BURST_COUNT_STATIC = 0x100,
> @@ -70,6 +75,7 @@ enum tis_defaults {
>  #define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
>  #define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
>  #define	TPM_STS(l)			(0x0018 | ((l) << 12))
> +#define	TPM_STS3(l)			(0x001b | ((l) << 12))
>  #define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
> 
>  #define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
> @@ -363,6 +369,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8
> *buf, size_t len) {
>  	int rc;
>  	u32 ordinal;
> +	unsigned long dur;
> 
>  	rc = tpm_tis_send_data(chip, buf, len);
>  	if (rc < 0)
> @@ -374,9 +381,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8
> *buf, size_t len)
> 
>  	if (chip->vendor.irq) {
>  		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
> +
> +		if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +			dur = tpm2_calc_ordinal_duration(chip, ordinal);
> +		else
> +			dur = tpm_calc_ordinal_duration(chip, ordinal);
> +
>  		if (wait_for_tpm_stat
> -		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> -		     tpm_calc_ordinal_duration(chip, ordinal),
> +		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
>  		     &chip->vendor.read_queue, false) < 0) {
>  			rc = -ETIME;
>  			goto out_err;
> @@ -588,6 +600,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle
> acpi_dev_handle, int rc, i, irq_s, irq_e, probe;
>  	struct tpm_chip *chip;
>  	struct priv_data *priv;
> +	u8 sts3;
> 
>  	priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
>  	if (priv == NULL)
> @@ -604,11 +617,28 @@ static int tpm_tis_init(struct device *dev,
> acpi_handle acpi_dev_handle, if (!chip->vendor.iobase)
>  		return -EIO;
> 
> +	sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1));
> +	if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM)
> +		chip->flags = TPM_CHIP_FLAG_TPM2;
> +
>  	/* Default timeouts */
> -	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> -	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
> -	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> -	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> +		chip->vendor.timeout_a = usecs_to_jiffies(TPM2_TIMEOUT_A);
> +		chip->vendor.timeout_b = usecs_to_jiffies(TPM2_TIMEOUT_B);
> +		chip->vendor.timeout_c = usecs_to_jiffies(TPM2_TIMEOUT_C);
> +		chip->vendor.timeout_d = usecs_to_jiffies(TPM2_TIMEOUT_D);
> +		chip->vendor.duration[TPM_SHORT] =
> +			usecs_to_jiffies(TPM2_DURATION_SHORT);
> +		chip->vendor.duration[TPM_MEDIUM] =
> +			usecs_to_jiffies(TPM2_DURATION_MEDIUM);
> +		chip->vendor.duration[TPM_LONG] =
> +			usecs_to_jiffies(TPM2_DURATION_LONG);
> +	} else {
> +		chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +		chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
> +		chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +		chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +	}
> 
>  	if (wait_startup(chip, 0) != 0) {
>  		rc = -ENODEV;
> @@ -623,8 +653,8 @@ static int tpm_tis_init(struct device *dev, acpi_handle
> acpi_dev_handle, vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
>  	chip->vendor.manufacturer_id = vendor;
> 
> -	dev_info(dev,
> -		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
> +	dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
> +		 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
>  		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
> 


When loading tpm_tis force=1 with my tpm1.2 chip on a machine without bios 
integration, it fets detected as a TPM2.0 chip :/

sudo rmmod tpm_tis
# modprobe tpm_tis force=1
modprobe: ERROR: could not insert 'tpm_tis': No such device
# dmesg 
[  263.903828] tpm_tis tpm_tis: 2.0 TPM (device-id 0xB, rev-id 16)
[  263.948049] tpm_tis tpm_tis: A TPM error (10) occurred continue selftest
[  263.948120] tpm_tis tpm_tis: TPM self test failed


sts3 is reported as 0xff from my TPM1.2

Thanks,
Peter



------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Peter Hüwe Dec. 4, 2014, 10:28 p.m. UTC | #4
Am Donnerstag, 4. Dezember 2014, 23:18:33 schrieb Peter Hüwe:
> Hi Jarkko,
> 
> Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen:
> > From: Will Arthur <will.c.arthur@intel.com>
> > 
> > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
> > instead of calling tpm_get_timeouts(), assign duration and timeout
> > values defined in the TPM 2.0 PTP specification.
> > 
> > Signed-off-by: Will Arthur <will.c.arthur@intel.com>
> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > ---
> > 
> >  drivers/char/tpm/tpm_tis.c | 80
> > 
> > ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 67
> > insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> > index 89e1abb..71cbb2d 100644
> > --- a/drivers/char/tpm/tpm_tis.c
> > +++ b/drivers/char/tpm/tpm_tis.c
> > @@ -1,5 +1,6 @@
> > 
> >  /*
> >  
> >   * Copyright (C) 2005, 2006 IBM Corporation
> > 
> > + * Copyright (C) 2014 Intel Corporation
> > 
> >   *
> >   * Authors:
> >   * Leendert van Doorn <leendert@watson.ibm.com>
> > 
> > @@ -44,6 +45,10 @@ enum tis_status {
> > 
> >  	TPM_STS_DATA_EXPECT = 0x08,
> >  
> >  };
> > 
> > +enum tis_status3 {
> > +	TPM_STS3_TPM2_FAM = 0x04,
> > +};
> > +
> > 
> >  enum tis_int_flags {
> >  
> >  	TPM_GLOBAL_INT_ENABLE = 0x80000000,
> >  	TPM_INTF_BURST_COUNT_STATIC = 0x100,
> > 
> > @@ -70,6 +75,7 @@ enum tis_defaults {
> > 
> >  #define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
> >  #define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
> >  #define	TPM_STS(l)			(0x0018 | ((l) << 12))
> > 
> > +#define	TPM_STS3(l)			(0x001b | ((l) << 12))
> > 
> >  #define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
> >  
> >  #define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
> > 
> > @@ -363,6 +369,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip,
> > u8 *buf, size_t len) {
> > 
> >  	int rc;
> >  	u32 ordinal;
> > 
> > +	unsigned long dur;
> > 
> >  	rc = tpm_tis_send_data(chip, buf, len);
> >  	if (rc < 0)
> > 
> > @@ -374,9 +381,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip,
> > u8 *buf, size_t len)
> > 
> >  	if (chip->vendor.irq) {
> >  	
> >  		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
> > 
> > +
> > +		if (chip->flags & TPM_CHIP_FLAG_TPM2)
> > +			dur = tpm2_calc_ordinal_duration(chip, ordinal);
> > +		else
> > +			dur = tpm_calc_ordinal_duration(chip, ordinal);
> > +
> > 
> >  		if (wait_for_tpm_stat
> > 
> > -		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> > -		     tpm_calc_ordinal_duration(chip, ordinal),
> > +		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
> > 
> >  		     &chip->vendor.read_queue, false) < 0) {
> >  			
> >  			rc = -ETIME;
> >  			goto out_err;
> > 
> > @@ -588,6 +600,7 @@ static int tpm_tis_init(struct device *dev,
> > acpi_handle acpi_dev_handle, int rc, i, irq_s, irq_e, probe;
> > 
> >  	struct tpm_chip *chip;
> >  	struct priv_data *priv;
> > 
> > +	u8 sts3;
> > 
> >  	priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
> >  	if (priv == NULL)
> > 
> > @@ -604,11 +617,28 @@ static int tpm_tis_init(struct device *dev,
> > acpi_handle acpi_dev_handle, if (!chip->vendor.iobase)
> > 
> >  		return -EIO;
> > 
> > +	sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1));
> > +	if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM)
> > +		chip->flags = TPM_CHIP_FLAG_TPM2;
> > +
> > 
> >  	/* Default timeouts */
> > 
> > -	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > -	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
> > -	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > -	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > +	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> > +		chip->vendor.timeout_a = usecs_to_jiffies(TPM2_TIMEOUT_A);
> > +		chip->vendor.timeout_b = usecs_to_jiffies(TPM2_TIMEOUT_B);
> > +		chip->vendor.timeout_c = usecs_to_jiffies(TPM2_TIMEOUT_C);
> > +		chip->vendor.timeout_d = usecs_to_jiffies(TPM2_TIMEOUT_D);
> > +		chip->vendor.duration[TPM_SHORT] =
> > +			usecs_to_jiffies(TPM2_DURATION_SHORT);
> > +		chip->vendor.duration[TPM_MEDIUM] =
> > +			usecs_to_jiffies(TPM2_DURATION_MEDIUM);
> > +		chip->vendor.duration[TPM_LONG] =
> > +			usecs_to_jiffies(TPM2_DURATION_LONG);
> > +	} else {
> > +		chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > +		chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
> > +		chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > +		chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > +	}
> > 
> >  	if (wait_startup(chip, 0) != 0) {
> >  	
> >  		rc = -ENODEV;
> > 
> > @@ -623,8 +653,8 @@ static int tpm_tis_init(struct device *dev,
> > acpi_handle acpi_dev_handle, vendor = ioread32(chip->vendor.iobase +
> > TPM_DID_VID(0));
> > 
> >  	chip->vendor.manufacturer_id = vendor;
> > 
> > -	dev_info(dev,
> > -		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
> > +	dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
> > +		 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
> > 
> >  		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
> 
> When loading tpm_tis force=1 with my tpm1.2 chip on a machine without bios
> integration, it fets detected as a TPM2.0 chip :/
> 
> sudo rmmod tpm_tis
> # modprobe tpm_tis force=1
> modprobe: ERROR: could not insert 'tpm_tis': No such device
> # dmesg
> [  263.903828] tpm_tis tpm_tis: 2.0 TPM (device-id 0xB, rev-id 16)
> [  263.948049] tpm_tis tpm_tis: A TPM error (10) occurred continue selftest
> [  263.948120] tpm_tis tpm_tis: TPM self test failed
> 
> 
> sts3 is reported as 0xff from my TPM1.2
> 


Hmm,
my TPM2.0 chip also reports sts3 as 0xff (when loading with force=1 on a 
machine without bios integration)

[  307.095344] sts3 ff
[  307.095366] tpm_tis tpm_tis: 2.0 TPM (device-id 0x1A, rev-id 16)
[  307.140047] tpm_tis tpm_tis: A TPM error (256) occurred continue selftest
[  307.140056] tpm_tis tpm_tis: TPM self test failed




Peter

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Jarkko Sakkinen Dec. 5, 2014, 1:05 p.m. UTC | #5
On Thu, Dec 04, 2014 at 03:25:12PM +0000, Scot Doyle wrote:
> Hi Jarkko,
> 
> On Thu, 4 Dec 2014, Jarkko Sakkinen wrote:
> > From: Will Arthur <will.c.arthur@intel.com>
> > 
> > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
> > instead of calling tpm_get_timeouts(), assign duration and timeout
> > values defined in the TPM 2.0 PTP specification.
> > 
> > Signed-off-by: Will Arthur <will.c.arthur@intel.com>
> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > ---
> >  drivers/char/tpm/tpm_tis.c | 80 ++++++++++++++++++++++++++++++++++++++--------
> >  1 file changed, 67 insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> > index 89e1abb..71cbb2d 100644
> > --- a/drivers/char/tpm/tpm_tis.c
> > +++ b/drivers/char/tpm/tpm_tis.c
> > @@ -1,5 +1,6 @@
> >  /*
> >   * Copyright (C) 2005, 2006 IBM Corporation
> > + * Copyright (C) 2014 Intel Corporation
> >   *
> >   * Authors:
> >   * Leendert van Doorn <leendert@watson.ibm.com>
> > @@ -44,6 +45,10 @@ enum tis_status {
> >  	TPM_STS_DATA_EXPECT = 0x08,
> >  };
> >  
> > +enum tis_status3 {
> > +	TPM_STS3_TPM2_FAM = 0x04,
> > +};
> > +
> >  enum tis_int_flags {
> >  	TPM_GLOBAL_INT_ENABLE = 0x80000000,
> >  	TPM_INTF_BURST_COUNT_STATIC = 0x100,
> > @@ -70,6 +75,7 @@ enum tis_defaults {
> >  #define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
> >  #define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
> >  #define	TPM_STS(l)			(0x0018 | ((l) << 12))
> > +#define	TPM_STS3(l)			(0x001b | ((l) << 12))
> >  #define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
> >  
> >  #define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
> > @@ -363,6 +369,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
> >  {
> >  	int rc;
> >  	u32 ordinal;
> > +	unsigned long dur;
> >  
> >  	rc = tpm_tis_send_data(chip, buf, len);
> >  	if (rc < 0)
> > @@ -374,9 +381,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
> >  
> >  	if (chip->vendor.irq) {
> >  		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
> > +
> > +		if (chip->flags & TPM_CHIP_FLAG_TPM2)
> > +			dur = tpm2_calc_ordinal_duration(chip, ordinal);
> > +		else
> > +			dur = tpm_calc_ordinal_duration(chip, ordinal);
> > +
> >  		if (wait_for_tpm_stat
> > -		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> > -		     tpm_calc_ordinal_duration(chip, ordinal),
> > +		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
> >  		     &chip->vendor.read_queue, false) < 0) {
> >  			rc = -ETIME;
> >  			goto out_err;
> > @@ -588,6 +600,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
> >  	int rc, i, irq_s, irq_e, probe;
> >  	struct tpm_chip *chip;
> >  	struct priv_data *priv;
> > +	u8 sts3;
> >  
> >  	priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
> >  	if (priv == NULL)
> > @@ -604,11 +617,28 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
> >  	if (!chip->vendor.iobase)
> >  		return -EIO;
> >  
> > +	sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1));
> > +	if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM)
> > +		chip->flags = TPM_CHIP_FLAG_TPM2;
> > +
> >  	/* Default timeouts */
> > -	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > -	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
> > -	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > -	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > +	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> > +		chip->vendor.timeout_a = usecs_to_jiffies(TPM2_TIMEOUT_A);
> > +		chip->vendor.timeout_b = usecs_to_jiffies(TPM2_TIMEOUT_B);
> > +		chip->vendor.timeout_c = usecs_to_jiffies(TPM2_TIMEOUT_C);
> > +		chip->vendor.timeout_d = usecs_to_jiffies(TPM2_TIMEOUT_D);
> > +		chip->vendor.duration[TPM_SHORT] =
> > +			usecs_to_jiffies(TPM2_DURATION_SHORT);
> > +		chip->vendor.duration[TPM_MEDIUM] =
> > +			usecs_to_jiffies(TPM2_DURATION_MEDIUM);
> > +		chip->vendor.duration[TPM_LONG] =
> > +			usecs_to_jiffies(TPM2_DURATION_LONG);
> > +	} else {
> > +		chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > +		chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
> > +		chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > +		chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> > +	}
> >  
> >  	if (wait_startup(chip, 0) != 0) {
> >  		rc = -ENODEV;
> > @@ -623,8 +653,8 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
> >  	vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
> >  	chip->vendor.manufacturer_id = vendor;
> >  
> > -	dev_info(dev,
> > -		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
> > +	dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
> > +		 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
> >  		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
> >  
> >  	if (!itpm) {
> > @@ -665,6 +695,23 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
> >  	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
> >  		dev_dbg(dev, "\tData Avail Int Support\n");
> >  
> > +	/* get the timeouts before testing for irqs */
> > +	if (!(chip->flags & TPM_CHIP_FLAG_TPM2) && tpm_get_timeouts(chip)) {
> > +		dev_err(dev, "Could not get TPM timeouts and durations\n");
> > +		rc = -ENODEV;
> > +		goto out_err;
> > +	}
> > +
> > +	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> > +		rc = tpm2_do_selftest(chip);
> > +	else
> > +		rc = tpm_do_selftest(chip);
> > +	if (rc) {
> > +		dev_err(dev, "TPM self test failed\n");
> > +		rc = -ENODEV;
> > +		goto out_err;
> > +	}
> > +
> >  	/* INTERRUPT Setup */
> >  	init_waitqueue_head(&chip->vendor.read_queue);
> >  	init_waitqueue_head(&chip->vendor.int_queue);
> 
> In Peter's for-james branch, commit 0e6cb01, the v1.2 calls to
> tpm_get_timeouts and tpm_do_selftest were moved toward the end of 
> tpm_tis_init.

Right. My bad. Could this be reverted with a separate fix or do
I prepare a new patch set? I would propose the former...

> > @@ -720,7 +767,10 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
> >  			chip->vendor.probed_irq = 0;
> >  
> >  			/* Generate Interrupts */
> > -			tpm_gen_interrupt(chip);
> > +			if (chip->flags & TPM_CHIP_FLAG_TPM2)
> > +				tpm2_gen_interrupt(chip);
> > +			else
> > +				tpm_gen_interrupt(chip);
> >  
> >  			chip->vendor.irq = chip->vendor.probed_irq;
> >  
> > @@ -808,14 +858,18 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
> >  static int tpm_tis_resume(struct device *dev)
> >  {
> >  	struct tpm_chip *chip = dev_get_drvdata(dev);
> > -	int ret;
> > +	int ret = 0;
> >  
> >  	if (chip->vendor.irq)
> >  		tpm_tis_reenable_interrupts(chip);
> >  
> > -	ret = tpm_pm_resume(dev);
> > -	if (!ret)
> > -		tpm_do_selftest(chip);
> > +	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> > +		tpm2_do_selftest(chip);
> > +	else {
> > +		ret = tpm_pm_resume(dev);
> > +		if (!ret)
> > +			tpm_do_selftest(chip);
> > +	}
> >  
> >  	return ret;
> >  }
> > -- 
> > 2.1.0
> > 

/Jarkko

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Jarkko Sakkinen Dec. 5, 2014, 1:06 p.m. UTC | #6
On Thu, Dec 04, 2014 at 10:46:25PM +0100, Peter Hüwe wrote:
> Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen:
> > From: Will Arthur <will.c.arthur@intel.com>
> > 
> > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
> > instead of calling tpm_get_timeouts(), assign duration and timeout
> > values defined in the TPM 2.0 PTP specification.
> > 
> > Signed-off-by: Will Arthur <will.c.arthur@intel.com>
> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > ---
> Should we change the KConfig string?
>  TPM Interface Specification 1.2 Interface
> is not quite accurate anymore after applying this patch.

Would make sense. Does this require a new patch set?

> Thanks,
> Peter

/Jarkko

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Peter Hüwe Dec. 5, 2014, 3:01 p.m. UTC | #7
> 
> > Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen:
> > > From: Will Arthur <will.c.arthur@intel.com>
> > >
> > > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
> > > instead of calling tpm_get_timeouts(), assign duration and timeout
> > > values defined in the TPM 2.0 PTP specification.
> > >
> > > Signed-off-by: Will Arthur <will.c.arthur@intel.com>
> > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> 
> > >
> > > + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1));
> > > + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM)
> > > + chip->flags = TPM_CHIP_FLAG_TPM2;
> > > +
> > >
> 
> >
> > When loading tpm_tis force=1 with my tpm1.2 chip on a machine without bios
> > integration, it fets detected as a TPM2.0 chip :/
> >
> > sudo rmmod tpm_tis
> > # modprobe tpm_tis force=1
> > modprobe: ERROR: could not insert 'tpm_tis': No such device
> > # dmesg
> > [ 263.903828] tpm_tis tpm_tis: 2.0 TPM (device-id 0xB, rev-id 16)
> > [ 263.948049] tpm_tis tpm_tis: A TPM error (10) occurred continue selftest
> > [ 263.948120] tpm_tis tpm_tis: TPM self test failed
> >
> >
> > sts3 is reported as 0xff from my TPM1.2
> >
> 
> 
> Hmm,
> my TPM2.0 chip also reports sts3 as 0xff (when loading with force=1 on a
> machine without bios integration)
> 
> [ 307.095344] sts3 ff
> [ 307.095366] tpm_tis tpm_tis: 2.0 TPM (device-id 0x1A, rev-id 16)
> [ 307.140047] tpm_tis tpm_tis: A TPM error (256) occurred continue selftest
> [ 307.140056] tpm_tis tpm_tis: TPM self test failed


You are reading "sts3" - before requesting the locality and thus it returns 0xff for a TPM20 chip as well.
--> You have to have an active locality first.


For a TPM2.0 0xFF is not a valid value (if active locality is set), since reading commandCancel and resetEstablishment bit always return 0 on reads (according to spec).

--> 0xFF should be treated as a TPM1.2 (older tpms with TIS 1.2)
--> 0x04 should be treated as TPM 2.0
--> 0x08 should be treated as TPM1.2 (newer tpms with TIS1.3 enhanced)



Thanks,
Peter

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Stefan Berger Dec. 5, 2014, 8:44 p.m. UTC | #8
On 12/05/2014 10:01 AM, Peter Huewe wrote:
>>> Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen:
>>>> From: Will Arthur <will.c.arthur@intel.com>
>>>>
>>>> Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
>>>> instead of calling tpm_get_timeouts(), assign duration and timeout
>>>> values defined in the TPM 2.0 PTP specification.
>>>>
>>>> Signed-off-by: Will Arthur <will.c.arthur@intel.com>
>>>> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
>>>> + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1));
>>>> + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM)
>>>> + chip->flags = TPM_CHIP_FLAG_TPM2;
>>>> +
>>>>
>>> When loading tpm_tis force=1 with my tpm1.2 chip on a machine without bios
>>> integration, it fets detected as a TPM2.0 chip :/
>>>
>>> sudo rmmod tpm_tis
>>> # modprobe tpm_tis force=1
>>> modprobe: ERROR: could not insert 'tpm_tis': No such device
>>> # dmesg
>>> [ 263.903828] tpm_tis tpm_tis: 2.0 TPM (device-id 0xB, rev-id 16)
>>> [ 263.948049] tpm_tis tpm_tis: A TPM error (10) occurred continue selftest
>>> [ 263.948120] tpm_tis tpm_tis: TPM self test failed
>>>
>>>
>>> sts3 is reported as 0xff from my TPM1.2
>>>
>>
>> Hmm,
>> my TPM2.0 chip also reports sts3 as 0xff (when loading with force=1 on a
>> machine without bios integration)
>>
>> [ 307.095344] sts3 ff
>> [ 307.095366] tpm_tis tpm_tis: 2.0 TPM (device-id 0x1A, rev-id 16)
>> [ 307.140047] tpm_tis tpm_tis: A TPM error (256) occurred continue selftest
>> [ 307.140056] tpm_tis tpm_tis: TPM self test failed
>
> You are reading "sts3" - before requesting the locality and thus it returns 0xff for a TPM20 chip as well.
> --> You have to have an active locality first.
>
>
> For a TPM2.0 0xFF is not a valid value (if active locality is set), since reading commandCancel and resetEstablishment bit always return 0 on reads (according to spec).
>
> --> 0xFF should be treated as a TPM1.2 (older tpms with TIS 1.2)
> --> 0x04 should be treated as TPM 2.0
> --> 0x08 should be treated as TPM1.2 (newer tpms with TIS1.3 enhanced)

> + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1));
> + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM)
> + chip->flags = TPM_CHIP_FLAG_TPM2;

#define TPM_STS3_TPM2_FAM_MASK = 0x0c

then:

if ((sts3 & TPM_STS3_TPM2_FAM_MASK) == TPM_STS3_TPM2_FAM) ...

[see my previous review on this]

    Stefan






>
>
>
> Thanks,
> Peter
>
> ------------------------------------------------------------------------------
> Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
> from Actuate! Instantly Supercharge Your Business Reports and Dashboards
> with Interactivity, Sharing, Native Excel Exports, App Integration & more
> Get technology previously reserved for billion-dollar corporations, FREE
> http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
> _______________________________________________
> tpmdd-devel mailing list
> tpmdd-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
>


------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Jarkko Sakkinen Dec. 9, 2014, 3:47 p.m. UTC | #9
On Fri, Dec 05, 2014 at 04:01:01PM +0100, Peter Huewe wrote:
> > 
> > > Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen:
> > > > From: Will Arthur <will.c.arthur@intel.com>
> > > >
> > > > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
> > > > instead of calling tpm_get_timeouts(), assign duration and timeout
> > > > values defined in the TPM 2.0 PTP specification.
> > > >
> > > > Signed-off-by: Will Arthur <will.c.arthur@intel.com>
> > > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > 
> > > >
> > > > + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1));
> > > > + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM)
> > > > + chip->flags = TPM_CHIP_FLAG_TPM2;
> > > > +
> > > >
> > 
> > >
> > > When loading tpm_tis force=1 with my tpm1.2 chip on a machine without bios
> > > integration, it fets detected as a TPM2.0 chip :/
> > >
> > > sudo rmmod tpm_tis
> > > # modprobe tpm_tis force=1
> > > modprobe: ERROR: could not insert 'tpm_tis': No such device
> > > # dmesg
> > > [ 263.903828] tpm_tis tpm_tis: 2.0 TPM (device-id 0xB, rev-id 16)
> > > [ 263.948049] tpm_tis tpm_tis: A TPM error (10) occurred continue selftest
> > > [ 263.948120] tpm_tis tpm_tis: TPM self test failed
> > >
> > >
> > > sts3 is reported as 0xff from my TPM1.2
> > >
> > 
> > 
> > Hmm,
> > my TPM2.0 chip also reports sts3 as 0xff (when loading with force=1 on a
> > machine without bios integration)
> > 
> > [ 307.095344] sts3 ff
> > [ 307.095366] tpm_tis tpm_tis: 2.0 TPM (device-id 0x1A, rev-id 16)
> > [ 307.140047] tpm_tis tpm_tis: A TPM error (256) occurred continue selftest
> > [ 307.140056] tpm_tis tpm_tis: TPM self test failed
> 
> 
> You are reading "sts3" - before requesting the locality and thus
> it returns 0xff for a TPM20 chip as well.
> --> You have to have an active locality first.
> 
> 
> For a TPM2.0 0xFF is not a valid value (if active locality is
> set), since reading commandCancel and resetEstablishment bit
> always return 0 on reads (according to spec).
> 
> --> 0xFF should be treated as a TPM1.2 (older tpms with TIS 1.2)
> --> 0x04 should be treated as TPM 2.0
> --> 0x08 should be treated as TPM1.2 (newer tpms with TIS1.3 enhanced)

Correct. I discussed with some people and verified the reason to be
such that if firmware does nothing, the locality is unopened. I have
access today to similar setup and can fix this regression and verify
my fix.

Thanks for pointing this out!

> Thanks,
> Peter

/Jarkko

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
diff mbox

Patch

diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 89e1abb..71cbb2d 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -1,5 +1,6 @@ 
 /*
  * Copyright (C) 2005, 2006 IBM Corporation
+ * Copyright (C) 2014 Intel Corporation
  *
  * Authors:
  * Leendert van Doorn <leendert@watson.ibm.com>
@@ -44,6 +45,10 @@  enum tis_status {
 	TPM_STS_DATA_EXPECT = 0x08,
 };
 
+enum tis_status3 {
+	TPM_STS3_TPM2_FAM = 0x04,
+};
+
 enum tis_int_flags {
 	TPM_GLOBAL_INT_ENABLE = 0x80000000,
 	TPM_INTF_BURST_COUNT_STATIC = 0x100,
@@ -70,6 +75,7 @@  enum tis_defaults {
 #define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
 #define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
 #define	TPM_STS(l)			(0x0018 | ((l) << 12))
+#define	TPM_STS3(l)			(0x001b | ((l) << 12))
 #define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
 
 #define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
@@ -363,6 +369,7 @@  static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
 {
 	int rc;
 	u32 ordinal;
+	unsigned long dur;
 
 	rc = tpm_tis_send_data(chip, buf, len);
 	if (rc < 0)
@@ -374,9 +381,14 @@  static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
 
 	if (chip->vendor.irq) {
 		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+
+		if (chip->flags & TPM_CHIP_FLAG_TPM2)
+			dur = tpm2_calc_ordinal_duration(chip, ordinal);
+		else
+			dur = tpm_calc_ordinal_duration(chip, ordinal);
+
 		if (wait_for_tpm_stat
-		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
-		     tpm_calc_ordinal_duration(chip, ordinal),
+		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
 		     &chip->vendor.read_queue, false) < 0) {
 			rc = -ETIME;
 			goto out_err;
@@ -588,6 +600,7 @@  static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
 	int rc, i, irq_s, irq_e, probe;
 	struct tpm_chip *chip;
 	struct priv_data *priv;
+	u8 sts3;
 
 	priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
 	if (priv == NULL)
@@ -604,11 +617,28 @@  static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
 	if (!chip->vendor.iobase)
 		return -EIO;
 
+	sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1));
+	if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM)
+		chip->flags = TPM_CHIP_FLAG_TPM2;
+
 	/* Default timeouts */
-	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
-	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
-	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
-	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+		chip->vendor.timeout_a = usecs_to_jiffies(TPM2_TIMEOUT_A);
+		chip->vendor.timeout_b = usecs_to_jiffies(TPM2_TIMEOUT_B);
+		chip->vendor.timeout_c = usecs_to_jiffies(TPM2_TIMEOUT_C);
+		chip->vendor.timeout_d = usecs_to_jiffies(TPM2_TIMEOUT_D);
+		chip->vendor.duration[TPM_SHORT] =
+			usecs_to_jiffies(TPM2_DURATION_SHORT);
+		chip->vendor.duration[TPM_MEDIUM] =
+			usecs_to_jiffies(TPM2_DURATION_MEDIUM);
+		chip->vendor.duration[TPM_LONG] =
+			usecs_to_jiffies(TPM2_DURATION_LONG);
+	} else {
+		chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+		chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+		chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+		chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	}
 
 	if (wait_startup(chip, 0) != 0) {
 		rc = -ENODEV;
@@ -623,8 +653,8 @@  static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
 	vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
 	chip->vendor.manufacturer_id = vendor;
 
-	dev_info(dev,
-		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
+	dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
+		 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
 		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
 
 	if (!itpm) {
@@ -665,6 +695,23 @@  static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
 	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
 		dev_dbg(dev, "\tData Avail Int Support\n");
 
+	/* get the timeouts before testing for irqs */
+	if (!(chip->flags & TPM_CHIP_FLAG_TPM2) && tpm_get_timeouts(chip)) {
+		dev_err(dev, "Could not get TPM timeouts and durations\n");
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	if (chip->flags & TPM_CHIP_FLAG_TPM2)
+		rc = tpm2_do_selftest(chip);
+	else
+		rc = tpm_do_selftest(chip);
+	if (rc) {
+		dev_err(dev, "TPM self test failed\n");
+		rc = -ENODEV;
+		goto out_err;
+	}
+
 	/* INTERRUPT Setup */
 	init_waitqueue_head(&chip->vendor.read_queue);
 	init_waitqueue_head(&chip->vendor.int_queue);
@@ -720,7 +767,10 @@  static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
 			chip->vendor.probed_irq = 0;
 
 			/* Generate Interrupts */
-			tpm_gen_interrupt(chip);
+			if (chip->flags & TPM_CHIP_FLAG_TPM2)
+				tpm2_gen_interrupt(chip);
+			else
+				tpm_gen_interrupt(chip);
 
 			chip->vendor.irq = chip->vendor.probed_irq;
 
@@ -808,14 +858,18 @@  static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
 static int tpm_tis_resume(struct device *dev)
 {
 	struct tpm_chip *chip = dev_get_drvdata(dev);
-	int ret;
+	int ret = 0;
 
 	if (chip->vendor.irq)
 		tpm_tis_reenable_interrupts(chip);
 
-	ret = tpm_pm_resume(dev);
-	if (!ret)
-		tpm_do_selftest(chip);
+	if (chip->flags & TPM_CHIP_FLAG_TPM2)
+		tpm2_do_selftest(chip);
+	else {
+		ret = tpm_pm_resume(dev);
+		if (!ret)
+			tpm_do_selftest(chip);
+	}
 
 	return ret;
 }