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.c102
1 files changed, 76 insertions, 26 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7beb0e25f1e1..caf8012ef47c 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -534,6 +534,7 @@ void tpm_get_timeouts(struct tpm_chip *chip)
534 struct duration_t *duration_cap; 534 struct duration_t *duration_cap;
535 ssize_t rc; 535 ssize_t rc;
536 u32 timeout; 536 u32 timeout;
537 unsigned int scale = 1;
537 538
538 tpm_cmd.header.in = tpm_getcap_header; 539 tpm_cmd.header.in = tpm_getcap_header;
539 tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; 540 tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
@@ -545,24 +546,30 @@ void tpm_get_timeouts(struct tpm_chip *chip)
545 if (rc) 546 if (rc)
546 goto duration; 547 goto duration;
547 548
548 if (be32_to_cpu(tpm_cmd.header.out.length) 549 if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
549 != 4 * sizeof(u32)) 550 be32_to_cpu(tpm_cmd.header.out.length)
550 goto duration; 551 != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
552 return;
551 553
552 timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; 554 timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
553 /* Don't overwrite default if value is 0 */ 555 /* Don't overwrite default if value is 0 */
554 timeout = be32_to_cpu(timeout_cap->a); 556 timeout = be32_to_cpu(timeout_cap->a);
557 if (timeout && timeout < 1000) {
558 /* timeouts in msec rather usec */
559 scale = 1000;
560 chip->vendor.timeout_adjusted = true;
561 }
555 if (timeout) 562 if (timeout)
556 chip->vendor.timeout_a = usecs_to_jiffies(timeout); 563 chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale);
557 timeout = be32_to_cpu(timeout_cap->b); 564 timeout = be32_to_cpu(timeout_cap->b);
558 if (timeout) 565 if (timeout)
559 chip->vendor.timeout_b = usecs_to_jiffies(timeout); 566 chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale);
560 timeout = be32_to_cpu(timeout_cap->c); 567 timeout = be32_to_cpu(timeout_cap->c);
561 if (timeout) 568 if (timeout)
562 chip->vendor.timeout_c = usecs_to_jiffies(timeout); 569 chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale);
563 timeout = be32_to_cpu(timeout_cap->d); 570 timeout = be32_to_cpu(timeout_cap->d);
564 if (timeout) 571 if (timeout)
565 chip->vendor.timeout_d = usecs_to_jiffies(timeout); 572 chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale);
566 573
567duration: 574duration:
568 tpm_cmd.header.in = tpm_getcap_header; 575 tpm_cmd.header.in = tpm_getcap_header;
@@ -575,23 +582,31 @@ duration:
575 if (rc) 582 if (rc)
576 return; 583 return;
577 584
578 if (be32_to_cpu(tpm_cmd.header.out.return_code) 585 if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
579 != 3 * sizeof(u32)) 586 be32_to_cpu(tpm_cmd.header.out.length)
587 != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
580 return; 588 return;
589
581 duration_cap = &tpm_cmd.params.getcap_out.cap.duration; 590 duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
582 chip->vendor.duration[TPM_SHORT] = 591 chip->vendor.duration[TPM_SHORT] =
583 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); 592 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
593 chip->vendor.duration[TPM_MEDIUM] =
594 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
595 chip->vendor.duration[TPM_LONG] =
596 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
597
584 /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above 598 /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
585 * value wrong and apparently reports msecs rather than usecs. So we 599 * value wrong and apparently reports msecs rather than usecs. So we
586 * fix up the resulting too-small TPM_SHORT value to make things work. 600 * fix up the resulting too-small TPM_SHORT value to make things work.
601 * We also scale the TPM_MEDIUM and -_LONG values by 1000.
587 */ 602 */
588 if (chip->vendor.duration[TPM_SHORT] < (HZ/100)) 603 if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) {
589 chip->vendor.duration[TPM_SHORT] = HZ; 604 chip->vendor.duration[TPM_SHORT] = HZ;
590 605 chip->vendor.duration[TPM_MEDIUM] *= 1000;
591 chip->vendor.duration[TPM_MEDIUM] = 606 chip->vendor.duration[TPM_LONG] *= 1000;
592 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); 607 chip->vendor.duration_adjusted = true;
593 chip->vendor.duration[TPM_LONG] = 608 dev_info(chip->dev, "Adjusting TPM timeout parameters.");
594 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); 609 }
595} 610}
596EXPORT_SYMBOL_GPL(tpm_get_timeouts); 611EXPORT_SYMBOL_GPL(tpm_get_timeouts);
597 612
@@ -600,7 +615,7 @@ void tpm_continue_selftest(struct tpm_chip *chip)
600 u8 data[] = { 615 u8 data[] = {
601 0, 193, /* TPM_TAG_RQU_COMMAND */ 616 0, 193, /* TPM_TAG_RQU_COMMAND */
602 0, 0, 0, 10, /* length */ 617 0, 0, 0, 10, /* length */
603 0, 0, 0, 83, /* TPM_ORD_GetCapability */ 618 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */
604 }; 619 };
605 620
606 tpm_transmit(chip, data, sizeof(data)); 621 tpm_transmit(chip, data, sizeof(data));
@@ -863,18 +878,24 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
863 data = tpm_cmd.params.readpubek_out_buffer; 878 data = tpm_cmd.params.readpubek_out_buffer;
864 str += 879 str +=
865 sprintf(str, 880 sprintf(str,
866 "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" 881 "Algorithm: %02X %02X %02X %02X\n"
867 "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X" 882 "Encscheme: %02X %02X\n"
868 " %02X %02X %02X %02X %02X %02X %02X %02X\n" 883 "Sigscheme: %02X %02X\n"
869 "Modulus length: %d\nModulus: \n", 884 "Parameters: %02X %02X %02X %02X "
870 data[10], data[11], data[12], data[13], data[14], 885 "%02X %02X %02X %02X "
871 data[15], data[16], data[17], data[22], data[23], 886 "%02X %02X %02X %02X\n"
872 data[24], data[25], data[26], data[27], data[28], 887 "Modulus length: %d\n"
873 data[29], data[30], data[31], data[32], data[33], 888 "Modulus:\n",
874 be32_to_cpu(*((__be32 *) (data + 34)))); 889 data[0], data[1], data[2], data[3],
890 data[4], data[5],
891 data[6], data[7],
892 data[12], data[13], data[14], data[15],
893 data[16], data[17], data[18], data[19],
894 data[20], data[21], data[22], data[23],
895 be32_to_cpu(*((__be32 *) (data + 24))));
875 896
876 for (i = 0; i < 256; i++) { 897 for (i = 0; i < 256; i++) {
877 str += sprintf(str, "%02X ", data[i + 38]); 898 str += sprintf(str, "%02X ", data[i + 28]);
878 if ((i + 1) % 16 == 0) 899 if ((i + 1) % 16 == 0)
879 str += sprintf(str, "\n"); 900 str += sprintf(str, "\n");
880 } 901 }
@@ -937,6 +958,35 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
937} 958}
938EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); 959EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
939 960
961ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr,
962 char *buf)
963{
964 struct tpm_chip *chip = dev_get_drvdata(dev);
965
966 return sprintf(buf, "%d %d %d [%s]\n",
967 jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
968 jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
969 jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
970 chip->vendor.duration_adjusted
971 ? "adjusted" : "original");
972}
973EXPORT_SYMBOL_GPL(tpm_show_durations);
974
975ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr,
976 char *buf)
977{
978 struct tpm_chip *chip = dev_get_drvdata(dev);
979
980 return sprintf(buf, "%d %d %d %d [%s]\n",
981 jiffies_to_usecs(chip->vendor.timeout_a),
982 jiffies_to_usecs(chip->vendor.timeout_b),
983 jiffies_to_usecs(chip->vendor.timeout_c),
984 jiffies_to_usecs(chip->vendor.timeout_d),
985 chip->vendor.timeout_adjusted
986 ? "adjusted" : "original");
987}
988EXPORT_SYMBOL_GPL(tpm_show_timeouts);
989
940ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, 990ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
941 const char *buf, size_t count) 991 const char *buf, size_t count)
942{ 992{