lkml.org 
[lkml]   [2006]   [Apr]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectPATCH 6/7] tpm: new 1.2 sysfs files
From
Date
With the 1.2 TPM Specification there is more useful information
available. This information is exported to the user through sysfs
functions that the 1.2 driver will use.

Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
---
drivers/char/tpm/tpm.c | 206 +++++++++++++++++++++++++++++++++++++++
drivers/char/tpm/tpm.h | 7 +
2 files changed, 213 insertions(+)

--- linux-2.6.16/drivers/char/tpm/tpm.c 2006-03-30 16:58:10.715155750 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.c 2006-03-30 16:51:48.567273000 -0600
@@ -431,17 +434,27 @@ out:
#define TPM_GET_CAP_RET_UINT32_2_IDX 18
#define TPM_GET_CAP_RET_UINT32_3_IDX 22
#define TPM_GET_CAP_RET_UINT32_4_IDX 26
+#define TPM_GET_CAP_PERM_DISABLE_IDX 16
+#define TPM_GET_CAP_PERM_INACTIVE_IDX 18
+#define TPM_GET_CAP_RET_BOOL_1_IDX 14
+#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16

#define TPM_CAP_IDX 13
#define TPM_CAP_SUBCAP_IDX 21

enum tpm_capabilities {
+ TPM_CAP_FLAG = 4,
TPM_CAP_PROP = 5,
};

enum tpm_sub_capabilities {
TPM_CAP_PROP_PCR = 0x1,
TPM_CAP_PROP_MANUFACTURER = 0x3,
+ TPM_CAP_FLAG_PERM = 0x8,
+ TPM_CAP_FLAG_VOL = 0x9,
+ TPM_CAP_PROP_OWNER = 0x11,
+ TPM_CAP_PROP_TIS_TIMEOUT = 0x15,
+ TPM_CAP_PROP_TIS_DURATION = 0x20,
};

/*
@@ -459,6 +472,155 @@ static const u8 tpm_cap[] = {
0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */
};

+void tpm_gen_interrupt(struct tpm_chip *chip)
+{
+ u8 data[30];
+ ssize_t len;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ <= TPM_ERROR_SIZE)
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the timeouts\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+}
+EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
+
+void tpm_get_timeouts(struct tpm_chip *chip)
+{
+ u8 data[30];
+ ssize_t len;
+ u32 timeout;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ <= TPM_ERROR_SIZE) {
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the timeouts\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ goto duration;
+ }
+
+ if ((len =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))))
+ != 4 * sizeof(u32))
+ goto duration;
+
+ /* Don't overwrite default if value is 0 */
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
+ if (timeout)
+ chip->vendor.timeout_a = timeout;
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
+ if (timeout)
+ chip->vendor.timeout_b = timeout;
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
+ if (timeout)
+ chip->vendor.timeout_c = timeout;
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
+ if (timeout)
+ chip->vendor.timeout_d = timeout;
+
+duration:
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ <= TPM_ERROR_SIZE) {
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the durations\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ return;
+ }
+
+ if ((len =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))))
+ != 3 * sizeof(u32))
+ return;
+
+ chip->vendor.duration[TPM_SHORT] =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
+ chip->vendor.duration[TPM_MEDIUM] =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
+ chip->vendor.duration[TPM_LONG] =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
+}
+EXPORT_SYMBOL_GPL(tpm_get_timeouts);
+
+ssize_t tpm_show_state(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[35];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ <= TPM_ERROR_SIZE)
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the permanent state\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ else {
+ str +=
+ sprintf(str, "%s\n",
+ (data[TPM_GET_CAP_PERM_DISABLE_IDX] ==
+ 1) ? "Disabled" : "Enabled");
+ str +=
+ sprintf(str, "%s\n",
+ (data[TPM_GET_CAP_PERM_INACTIVE_IDX] ==
+ 1) ? "Inactive" : "Active");
+ }
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ <= TPM_ERROR_SIZE)
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the owner state\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ else
+ str +=
+ sprintf(str, "%s\n",
+ (data[TPM_GET_CAP_RET_BOOL_1_IDX] ==
+ 1) ? "Owned" : "Unowned");
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ <= TPM_ERROR_SIZE) {
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the temporary state\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ goto out;
+ }
+
+ if (data[TPM_GET_CAP_TEMP_INACTIVE_IDX] != 0)
+ str += sprintf(str, "Deactivated for this boot\n");
+out:
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tpm_show_state);
+
static const u8 pcrread[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 14, /* length */
@@ -590,6 +768,7 @@ out:
EXPORT_SYMBOL_GPL(tpm_show_pubek);

#define CAP_VERSION_1_1 6
+#define CAP_VERSION_1_2 0x1A
#define CAP_VERSION_IDX 13
static const u8 cap_version[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
@@ -651,6 +830,52 @@ out:
}
EXPORT_SYMBOL_GPL(tpm_show_caps);

+ssize_t tpm_show_caps_1_2(struct device * dev,
+ struct device_attribute * attr, char *buf)
+{
+ u8 data[30];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+ TPM_ERROR_SIZE) {
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the manufacturer\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ return 0;
+ }
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+ TPM_ERROR_SIZE) {
+ dev_err(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the 1.2 version\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ goto out;
+ }
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[16], (int) data[17], (int) data[18],
+ (int) data[19]);
+
+out:
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
+
ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
--- linux-2.6.16/drivers/char/tpm/tpm.h 2006-03-30 16:58:10.715155750 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.h 2006-03-29 14:16:30.119053500 -0600
@@ -41,8 +41,12 @@ extern ssize_t tpm_show_pcrs(struct devi
char *);
extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
char *);
+extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr,
+ char *);
extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
const char *, size_t);
+extern ssize_t tpm_show_state(struct device *, struct device_attribute *attr,
+ char *);

struct tpm_chip;

@@ -62,6 +68,7 @@ struct tpm_vendor_specific {
u8 (*status) (struct tpm_chip *);
struct miscdevice miscdev;
struct attribute_group *attr_group;
+ u32 timeout_a, timeout_b, timeout_c, timeout_d;
u32 duration[3];
};

@@ -100,6 +114,8 @@ static inline void tpm_write_index(int b
outb(value & 0xFF, base+1);
}

+extern void tpm_get_timeouts(struct tpm_chip *);
+extern void tpm_gen_interrupt(struct tpm_chip *);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern struct tpm_chip* tpm_register_hardware(struct device *,
const struct tpm_vendor_specific *);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2006-04-03 18:47    [W:0.374 / U:0.172 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site