Skip to content

Commit 08e96e4

Browse files
Kylene Jo HallLinus Torvalds
authored andcommitted
[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>
1 parent 9e18ee1 commit 08e96e4

File tree

2 files changed

+247
-2
lines changed

2 files changed

+247
-2
lines changed

drivers/char/tpm/tpm.c

Lines changed: 233 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,17 +430,27 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
430430
#define TPM_GET_CAP_RET_UINT32_2_IDX 18
431431
#define TPM_GET_CAP_RET_UINT32_3_IDX 22
432432
#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
433437

434438
#define TPM_CAP_IDX 13
435439
#define TPM_CAP_SUBCAP_IDX 21
436440

437441
enum tpm_capabilities {
442+
TPM_CAP_FLAG = 4,
438443
TPM_CAP_PROP = 5,
439444
};
440445

441446
enum tpm_sub_capabilities {
442447
TPM_CAP_PROP_PCR = 0x1,
443448
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,
444454
};
445455

446456
/*
@@ -474,6 +484,180 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
474484
return 0;
475485
}
476486

487+
void 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+
}
499+
EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
500+
501+
void 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+
538+
duration:
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+
}
559+
EXPORT_SYMBOL_GPL(tpm_get_timeouts);
560+
561+
void 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+
}
571+
EXPORT_SYMBOL_GPL(tpm_continue_selftest);
572+
573+
ssize_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+
}
593+
EXPORT_SYMBOL_GPL(tpm_show_enabled);
594+
595+
ssize_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+
}
615+
EXPORT_SYMBOL_GPL(tpm_show_active);
616+
617+
ssize_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+
}
637+
EXPORT_SYMBOL_GPL(tpm_show_owned);
638+
639+
ssize_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+
}
659+
EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
660+
477661
static const u8 pcrread[] = {
478662
0, 193, /* TPM_TAG_RQU_COMMAND */
479663
0, 0, 0, 14, /* length */
@@ -484,7 +668,7 @@ static const u8 pcrread[] = {
484668
ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
485669
char *buf)
486670
{
487-
u8 data[30];
671+
u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)];
488672
ssize_t rc;
489673
int i, j, num_pcrs;
490674
__be32 index;
@@ -588,6 +772,7 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
588772
EXPORT_SYMBOL_GPL(tpm_show_pubek);
589773

590774
#define CAP_VERSION_1_1 6
775+
#define CAP_VERSION_1_2 0x1A
591776
#define CAP_VERSION_IDX 13
592777
static const u8 cap_version[] = {
593778
0, 193, /* TPM_TAG_RQU_COMMAND */
@@ -600,7 +785,7 @@ static const u8 cap_version[] = {
600785
ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
601786
char *buf)
602787
{
603-
u8 data[30];
788+
u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
604789
ssize_t rc;
605790
char *str = buf;
606791

@@ -637,6 +822,52 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
637822
}
638823
EXPORT_SYMBOL_GPL(tpm_show_caps);
639824

825+
ssize_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+
866+
out:
867+
return str - buf;
868+
}
869+
EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
870+
640871
ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
641872
const char *buf, size_t count)
642873
{

drivers/char/tpm/tpm.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,18 @@ extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
4242
char *);
4343
extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
4444
char *);
45+
extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr,
46+
char *);
4547
extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
4648
const char *, size_t);
49+
extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr,
50+
char *);
51+
extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr,
52+
char *);
53+
extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
54+
char *);
55+
extern ssize_t tpm_show_temp_deactivated(struct device *,
56+
struct device_attribute *attr, char *);
4757

4858
struct tpm_chip;
4959

@@ -63,6 +73,7 @@ struct tpm_vendor_specific {
6373
u8 (*status) (struct tpm_chip *);
6474
struct miscdevice miscdev;
6575
struct attribute_group *attr_group;
76+
u32 timeout_a, timeout_b, timeout_c, timeout_d;
6677
u32 duration[3];
6778
};
6879

@@ -101,6 +112,9 @@ static inline void tpm_write_index(int base, int index, int value)
101112
outb(value & 0xFF, base+1);
102113
}
103114

115+
extern void tpm_get_timeouts(struct tpm_chip *);
116+
extern void tpm_gen_interrupt(struct tpm_chip *);
117+
extern void tpm_continue_selftest(struct tpm_chip *);
104118
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
105119
extern struct tpm_chip* tpm_register_hardware(struct device *,
106120
const struct tpm_vendor_specific *);

0 commit comments

Comments
 (0)