Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 260954
b: refs/heads/master
c: 9519de3
h: refs/heads/master
v: v3
  • Loading branch information
Stefan Berger authored and Rajiv Andrade committed Jul 12, 2011
1 parent 186e89c commit b8b89ed
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a7b66822b20f67f106690d0acee3d0ba667fd9bb
refs/heads/master: 9519de3f265f112e992aa7f446d905196bd608e8
77 changes: 73 additions & 4 deletions trunk/drivers/char/tpm/tpm_tis.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,10 @@ MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
* tpm.c can skip polling for the data to be available as the interrupt is
* waited for here
*/
static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
{
int rc, status, burstcnt;
size_t count = 0;
u32 ordinal;

if (request_locality(chip, 0) < 0)
return -EBUSY;
Expand Down Expand Up @@ -345,8 +344,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)

/* write last byte */
iowrite8(buf[count],
chip->vendor.iobase +
TPM_DATA_FIFO(chip->vendor.locality));
chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
&chip->vendor.int_queue);
status = tpm_tis_status(chip);
Expand All @@ -355,6 +353,28 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
goto out_err;
}

return 0;

out_err:
tpm_tis_ready(chip);
release_locality(chip, chip->vendor.locality, 0);
return rc;
}

/*
* If interrupts are used (signaled by an irq set in the vendor structure)
* tpm.c can skip polling for the data to be available as the interrupt is
* waited for here
*/
static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
int rc;
u32 ordinal;

rc = tpm_tis_send_data(chip, buf, len);
if (rc < 0)
return rc;

/* go and do it */
iowrite8(TPM_STS_GO,
chip->vendor.iobase + TPM_STS(chip->vendor.locality));
Expand All @@ -376,6 +396,47 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
return rc;
}

/*
* Early probing for iTPM with STS_DATA_EXPECT flaw.
* Try sending command without itpm flag set and if that
* fails, repeat with itpm flag set.
*/
static int probe_itpm(struct tpm_chip *chip)
{
int rc = 0;
u8 cmd_getticks[] = {
0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x00, 0x00, 0xf1
};
size_t len = sizeof(cmd_getticks);
int rem_itpm = itpm;

itpm = 0;

rc = tpm_tis_send_data(chip, cmd_getticks, len);
if (rc == 0)
goto out;

tpm_tis_ready(chip);
release_locality(chip, chip->vendor.locality, 0);

itpm = 1;

rc = tpm_tis_send_data(chip, cmd_getticks, len);
if (rc == 0) {
dev_info(chip->dev, "Detected an iTPM.\n");
rc = 1;
} else
rc = -EFAULT;

out:
itpm = rem_itpm;
tpm_tis_ready(chip);
release_locality(chip, chip->vendor.locality, 0);

return rc;
}

static const struct file_operations tis_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
Expand Down Expand Up @@ -515,6 +576,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
"1.2 TPM (device-id 0x%X, rev-id %d)\n",
vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));

if (!itpm) {
itpm = probe_itpm(chip);
if (itpm < 0) {
rc = -ENODEV;
goto out_err;
}
}

if (itpm)
dev_info(dev, "Intel iTPM workaround enabled\n");

Expand Down

0 comments on commit b8b89ed

Please sign in to comment.