diff options
author | Stefan Berger <stefanb@linux.vnet.ibm.com> | 2011-11-11 12:57:04 -0500 |
---|---|---|
committer | Rajiv Andrade <srajiv@linux.vnet.ibm.com> | 2011-11-16 06:42:59 -0500 |
commit | 68d6e6713fcb2ea6278661aaaf5f1c9c821b3751 (patch) | |
tree | fb02641cb1941a6d9c23ac3df37d6aafcd4f7f3a /drivers/char | |
parent | d97c6ade5926afb6d52df36c33a3491d62cd0dc0 (diff) |
tpm: Introduce function to poll for result of self test
This patch introduces a function that runs the TPM_ContinueSelfTest()
function and then polls the TPM to check whether it finished the selftest
and can receive new commands.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/tpm/tpm.c | 44 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 4 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 9 |
3 files changed, 51 insertions, 6 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 9bd4668e2855..2e12b3f98139 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -627,7 +627,7 @@ static struct tpm_input_header continue_selftest_header = { | |||
627 | * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing | 627 | * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing |
628 | * a TPM error code. | 628 | * a TPM error code. |
629 | */ | 629 | */ |
630 | int tpm_continue_selftest(struct tpm_chip *chip) | 630 | static int tpm_continue_selftest(struct tpm_chip *chip) |
631 | { | 631 | { |
632 | int rc; | 632 | int rc; |
633 | struct tpm_cmd_t cmd; | 633 | struct tpm_cmd_t cmd; |
@@ -637,7 +637,6 @@ int tpm_continue_selftest(struct tpm_chip *chip) | |||
637 | "continue selftest"); | 637 | "continue selftest"); |
638 | return rc; | 638 | return rc; |
639 | } | 639 | } |
640 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); | ||
641 | 640 | ||
642 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, | 641 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, |
643 | char *buf) | 642 | char *buf) |
@@ -732,7 +731,7 @@ static struct tpm_input_header pcrread_header = { | |||
732 | .ordinal = TPM_ORDINAL_PCRREAD | 731 | .ordinal = TPM_ORDINAL_PCRREAD |
733 | }; | 732 | }; |
734 | 733 | ||
735 | int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | 734 | static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) |
736 | { | 735 | { |
737 | int rc; | 736 | int rc; |
738 | struct tpm_cmd_t cmd; | 737 | struct tpm_cmd_t cmd; |
@@ -812,6 +811,45 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | |||
812 | } | 811 | } |
813 | EXPORT_SYMBOL_GPL(tpm_pcr_extend); | 812 | EXPORT_SYMBOL_GPL(tpm_pcr_extend); |
814 | 813 | ||
814 | /** | ||
815 | * tpm_do_selftest - have the TPM continue its selftest and wait until it | ||
816 | * can receive further commands | ||
817 | * @chip: TPM chip to use | ||
818 | * | ||
819 | * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing | ||
820 | * a TPM error code. | ||
821 | */ | ||
822 | int tpm_do_selftest(struct tpm_chip *chip) | ||
823 | { | ||
824 | int rc; | ||
825 | u8 digest[TPM_DIGEST_SIZE]; | ||
826 | unsigned int loops; | ||
827 | unsigned int delay_msec = 1000; | ||
828 | unsigned long duration; | ||
829 | |||
830 | duration = tpm_calc_ordinal_duration(chip, | ||
831 | TPM_ORD_CONTINUE_SELFTEST); | ||
832 | |||
833 | loops = jiffies_to_msecs(duration) / delay_msec; | ||
834 | |||
835 | rc = tpm_continue_selftest(chip); | ||
836 | /* This may fail if there was no TPM driver during a suspend/resume | ||
837 | * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) | ||
838 | */ | ||
839 | if (rc) | ||
840 | return rc; | ||
841 | |||
842 | do { | ||
843 | rc = __tpm_pcr_read(chip, 0, digest); | ||
844 | if (rc != TPM_WARN_DOING_SELFTEST) | ||
845 | return rc; | ||
846 | msleep(delay_msec); | ||
847 | } while (--loops > 0); | ||
848 | |||
849 | return rc; | ||
850 | } | ||
851 | EXPORT_SYMBOL_GPL(tpm_do_selftest); | ||
852 | |||
815 | int tpm_send(u32 chip_num, void *cmd, size_t buflen) | 853 | int tpm_send(u32 chip_num, void *cmd, size_t buflen) |
816 | { | 854 | { |
817 | struct tpm_chip *chip; | 855 | struct tpm_chip *chip; |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 5d2be8ae1b48..e264de16285f 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -38,6 +38,8 @@ enum tpm_addr { | |||
38 | TPM_ADDR = 0x4E, | 38 | TPM_ADDR = 0x4E, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | #define TPM_WARN_DOING_SELFTEST 0x802 | ||
42 | |||
41 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, | 43 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, |
42 | char *); | 44 | char *); |
43 | extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, | 45 | extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, |
@@ -281,7 +283,7 @@ ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); | |||
281 | 283 | ||
282 | extern int tpm_get_timeouts(struct tpm_chip *); | 284 | extern int tpm_get_timeouts(struct tpm_chip *); |
283 | extern void tpm_gen_interrupt(struct tpm_chip *); | 285 | extern void tpm_gen_interrupt(struct tpm_chip *); |
284 | extern int tpm_continue_selftest(struct tpm_chip *); | 286 | extern int tpm_do_selftest(struct tpm_chip *); |
285 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); | 287 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); |
286 | extern struct tpm_chip* tpm_register_hardware(struct device *, | 288 | extern struct tpm_chip* tpm_register_hardware(struct device *, |
287 | const struct tpm_vendor_specific *); | 289 | const struct tpm_vendor_specific *); |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 3f4051a7c5a7..d30d5c3c6c02 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -616,6 +616,12 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
616 | /* get the timeouts before testing for irqs */ | 616 | /* get the timeouts before testing for irqs */ |
617 | tpm_get_timeouts(chip); | 617 | tpm_get_timeouts(chip); |
618 | 618 | ||
619 | if (tpm_do_selftest(chip)) { | ||
620 | dev_err(dev, "TPM self test failed\n"); | ||
621 | rc = -ENODEV; | ||
622 | goto out_err; | ||
623 | } | ||
624 | |||
619 | /* INTERRUPT Setup */ | 625 | /* INTERRUPT Setup */ |
620 | init_waitqueue_head(&chip->vendor.read_queue); | 626 | init_waitqueue_head(&chip->vendor.read_queue); |
621 | init_waitqueue_head(&chip->vendor.int_queue); | 627 | init_waitqueue_head(&chip->vendor.int_queue); |
@@ -722,7 +728,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
722 | list_add(&chip->vendor.list, &tis_chips); | 728 | list_add(&chip->vendor.list, &tis_chips); |
723 | spin_unlock(&tis_lock); | 729 | spin_unlock(&tis_lock); |
724 | 730 | ||
725 | tpm_continue_selftest(chip); | ||
726 | 731 | ||
727 | return 0; | 732 | return 0; |
728 | out_err: | 733 | out_err: |
@@ -790,7 +795,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev) | |||
790 | 795 | ||
791 | ret = tpm_pm_resume(&dev->dev); | 796 | ret = tpm_pm_resume(&dev->dev); |
792 | if (!ret) | 797 | if (!ret) |
793 | tpm_continue_selftest(chip); | 798 | tpm_do_selftest(chip); |
794 | 799 | ||
795 | return ret; | 800 | return ret; |
796 | } | 801 | } |