aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStefan Berger <stefanb@linux.vnet.ibm.com>2011-03-30 12:13:33 -0400
committerRajiv Andrade <srajiv@linux.vnet.ibm.com>2011-07-12 17:53:09 -0400
commit9519de3f265f112e992aa7f446d905196bd608e8 (patch)
tree112d43561d9ffb478ebce085d202d77d85ad3a1a /drivers
parenta7b66822b20f67f106690d0acee3d0ba667fd9bb (diff)
tpm_tis: Probing function for Intel iTPM bug
This patch introduces a function for automatic probing for the Intel iTPM STS_DATA_EXPECT flaw. The patch splits the current tpm_tis_send function into 2 parts where the 1st part is now called tpm_tis_send_data() and merely sends the data to the TPM. This function is then used for probing. The new tpm_tis_send function now first calls tpm_tis_send_data and if that succeeds has the TPM process the command and waits until the response is there. The probing for the Intel iTPM is only invoked if the user has not passed itpm=1 as parameter for the module *or* if such a TPM was detected via ACPI. Previously it was necessary to pass itpm=1 when also passing force=1 to the module when doing a 'modprobe'. This function is more general than the ACPI test function and the function relying on ACPI could probably be removed. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Signed-off-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/tpm/tpm_tis.c77
1 files changed, 73 insertions, 4 deletions
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 47517e49d2be..ed97cfed30ea 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -306,11 +306,10 @@ MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
306 * tpm.c can skip polling for the data to be available as the interrupt is 306 * tpm.c can skip polling for the data to be available as the interrupt is
307 * waited for here 307 * waited for here
308 */ 308 */
309static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) 309static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
310{ 310{
311 int rc, status, burstcnt; 311 int rc, status, burstcnt;
312 size_t count = 0; 312 size_t count = 0;
313 u32 ordinal;
314 313
315 if (request_locality(chip, 0) < 0) 314 if (request_locality(chip, 0) < 0)
316 return -EBUSY; 315 return -EBUSY;
@@ -345,8 +344,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
345 344
346 /* write last byte */ 345 /* write last byte */
347 iowrite8(buf[count], 346 iowrite8(buf[count],
348 chip->vendor.iobase + 347 chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
349 TPM_DATA_FIFO(chip->vendor.locality));
350 wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, 348 wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
351 &chip->vendor.int_queue); 349 &chip->vendor.int_queue);
352 status = tpm_tis_status(chip); 350 status = tpm_tis_status(chip);
@@ -355,6 +353,28 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
355 goto out_err; 353 goto out_err;
356 } 354 }
357 355
356 return 0;
357
358out_err:
359 tpm_tis_ready(chip);
360 release_locality(chip, chip->vendor.locality, 0);
361 return rc;
362}
363
364/*
365 * If interrupts are used (signaled by an irq set in the vendor structure)
366 * tpm.c can skip polling for the data to be available as the interrupt is
367 * waited for here
368 */
369static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
370{
371 int rc;
372 u32 ordinal;
373
374 rc = tpm_tis_send_data(chip, buf, len);
375 if (rc < 0)
376 return rc;
377
358 /* go and do it */ 378 /* go and do it */
359 iowrite8(TPM_STS_GO, 379 iowrite8(TPM_STS_GO,
360 chip->vendor.iobase + TPM_STS(chip->vendor.locality)); 380 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
@@ -376,6 +396,47 @@ out_err:
376 return rc; 396 return rc;
377} 397}
378 398
399/*
400 * Early probing for iTPM with STS_DATA_EXPECT flaw.
401 * Try sending command without itpm flag set and if that
402 * fails, repeat with itpm flag set.
403 */
404static int probe_itpm(struct tpm_chip *chip)
405{
406 int rc = 0;
407 u8 cmd_getticks[] = {
408 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
409 0x00, 0x00, 0x00, 0xf1
410 };
411 size_t len = sizeof(cmd_getticks);
412 int rem_itpm = itpm;
413
414 itpm = 0;
415
416 rc = tpm_tis_send_data(chip, cmd_getticks, len);
417 if (rc == 0)
418 goto out;
419
420 tpm_tis_ready(chip);
421 release_locality(chip, chip->vendor.locality, 0);
422
423 itpm = 1;
424
425 rc = tpm_tis_send_data(chip, cmd_getticks, len);
426 if (rc == 0) {
427 dev_info(chip->dev, "Detected an iTPM.\n");
428 rc = 1;
429 } else
430 rc = -EFAULT;
431
432out:
433 itpm = rem_itpm;
434 tpm_tis_ready(chip);
435 release_locality(chip, chip->vendor.locality, 0);
436
437 return rc;
438}
439
379static const struct file_operations tis_ops = { 440static const struct file_operations tis_ops = {
380 .owner = THIS_MODULE, 441 .owner = THIS_MODULE,
381 .llseek = no_llseek, 442 .llseek = no_llseek,
@@ -515,6 +576,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
515 "1.2 TPM (device-id 0x%X, rev-id %d)\n", 576 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
516 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); 577 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
517 578
579 if (!itpm) {
580 itpm = probe_itpm(chip);
581 if (itpm < 0) {
582 rc = -ENODEV;
583 goto out_err;
584 }
585 }
586
518 if (itpm) 587 if (itpm)
519 dev_info(dev, "Intel iTPM workaround enabled\n"); 588 dev_info(dev, "Intel iTPM workaround enabled\n");
520 589