aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/tpm')
-rw-r--r--drivers/char/tpm/tpm.c235
-rw-r--r--drivers/char/tpm/tpm.h14
2 files changed, 247 insertions, 2 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index e54bcb4e4e3e..24c4423d4851 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -430,17 +430,27 @@ out:
430#define TPM_GET_CAP_RET_UINT32_2_IDX 18 430#define TPM_GET_CAP_RET_UINT32_2_IDX 18
431#define TPM_GET_CAP_RET_UINT32_3_IDX 22 431#define TPM_GET_CAP_RET_UINT32_3_IDX 22
432#define TPM_GET_CAP_RET_UINT32_4_IDX 26 432#define TPM_GET_CAP_RET_UINT32_4_IDX 26
433#define TPM_GET_CAP_PERM_DISABLE_IDX 16
434#define TPM_GET_CAP_PERM_INACTIVE_IDX 18
435#define TPM_GET_CAP_RET_BOOL_1_IDX 14
436#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16
433 437
434#define TPM_CAP_IDX 13 438#define TPM_CAP_IDX 13
435#define TPM_CAP_SUBCAP_IDX 21 439#define TPM_CAP_SUBCAP_IDX 21
436 440
437enum tpm_capabilities { 441enum tpm_capabilities {
442 TPM_CAP_FLAG = 4,
438 TPM_CAP_PROP = 5, 443 TPM_CAP_PROP = 5,
439}; 444};
440 445
441enum tpm_sub_capabilities { 446enum tpm_sub_capabilities {
442 TPM_CAP_PROP_PCR = 0x1, 447 TPM_CAP_PROP_PCR = 0x1,
443 TPM_CAP_PROP_MANUFACTURER = 0x3, 448 TPM_CAP_PROP_MANUFACTURER = 0x3,
449 TPM_CAP_FLAG_PERM = 0x8,
450 TPM_CAP_FLAG_VOL = 0x9,
451 TPM_CAP_PROP_OWNER = 0x11,
452 TPM_CAP_PROP_TIS_TIMEOUT = 0x15,
453 TPM_CAP_PROP_TIS_DURATION = 0x20,
444}; 454};
445 455
446/* 456/*
@@ -474,6 +484,180 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
474 return 0; 484 return 0;
475} 485}
476 486
487void tpm_gen_interrupt(struct tpm_chip *chip)
488{
489 u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
490 ssize_t rc;
491
492 memcpy(data, tpm_cap, sizeof(tpm_cap));
493 data[TPM_CAP_IDX] = TPM_CAP_PROP;
494 data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
495
496 rc = transmit_cmd(chip, data, sizeof(data),
497 "attempting to determine the timeouts");
498}
499EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
500
501void tpm_get_timeouts(struct tpm_chip *chip)
502{
503 u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
504 ssize_t rc;
505 u32 timeout;
506
507 memcpy(data, tpm_cap, sizeof(tpm_cap));
508 data[TPM_CAP_IDX] = TPM_CAP_PROP;
509 data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
510
511 rc = transmit_cmd(chip, data, sizeof(data),
512 "attempting to determine the timeouts");
513 if (rc)
514 goto duration;
515
516 if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
517 != 4 * sizeof(u32))
518 goto duration;
519
520 /* Don't overwrite default if value is 0 */
521 timeout =
522 be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
523 if (timeout)
524 chip->vendor.timeout_a = timeout;
525 timeout =
526 be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
527 if (timeout)
528 chip->vendor.timeout_b = timeout;
529 timeout =
530 be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
531 if (timeout)
532 chip->vendor.timeout_c = timeout;
533 timeout =
534 be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
535 if (timeout)
536 chip->vendor.timeout_d = timeout;
537
538duration:
539 memcpy(data, tpm_cap, sizeof(tpm_cap));
540 data[TPM_CAP_IDX] = TPM_CAP_PROP;
541 data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION;
542
543 rc = transmit_cmd(chip, data, sizeof(data),
544 "attempting to determine the durations");
545 if (rc)
546 return;
547
548 if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
549 != 3 * sizeof(u32))
550 return;
551
552 chip->vendor.duration[TPM_SHORT] =
553 be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
554 chip->vendor.duration[TPM_MEDIUM] =
555 be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
556 chip->vendor.duration[TPM_LONG] =
557 be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
558}
559EXPORT_SYMBOL_GPL(tpm_get_timeouts);
560
561void tpm_continue_selftest(struct tpm_chip *chip)
562{
563 u8 data[] = {
564 0, 193, /* TPM_TAG_RQU_COMMAND */
565 0, 0, 0, 10, /* length */
566 0, 0, 0, 83, /* TPM_ORD_GetCapability */
567 };
568
569 tpm_transmit(chip, data, sizeof(data));
570}
571EXPORT_SYMBOL_GPL(tpm_continue_selftest);
572
573ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
574 char *buf)
575{
576 u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
577 ssize_t rc;
578
579 struct tpm_chip *chip = dev_get_drvdata(dev);
580 if (chip == NULL)
581 return -ENODEV;
582
583 memcpy(data, tpm_cap, sizeof(tpm_cap));
584 data[TPM_CAP_IDX] = TPM_CAP_FLAG;
585 data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
586
587 rc = transmit_cmd(chip, data, sizeof(data),
588 "attemtping to determine the permanent state");
589 if (rc)
590 return 0;
591 return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
592}
593EXPORT_SYMBOL_GPL(tpm_show_enabled);
594
595ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
596 char *buf)
597{
598 u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
599 ssize_t rc;
600
601 struct tpm_chip *chip = dev_get_drvdata(dev);
602 if (chip == NULL)
603 return -ENODEV;
604
605 memcpy(data, tpm_cap, sizeof(tpm_cap));
606 data[TPM_CAP_IDX] = TPM_CAP_FLAG;
607 data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
608
609 rc = transmit_cmd(chip, data, sizeof(data),
610 "attemtping to determine the permanent state");
611 if (rc)
612 return 0;
613 return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
614}
615EXPORT_SYMBOL_GPL(tpm_show_active);
616
617ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
618 char *buf)
619{
620 u8 data[sizeof(tpm_cap)];
621 ssize_t rc;
622
623 struct tpm_chip *chip = dev_get_drvdata(dev);
624 if (chip == NULL)
625 return -ENODEV;
626
627 memcpy(data, tpm_cap, sizeof(tpm_cap));
628 data[TPM_CAP_IDX] = TPM_CAP_PROP;
629 data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
630
631 rc = transmit_cmd(chip, data, sizeof(data),
632 "attempting to determine the owner state");
633 if (rc)
634 return 0;
635 return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
636}
637EXPORT_SYMBOL_GPL(tpm_show_owned);
638
639ssize_t tpm_show_temp_deactivated(struct device * dev,
640 struct device_attribute * attr, char *buf)
641{
642 u8 data[sizeof(tpm_cap)];
643 ssize_t rc;
644
645 struct tpm_chip *chip = dev_get_drvdata(dev);
646 if (chip == NULL)
647 return -ENODEV;
648
649 memcpy(data, tpm_cap, sizeof(tpm_cap));
650 data[TPM_CAP_IDX] = TPM_CAP_FLAG;
651 data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
652
653 rc = transmit_cmd(chip, data, sizeof(data),
654 "attempting to determine the temporary state");
655 if (rc)
656 return 0;
657 return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
658}
659EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
660
477static const u8 pcrread[] = { 661static const u8 pcrread[] = {
478 0, 193, /* TPM_TAG_RQU_COMMAND */ 662 0, 193, /* TPM_TAG_RQU_COMMAND */
479 0, 0, 0, 14, /* length */ 663 0, 0, 0, 14, /* length */
@@ -484,7 +668,7 @@ static const u8 pcrread[] = {
484ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, 668ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
485 char *buf) 669 char *buf)
486{ 670{
487 u8 data[30]; 671 u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)];
488 ssize_t rc; 672 ssize_t rc;
489 int i, j, num_pcrs; 673 int i, j, num_pcrs;
490 __be32 index; 674 __be32 index;
@@ -588,6 +772,7 @@ out:
588EXPORT_SYMBOL_GPL(tpm_show_pubek); 772EXPORT_SYMBOL_GPL(tpm_show_pubek);
589 773
590#define CAP_VERSION_1_1 6 774#define CAP_VERSION_1_1 6
775#define CAP_VERSION_1_2 0x1A
591#define CAP_VERSION_IDX 13 776#define CAP_VERSION_IDX 13
592static const u8 cap_version[] = { 777static const u8 cap_version[] = {
593 0, 193, /* TPM_TAG_RQU_COMMAND */ 778 0, 193, /* TPM_TAG_RQU_COMMAND */
@@ -600,7 +785,7 @@ static const u8 cap_version[] = {
600ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, 785ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
601 char *buf) 786 char *buf)
602{ 787{
603 u8 data[30]; 788 u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
604 ssize_t rc; 789 ssize_t rc;
605 char *str = buf; 790 char *str = buf;
606 791
@@ -637,6 +822,52 @@ out:
637} 822}
638EXPORT_SYMBOL_GPL(tpm_show_caps); 823EXPORT_SYMBOL_GPL(tpm_show_caps);
639 824
825ssize_t tpm_show_caps_1_2(struct device * dev,
826 struct device_attribute * attr, char *buf)
827{
828 u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
829 ssize_t len;
830 char *str = buf;
831
832 struct tpm_chip *chip = dev_get_drvdata(dev);
833 if (chip == NULL)
834 return -ENODEV;
835
836 memcpy(data, tpm_cap, sizeof(tpm_cap));
837 data[TPM_CAP_IDX] = TPM_CAP_PROP;
838 data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
839
840 if ((len = tpm_transmit(chip, data, sizeof(data))) <=
841 TPM_ERROR_SIZE) {
842 dev_dbg(chip->dev, "A TPM error (%d) occurred "
843 "attempting to determine the manufacturer\n",
844 be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
845 return 0;
846 }
847
848 str += sprintf(str, "Manufacturer: 0x%x\n",
849 be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
850
851 memcpy(data, cap_version, sizeof(cap_version));
852 data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
853
854 if ((len = tpm_transmit(chip, data, sizeof(data))) <=
855 TPM_ERROR_SIZE) {
856 dev_err(chip->dev, "A TPM error (%d) occurred "
857 "attempting to determine the 1.2 version\n",
858 be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
859 goto out;
860 }
861 str += sprintf(str,
862 "TCG version: %d.%d\nFirmware version: %d.%d\n",
863 (int) data[16], (int) data[17], (int) data[18],
864 (int) data[19]);
865
866out:
867 return str - buf;
868}
869EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
870
640ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, 871ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
641 const char *buf, size_t count) 872 const char *buf, size_t count)
642{ 873{
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 1d28485b8fb3..75d105c4e65d 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -42,8 +42,18 @@ extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
42 char *); 42 char *);
43extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr, 43extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
44 char *); 44 char *);
45extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr,
46 char *);
45extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr, 47extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
46 const char *, size_t); 48 const char *, size_t);
49extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr,
50 char *);
51extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr,
52 char *);
53extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
54 char *);
55extern ssize_t tpm_show_temp_deactivated(struct device *,
56 struct device_attribute *attr, char *);
47 57
48struct tpm_chip; 58struct tpm_chip;
49 59
@@ -63,6 +73,7 @@ struct tpm_vendor_specific {
63 u8 (*status) (struct tpm_chip *); 73 u8 (*status) (struct tpm_chip *);
64 struct miscdevice miscdev; 74 struct miscdevice miscdev;
65 struct attribute_group *attr_group; 75 struct attribute_group *attr_group;
76 u32 timeout_a, timeout_b, timeout_c, timeout_d;
66 u32 duration[3]; 77 u32 duration[3];
67}; 78};
68 79
@@ -101,6 +112,9 @@ static inline void tpm_write_index(int base, int index, int value)
101 outb(value & 0xFF, base+1); 112 outb(value & 0xFF, base+1);
102} 113}
103 114
115extern void tpm_get_timeouts(struct tpm_chip *);
116extern void tpm_gen_interrupt(struct tpm_chip *);
117extern void tpm_continue_selftest(struct tpm_chip *);
104extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); 118extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
105extern struct tpm_chip* tpm_register_hardware(struct device *, 119extern struct tpm_chip* tpm_register_hardware(struct device *,
106 const struct tpm_vendor_specific *); 120 const struct tpm_vendor_specific *);