Added tpm2-sysfs.c that implements sysfs attributes for a TPM2
device.

Signed-off-by: Jarkko Sakkinen <jarkko.sakki...@linux.intel.com>
---
 drivers/char/tpm/Makefile        |   2 +-
 drivers/char/tpm/tpm-chip.c      |  10 +-
 drivers/char/tpm/tpm-interface.c |   1 +
 drivers/char/tpm/tpm2-commands.c |   2 +-
 drivers/char/tpm/tpm2-sysfs.c    | 242 +++++++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm2.h          |  31 +++++
 6 files changed, 284 insertions(+), 4 deletions(-)
 create mode 100644 drivers/char/tpm/tpm2-sysfs.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 253e823..9e71c43 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the kernel tpm device drivers.
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
-tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-commands.o
+tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-commands.o 
tpm2-sysfs.o
 tpm-$(CONFIG_ACPI) += tpm_ppi.o
 
 ifdef CONFIG_ACPI
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 128942b..91d8213 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -127,7 +127,10 @@ int tpm_chip_register(struct tpm_chip *chip)
        if (rc)
                return rc;
 
-       rc = tpm_sysfs_add_device(chip);
+       if (chip->tpm2)
+               rc = tpm2_sysfs_add_device(chip);
+       else
+               rc = tpm_sysfs_add_device(chip);
        if (rc)
                goto del_misc;
 
@@ -160,7 +163,10 @@ void tpm_chip_unregister(struct tpm_chip *chip)
        synchronize_rcu();
 
        tpm_dev_del_device(chip);
-       tpm_sysfs_del_device(chip);
+       if (chip->tpm2)
+               tpm2_sysfs_del_device(chip);
+       else
+               tpm_sysfs_del_device(chip);
        tpm_remove_ppi(&chip->dev->kobj);
 
        if (!chip->tpm2)
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 7a9c096..26195db 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -899,6 +899,7 @@ void tpm_remove_hardware(struct device *dev)
 
        tpm_chip_unregister(chip);
 
+
        /* write it this way to be explicit (chip->dev == dev) */
        put_device(chip->dev);
 }
diff --git a/drivers/char/tpm/tpm2-commands.c b/drivers/char/tpm/tpm2-commands.c
index a21dfd5..6365087 100644
--- a/drivers/char/tpm/tpm2-commands.c
+++ b/drivers/char/tpm/tpm2-commands.c
@@ -195,7 +195,7 @@ ssize_t tpm2_get_tpm_pt(struct device *dev, u32 
property_id,  u32* value,
        cmd.header.in = tpm2_get_tpm_pt_header;
        cmd.params.tpm2_get_tpm_pt_in.cap_id =
                cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
-       cmd.params.tpm2_get_tpm_pt_in.property_id = property_id;
+       cmd.params.tpm2_get_tpm_pt_in.property_id = cpu_to_be32(property_id);
        cmd.params.tpm2_get_tpm_pt_in.property_cnt = cpu_to_be32(1);
 
        rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc);
diff --git a/drivers/char/tpm/tpm2-sysfs.c b/drivers/char/tpm/tpm2-sysfs.c
new file mode 100644
index 0000000..a254b2c
--- /dev/null
+++ b/drivers/char/tpm/tpm2-sysfs.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ * Authors:
+ * Leendert van Doorn <leend...@watson.ibm.com>
+ * Dave Safford <saff...@watson.ibm.com>
+ * Reiner Sailer <sai...@watson.ibm.com>
+ * Kylene Hall <kjh...@us.ibm.com>
+ *
+ * Copyright (C) 2013 Obsidian Research Corp
+ * Jason Gunthorpe <jguntho...@obsidianresearch.com>
+ *
+ * sysfs filesystem inspection interface to the TPM
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+#include <linux/device.h>
+#include "tpm.h"
+
+static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       u8 digest[TPM_DIGEST_SIZE];
+       ssize_t rc;
+       int i, j;
+       char *str = buf;
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+
+       for (i = 0; i < TPM2_PLATFORM_PCR; i++) {
+               rc = tpm2_pcr_read_dev(chip, i, digest);
+               if (rc)
+                       break;
+               str += sprintf(str, "PCR-%02d: ", i);
+               for (j = 0; j < TPM_DIGEST_SIZE; j++)
+                       str += sprintf(str, "%02X ", digest[j]);
+               str += sprintf(str, "\n");
+       }
+
+       return str - buf;
+}
+static DEVICE_ATTR_RO(pcrs);
+
+static ssize_t enabled_sh_show(struct device *dev, struct device_attribute 
*attr,
+                    char *buf)
+{
+       struct tpm2_startup_clear value;
+       ssize_t rc;
+
+       rc = tpm2_get_tpm_pt(dev, TPM2_PT_STARTUP_CLEAR, (u32 *) &value,
+                            "could not retrieve STARTUP_CLEAR property");
+       if (rc)
+               return 0;
+
+       rc = sprintf(buf, "%d\n", value.sh_enable);
+       return rc;
+}
+static DEVICE_ATTR_RO(enabled_sh);
+
+static ssize_t enabled_eh_show(struct device *dev, struct device_attribute 
*attr,
+                    char *buf)
+{
+       struct tpm2_startup_clear value;
+       ssize_t rc;
+
+       rc = tpm2_get_tpm_pt(dev, TPM2_PT_STARTUP_CLEAR, (u32 *) &value,
+                            "could not retrieve STARTUP_CLEAR property");
+       if (rc)
+               return 0;
+
+       rc = sprintf(buf, "%d\n", value.eh_enable);
+       return rc;
+}
+static DEVICE_ATTR_RO(enabled_eh);
+
+static ssize_t owned_sh_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct tpm2_permanent value;
+       ssize_t rc;
+
+       rc = tpm2_get_tpm_pt(dev, TPM2_PT_PERMANENT, (u32 *) &value,
+                            "could not retrieve PERMANENT property");
+       if (rc)
+               return 0;
+
+       rc = sprintf(buf, "%d\n", value.owner_auth_set);
+       return rc;
+}
+static DEVICE_ATTR_RO(owned_sh);
+
+static ssize_t owned_eh_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct tpm2_permanent value;
+       ssize_t rc;
+
+       rc = tpm2_get_tpm_pt(dev, TPM2_PT_PERMANENT, (u32 *) &value,
+                            "could not retrieve PERMANENT property");
+       if (rc)
+               return 0;
+
+       rc = sprintf(buf, "%d\n", value.endorsement_auth_set);
+       return rc;
+}
+static DEVICE_ATTR_RO(owned_eh);
+
+static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       u32 value1;
+       u32 value2;
+       ssize_t rc;
+       char *str = buf;
+
+       rc = tpm2_get_tpm_pt(dev, TPM2_PT_MANUFACTURER, (u32 *) &value1,
+                            "could not retrieve MANUFACTURER property");
+       if (rc)
+               return 0;
+
+       str += sprintf(str, "Manufacturer: 0x%08x\n", be32_to_cpu(value1));
+       str += sprintf(str, "TCG version: 2.0\n");
+
+       rc = tpm2_get_tpm_pt(dev, TPM2_PT_FIRMWARE_VERSION_1, (u32 *) &value1,
+                            "could not retrieve FIRMWARE_VERSION_1 property");
+       if (rc)
+               return 0;
+
+       rc = tpm2_get_tpm_pt(dev, TPM2_PT_FIRMWARE_VERSION_2, (u32 *) &value2,
+                            "could not retrieve FIRMWARE_VERSION_2 property");
+       if (rc)
+               return 0;
+
+       str += sprintf(str, "Firmware version: 0x%08x 0x%08x\n", value1, 
value2);
+
+       return str - buf;
+}
+static DEVICE_ATTR_RO(caps);
+
+static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+       if (chip == NULL)
+               return 0;
+
+       chip->ops->cancel(chip);
+       return count;
+}
+static DEVICE_ATTR_WO(cancel);
+
+static ssize_t durations_show(struct device *dev, struct device_attribute 
*attr,
+                             char *buf)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+
+       if (chip->vendor.duration[TPM_LONG] == 0)
+               return 0;
+
+       return sprintf(buf, "%d %d %d [%s]\n",
+                      jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
+                      jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
+                      jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
+                      chip->vendor.duration_adjusted
+                      ? "adjusted" : "original");
+}
+static DEVICE_ATTR_RO(durations);
+
+static ssize_t timeouts_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d %d %d %d [%s]\n",
+                      jiffies_to_usecs(chip->vendor.timeout_a),
+                      jiffies_to_usecs(chip->vendor.timeout_b),
+                      jiffies_to_usecs(chip->vendor.timeout_c),
+                      jiffies_to_usecs(chip->vendor.timeout_d),
+                      chip->vendor.timeout_adjusted
+                      ? "adjusted" : "original");
+}
+static DEVICE_ATTR_RO(timeouts);
+
+static ssize_t version_show(struct device *dev, struct device_attribute *attr,
+                          char *buf)
+{
+       char *str = buf;
+
+       str += sprintf(str, "2.0\n");
+
+       return str - buf;
+}
+
+static DEVICE_ATTR_RO(version);
+
+
+static ssize_t tpm2_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", chip->tpm2);
+}
+static DEVICE_ATTR_RO(tpm2);
+
+static struct attribute *tpm_dev_attrs[] = {
+       &dev_attr_pcrs.attr,
+       &dev_attr_enabled_sh.attr,
+       &dev_attr_enabled_eh.attr,
+       &dev_attr_owned_sh.attr,
+       &dev_attr_owned_eh.attr,
+       &dev_attr_caps.attr,
+       &dev_attr_cancel.attr,
+       &dev_attr_durations.attr,
+       &dev_attr_timeouts.attr,
+       &dev_attr_version.attr,
+       &dev_attr_tpm2.attr,
+       NULL,
+};
+
+static const struct attribute_group tpm_dev_group = {
+       .attrs = tpm_dev_attrs,
+};
+
+int tpm2_sysfs_add_device(struct tpm_chip *chip)
+{
+       int err;
+       err = sysfs_create_group(&chip->dev->kobj,
+                                &tpm_dev_group);
+
+       if (err)
+               dev_err(chip->dev,
+                       "failed to create sysfs attributes, %d\n", err);
+       return err;
+}
+
+void tpm2_sysfs_del_device(struct tpm_chip *chip)
+{
+       sysfs_remove_group(&chip->dev->kobj, &tpm_dev_group);
+}
diff --git a/drivers/char/tpm/tpm2.h b/drivers/char/tpm/tpm2.h
index ba7c053..7a1502a 100644
--- a/drivers/char/tpm/tpm2.h
+++ b/drivers/char/tpm/tpm2.h
@@ -59,6 +59,34 @@ enum tpm2_capabilities {
        TPM2_CAP_TPM_PROPERTIES = 6,
 };
 
+enum tpm2_tpm_properties {
+       TPM2_PT_MANUFACTURER            = 0x00000105,
+       TPM2_PT_FIRMWARE_VERSION_1      = 0x00000111,
+       TPM2_PT_FIRMWARE_VERSION_2      = 0x00000111,
+       TPM2_PT_PERMANENT               = 0x00000200,
+       TPM2_PT_STARTUP_CLEAR           = 0x00000201,
+};
+
+struct tpm2_permanent {
+       unsigned int owner_auth_set             : 1;
+       unsigned int endorsement_auth_set       : 1;
+       unsigned int lockout_auth_set           : 1;
+       unsigned int reserved1                  : 5;
+       unsigned int disable_clear              : 1;
+       unsigned int in_lockout                 : 1;
+       unsigned int tpm_generated_eps          : 1;
+       unsigned int reserved2                  : 21;
+};
+
+struct tpm2_startup_clear {
+       unsigned int ph_enable                  : 1;
+       unsigned int sh_enable                  : 1;
+       unsigned int eh_enable                  : 1;
+       unsigned int ph_enable_nv               : 1;
+       unsigned int reserved                   : 27;
+       unsigned int orderly                    : 1;
+};
+
 struct tpm_chip;
 
 #define TPM2_CC_FIRST  0x11F
@@ -74,4 +102,7 @@ int tpm2_do_selftest(struct tpm_chip *chip);
 int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max);
 void tpm2_gen_interrupt(struct tpm_chip *chip);
 
+int tpm2_sysfs_add_device(struct tpm_chip *chip);
+void tpm2_sysfs_del_device(struct tpm_chip *chip);
+
 #endif /* __DRIVERS_CHAR_TPM2_H__ */
-- 
2.1.0

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

Reply via email to