[PATCH v5 2/2] driver: add PPI support in tpm driver

2012-08-21 Thread xiaoyan . zhang
From: Xiaoyan Zhang 

The Physical Presence Interface enables the OS and the BIOS to cooperate and
provides a simple and straightforward platform user experience for
administering the TPM without sacrificing security.

V2: separate the patch out in a separate source file,
add #ifdef CONFIG_ACPI so it compiles out on ppc,
use standard error instead of ACPI error as return code of show/store fns.
V3: move #ifdef CONFIG_ACPI from .c file to .h file.
V4: move tpm_ppi code from tpm module to tpm_bios module.
V5: modify sys_add_ppi() so that ppi_attr_grp doesn't need to be exported

Signed-off-by: Xiaoyan Zhang 
---
 drivers/char/tpm/Makefile  |2 +-
 drivers/char/tpm/tpm.c |5 +
 drivers/char/tpm/tpm.h |9 +
 drivers/char/tpm/tpm_ppi.c |  460 
 4 files changed, 475 insertions(+), 1 deletions(-)
 create mode 100644 drivers/char/tpm/tpm_ppi.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 9080cc4..5b3fc8b 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -4,7 +4,7 @@
 obj-$(CONFIG_TCG_TPM) += tpm.o
 ifdef CONFIG_ACPI
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
-   tpm_bios-objs += tpm_eventlog.o tpm_acpi.o
+   tpm_bios-objs += tpm_eventlog.o tpm_acpi.o tpm_ppi.o
 else
 ifdef CONFIG_TCG_IBMVTPM
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 0a75638..39526c0 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -1476,6 +1476,11 @@ struct tpm_chip *tpm_register_hardware(struct device 
*dev,
goto put_device;
}
 
+   if (sys_add_ppi(>kobj)) {
+   misc_deregister(>vendor.miscdev);
+   goto put_device;
+   }
+
chip->bios_dir = tpm_bios_log_setup(devname);
 
/* Make chip available */
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f1af738..02c266a 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -327,3 +327,12 @@ extern int tpm_pm_suspend(struct device *);
 extern int tpm_pm_resume(struct device *);
 extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
 wait_queue_head_t *);
+
+#ifdef CONFIG_ACPI
+extern ssize_t sys_add_ppi(struct kobject *parent);
+#else
+static inline ssize_t sys_add_ppi(struct kobject *parent)
+{
+   return 0;
+}
+#endif
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
new file mode 100644
index 000..440fa1c
--- /dev/null
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -0,0 +1,460 @@
+#include 
+#include 
+#include "tpm.h"
+
+static const u8 tpm_ppi_uuid[] = {
+   0xA6, 0xFA, 0xDD, 0x3D,
+   0x1B, 0x36,
+   0xB4, 0x4E,
+   0xA4, 0x24,
+   0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53
+};
+static char *tpm_device_name = "TPM";
+
+#define TPM_PPI_REVISION_ID1
+#define TPM_PPI_FN_VERSION 1
+#define TPM_PPI_FN_SUBREQ  2
+#define TPM_PPI_FN_GETREQ  3
+#define TPM_PPI_FN_GETACT  4
+#define TPM_PPI_FN_GETRSP  5
+#define TPM_PPI_FN_SUBREQ2 7
+#define TPM_PPI_FN_GETOPR  8
+#define PPI_TPM_REQ_MAX22
+#define PPI_VS_REQ_START   128
+#define PPI_VS_REQ_END 255
+#define PPI_VERSION_LEN3
+
+static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
+   void **return_value)
+{
+   acpi_status status;
+   struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+   status = acpi_get_name(handle, ACPI_FULL_PATHNAME, );
+   if (strstr(buffer.pointer, context) != NULL) {
+   *return_value = handle;
+   kfree(buffer.pointer);
+   return AE_CTRL_TERMINATE;
+   }
+   return AE_OK;
+}
+
+static inline void ppi_assign_params(union acpi_object params[4],
+u64 function_num)
+{
+   params[0].type = ACPI_TYPE_BUFFER;
+   params[0].buffer.length = sizeof(tpm_ppi_uuid);
+   params[0].buffer.pointer = (char *)tpm_ppi_uuid;
+   params[1].type = ACPI_TYPE_INTEGER;
+   params[1].integer.value = TPM_PPI_REVISION_ID;
+   params[2].type = ACPI_TYPE_INTEGER;
+   params[2].integer.value = function_num;
+   params[3].type = ACPI_TYPE_PACKAGE;
+   params[3].package.count = 0;
+   params[3].package.elements = NULL;
+}
+
+ssize_t tpm_show_ppi_version(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   acpi_handle handle;
+   acpi_status status;
+   struct acpi_object_list input;
+   struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+   union acpi_object params[4];
+   union acpi_object *obj;
+
+   input.count = 4;
+   ppi_assign_params(params, TPM_PPI_FN_VERSION);
+   input.pointer = params;
+   status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ACPI_UINT32_MAX, 

[PATCH v5 2/2] driver: add PPI support in tpm driver

2012-08-21 Thread xiaoyan . zhang
From: Xiaoyan Zhang xiaoyan.zh...@intel.com

The Physical Presence Interface enables the OS and the BIOS to cooperate and
provides a simple and straightforward platform user experience for
administering the TPM without sacrificing security.

V2: separate the patch out in a separate source file,
add #ifdef CONFIG_ACPI so it compiles out on ppc,
use standard error instead of ACPI error as return code of show/store fns.
V3: move #ifdef CONFIG_ACPI from .c file to .h file.
V4: move tpm_ppi code from tpm module to tpm_bios module.
V5: modify sys_add_ppi() so that ppi_attr_grp doesn't need to be exported

Signed-off-by: Xiaoyan Zhang xiaoyan.zh...@intel.com
---
 drivers/char/tpm/Makefile  |2 +-
 drivers/char/tpm/tpm.c |5 +
 drivers/char/tpm/tpm.h |9 +
 drivers/char/tpm/tpm_ppi.c |  460 
 4 files changed, 475 insertions(+), 1 deletions(-)
 create mode 100644 drivers/char/tpm/tpm_ppi.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 9080cc4..5b3fc8b 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -4,7 +4,7 @@
 obj-$(CONFIG_TCG_TPM) += tpm.o
 ifdef CONFIG_ACPI
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
-   tpm_bios-objs += tpm_eventlog.o tpm_acpi.o
+   tpm_bios-objs += tpm_eventlog.o tpm_acpi.o tpm_ppi.o
 else
 ifdef CONFIG_TCG_IBMVTPM
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 0a75638..39526c0 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -1476,6 +1476,11 @@ struct tpm_chip *tpm_register_hardware(struct device 
*dev,
goto put_device;
}
 
+   if (sys_add_ppi(dev-kobj)) {
+   misc_deregister(chip-vendor.miscdev);
+   goto put_device;
+   }
+
chip-bios_dir = tpm_bios_log_setup(devname);
 
/* Make chip available */
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f1af738..02c266a 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -327,3 +327,12 @@ extern int tpm_pm_suspend(struct device *);
 extern int tpm_pm_resume(struct device *);
 extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
 wait_queue_head_t *);
+
+#ifdef CONFIG_ACPI
+extern ssize_t sys_add_ppi(struct kobject *parent);
+#else
+static inline ssize_t sys_add_ppi(struct kobject *parent)
+{
+   return 0;
+}
+#endif
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
new file mode 100644
index 000..440fa1c
--- /dev/null
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -0,0 +1,460 @@
+#include linux/acpi.h
+#include acpi/acpi_drivers.h
+#include tpm.h
+
+static const u8 tpm_ppi_uuid[] = {
+   0xA6, 0xFA, 0xDD, 0x3D,
+   0x1B, 0x36,
+   0xB4, 0x4E,
+   0xA4, 0x24,
+   0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53
+};
+static char *tpm_device_name = TPM;
+
+#define TPM_PPI_REVISION_ID1
+#define TPM_PPI_FN_VERSION 1
+#define TPM_PPI_FN_SUBREQ  2
+#define TPM_PPI_FN_GETREQ  3
+#define TPM_PPI_FN_GETACT  4
+#define TPM_PPI_FN_GETRSP  5
+#define TPM_PPI_FN_SUBREQ2 7
+#define TPM_PPI_FN_GETOPR  8
+#define PPI_TPM_REQ_MAX22
+#define PPI_VS_REQ_START   128
+#define PPI_VS_REQ_END 255
+#define PPI_VERSION_LEN3
+
+static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
+   void **return_value)
+{
+   acpi_status status;
+   struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+   status = acpi_get_name(handle, ACPI_FULL_PATHNAME, buffer);
+   if (strstr(buffer.pointer, context) != NULL) {
+   *return_value = handle;
+   kfree(buffer.pointer);
+   return AE_CTRL_TERMINATE;
+   }
+   return AE_OK;
+}
+
+static inline void ppi_assign_params(union acpi_object params[4],
+u64 function_num)
+{
+   params[0].type = ACPI_TYPE_BUFFER;
+   params[0].buffer.length = sizeof(tpm_ppi_uuid);
+   params[0].buffer.pointer = (char *)tpm_ppi_uuid;
+   params[1].type = ACPI_TYPE_INTEGER;
+   params[1].integer.value = TPM_PPI_REVISION_ID;
+   params[2].type = ACPI_TYPE_INTEGER;
+   params[2].integer.value = function_num;
+   params[3].type = ACPI_TYPE_PACKAGE;
+   params[3].package.count = 0;
+   params[3].package.elements = NULL;
+}
+
+ssize_t tpm_show_ppi_version(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   acpi_handle handle;
+   acpi_status status;
+   struct acpi_object_list input;
+   struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+   union acpi_object params[4];
+   union acpi_object *obj;
+
+   input.count = 4;
+   ppi_assign_params(params, TPM_PPI_FN_VERSION);
+   input.pointer = params;
+   status =