aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKylene Jo Hall <kjhall@us.ibm.com>2006-04-22 05:37:50 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-22 12:19:54 -0400
commit08e96e486dd1345ae0ad70247387d0d4fd346889 (patch)
tree25dbff8ebc7ec35d476917ccc1f8c54808e79bea
parent9e18ee19179a7742999d0e2d4bfcba75b5562439 (diff)
[PATCH] tpm: new 1.2 sysfs files
Many of the sysfs files were calling the TPM_GetCapability command with array. Since for 1.2 more sysfs files of this type are coming I am generalizing the array so there can be one array and the unique parts can be filled in just before the command is called. This updated version of the patch breaks the multi-value sysfs file into separate files pointed out by Greg. It also addresses the code redundancy and ugliness in the tpm_show_* functions pointed out on another patch by Dave Hansen. Signed-off-by: Kylene Hall <kjhall@us.ibm.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-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 *);