aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm/tpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/tpm/tpm.c')
-rw-r--r--drivers/char/tpm/tpm.c137
1 files changed, 117 insertions, 20 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 361a1dff8f77..6a8771f47a55 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -27,6 +27,7 @@
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/mutex.h> 28#include <linux/mutex.h>
29#include <linux/spinlock.h> 29#include <linux/spinlock.h>
30#include <linux/freezer.h>
30 31
31#include "tpm.h" 32#include "tpm.h"
32 33
@@ -440,7 +441,6 @@ out:
440} 441}
441 442
442#define TPM_DIGEST_SIZE 20 443#define TPM_DIGEST_SIZE 20
443#define TPM_ERROR_SIZE 10
444#define TPM_RET_CODE_IDX 6 444#define TPM_RET_CODE_IDX 6
445 445
446enum tpm_capabilities { 446enum tpm_capabilities {
@@ -469,12 +469,14 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
469 len = tpm_transmit(chip,(u8 *) cmd, len); 469 len = tpm_transmit(chip,(u8 *) cmd, len);
470 if (len < 0) 470 if (len < 0)
471 return len; 471 return len;
472 if (len == TPM_ERROR_SIZE) { 472 else if (len < TPM_HEADER_SIZE)
473 err = be32_to_cpu(cmd->header.out.return_code); 473 return -EFAULT;
474 dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); 474
475 return err; 475 err = be32_to_cpu(cmd->header.out.return_code);
476 } 476 if (err != 0)
477 return 0; 477 dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
478
479 return err;
478} 480}
479 481
480#define TPM_INTERNAL_RESULT_SIZE 200 482#define TPM_INTERNAL_RESULT_SIZE 200
@@ -530,7 +532,7 @@ void tpm_gen_interrupt(struct tpm_chip *chip)
530} 532}
531EXPORT_SYMBOL_GPL(tpm_gen_interrupt); 533EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
532 534
533void tpm_get_timeouts(struct tpm_chip *chip) 535int tpm_get_timeouts(struct tpm_chip *chip)
534{ 536{
535 struct tpm_cmd_t tpm_cmd; 537 struct tpm_cmd_t tpm_cmd;
536 struct timeout_t *timeout_cap; 538 struct timeout_t *timeout_cap;
@@ -552,7 +554,7 @@ void tpm_get_timeouts(struct tpm_chip *chip)
552 if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || 554 if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
553 be32_to_cpu(tpm_cmd.header.out.length) 555 be32_to_cpu(tpm_cmd.header.out.length)
554 != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) 556 != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
555 return; 557 return -EINVAL;
556 558
557 timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; 559 timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
558 /* Don't overwrite default if value is 0 */ 560 /* Don't overwrite default if value is 0 */
@@ -583,12 +585,12 @@ duration:
583 rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 585 rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
584 "attempting to determine the durations"); 586 "attempting to determine the durations");
585 if (rc) 587 if (rc)
586 return; 588 return rc;
587 589
588 if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || 590 if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
589 be32_to_cpu(tpm_cmd.header.out.length) 591 be32_to_cpu(tpm_cmd.header.out.length)
590 != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) 592 != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
591 return; 593 return -EINVAL;
592 594
593 duration_cap = &tpm_cmd.params.getcap_out.cap.duration; 595 duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
594 chip->vendor.duration[TPM_SHORT] = 596 chip->vendor.duration[TPM_SHORT] =
@@ -610,20 +612,36 @@ duration:
610 chip->vendor.duration_adjusted = true; 612 chip->vendor.duration_adjusted = true;
611 dev_info(chip->dev, "Adjusting TPM timeout parameters."); 613 dev_info(chip->dev, "Adjusting TPM timeout parameters.");
612 } 614 }
615 return 0;
613} 616}
614EXPORT_SYMBOL_GPL(tpm_get_timeouts); 617EXPORT_SYMBOL_GPL(tpm_get_timeouts);
615 618
616void tpm_continue_selftest(struct tpm_chip *chip) 619#define TPM_ORD_CONTINUE_SELFTEST 83
620#define CONTINUE_SELFTEST_RESULT_SIZE 10
621
622static struct tpm_input_header continue_selftest_header = {
623 .tag = TPM_TAG_RQU_COMMAND,
624 .length = cpu_to_be32(10),
625 .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
626};
627
628/**
629 * tpm_continue_selftest -- run TPM's selftest
630 * @chip: TPM chip to use
631 *
632 * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
633 * a TPM error code.
634 */
635static int tpm_continue_selftest(struct tpm_chip *chip)
617{ 636{
618 u8 data[] = { 637 int rc;
619 0, 193, /* TPM_TAG_RQU_COMMAND */ 638 struct tpm_cmd_t cmd;
620 0, 0, 0, 10, /* length */
621 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */
622 };
623 639
624 tpm_transmit(chip, data, sizeof(data)); 640 cmd.header.in = continue_selftest_header;
641 rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
642 "continue selftest");
643 return rc;
625} 644}
626EXPORT_SYMBOL_GPL(tpm_continue_selftest);
627 645
628ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, 646ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
629 char *buf) 647 char *buf)
@@ -718,7 +736,7 @@ static struct tpm_input_header pcrread_header = {
718 .ordinal = TPM_ORDINAL_PCRREAD 736 .ordinal = TPM_ORDINAL_PCRREAD
719}; 737};
720 738
721int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) 739static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
722{ 740{
723 int rc; 741 int rc;
724 struct tpm_cmd_t cmd; 742 struct tpm_cmd_t cmd;
@@ -798,6 +816,45 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
798} 816}
799EXPORT_SYMBOL_GPL(tpm_pcr_extend); 817EXPORT_SYMBOL_GPL(tpm_pcr_extend);
800 818
819/**
820 * tpm_do_selftest - have the TPM continue its selftest and wait until it
821 * can receive further commands
822 * @chip: TPM chip to use
823 *
824 * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
825 * a TPM error code.
826 */
827int tpm_do_selftest(struct tpm_chip *chip)
828{
829 int rc;
830 u8 digest[TPM_DIGEST_SIZE];
831 unsigned int loops;
832 unsigned int delay_msec = 1000;
833 unsigned long duration;
834
835 duration = tpm_calc_ordinal_duration(chip,
836 TPM_ORD_CONTINUE_SELFTEST);
837
838 loops = jiffies_to_msecs(duration) / delay_msec;
839
840 rc = tpm_continue_selftest(chip);
841 /* This may fail if there was no TPM driver during a suspend/resume
842 * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST)
843 */
844 if (rc)
845 return rc;
846
847 do {
848 rc = __tpm_pcr_read(chip, 0, digest);
849 if (rc != TPM_WARN_DOING_SELFTEST)
850 return rc;
851 msleep(delay_msec);
852 } while (--loops > 0);
853
854 return rc;
855}
856EXPORT_SYMBOL_GPL(tpm_do_selftest);
857
801int tpm_send(u32 chip_num, void *cmd, size_t buflen) 858int tpm_send(u32 chip_num, void *cmd, size_t buflen)
802{ 859{
803 struct tpm_chip *chip; 860 struct tpm_chip *chip;
@@ -1005,6 +1062,46 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
1005} 1062}
1006EXPORT_SYMBOL_GPL(tpm_store_cancel); 1063EXPORT_SYMBOL_GPL(tpm_store_cancel);
1007 1064
1065int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
1066 wait_queue_head_t *queue)
1067{
1068 unsigned long stop;
1069 long rc;
1070 u8 status;
1071
1072 /* check current status */
1073 status = chip->vendor.status(chip);
1074 if ((status & mask) == mask)
1075 return 0;
1076
1077 stop = jiffies + timeout;
1078
1079 if (chip->vendor.irq) {
1080again:
1081 timeout = stop - jiffies;
1082 if ((long)timeout <= 0)
1083 return -ETIME;
1084 rc = wait_event_interruptible_timeout(*queue,
1085 ((chip->vendor.status(chip)
1086 & mask) == mask),
1087 timeout);
1088 if (rc > 0)
1089 return 0;
1090 if (rc == -ERESTARTSYS && freezing(current)) {
1091 clear_thread_flag(TIF_SIGPENDING);
1092 goto again;
1093 }
1094 } else {
1095 do {
1096 msleep(TPM_TIMEOUT);
1097 status = chip->vendor.status(chip);
1098 if ((status & mask) == mask)
1099 return 0;
1100 } while (time_before(jiffies, stop));
1101 }
1102 return -ETIME;
1103}
1104EXPORT_SYMBOL_GPL(wait_for_tpm_stat);
1008/* 1105/*
1009 * Device file system interface to the TPM 1106 * Device file system interface to the TPM
1010 * 1107 *