lkml.org 
[lkml]   [2015]   [Apr]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH] tpm: unified PPI interface for TPM 1.x/2.0 devices
Date
Added PPI interface to the character device. PPI interface is also kept
in the pdev for backwards compatibility.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
drivers/char/tpm/tpm-chip.c | 16 +++---
drivers/char/tpm/tpm-interface.c | 1 +
drivers/char/tpm/tpm.h | 3 +-
drivers/char/tpm/tpm_ppi.c | 105 ++++++++++++++++++++++++++++++++-------
4 files changed, 97 insertions(+), 28 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 283f00a..44f39be 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -181,12 +181,6 @@ static int tpm1_chip_register(struct tpm_chip *chip)
if (rc)
return rc;

- rc = tpm_add_ppi(chip);
- if (rc) {
- tpm_sysfs_del_device(chip);
- return rc;
- }
-
chip->bios_dir = tpm_bios_log_setup(chip->devname);

return 0;
@@ -200,8 +194,6 @@ static void tpm1_chip_unregister(struct tpm_chip *chip)
if (chip->bios_dir)
tpm_bios_log_teardown(chip->bios_dir);

- tpm_remove_ppi(chip);
-
tpm_sysfs_del_device(chip);
}

@@ -224,6 +216,10 @@ int tpm_chip_register(struct tpm_chip *chip)
if (rc)
return rc;

+ rc = tpm_add_ppi(chip);
+ if (rc)
+ goto out_err;
+
rc = tpm_dev_add_device(chip);
if (rc)
goto out_err;
@@ -237,6 +233,7 @@ int tpm_chip_register(struct tpm_chip *chip)

return 0;
out_err:
+ tpm_remove_ppi(chip);
tpm1_chip_unregister(chip);
return rc;
}
@@ -262,7 +259,8 @@ void tpm_chip_unregister(struct tpm_chip *chip)
spin_unlock(&driver_lock);
synchronize_rcu();

- tpm1_chip_unregister(chip);
tpm_dev_del_device(chip);
+ tpm_remove_ppi(chip);
+ tpm1_chip_unregister(chip);
}
EXPORT_SYMBOL_GPL(tpm_chip_unregister);
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index e85d341..aa813ff 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1038,6 +1038,7 @@ static int __init tpm_init(void)
return rc;
}

+ tpm_ppi_init(tpm_class);
return 0;
}

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f8319a0..65872a5 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -182,7 +182,7 @@ struct tpm_chip {
struct list_head list;
};

-#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
+#define to_tpm_chip(n) container_of(dev, struct tpm_chip, dev)

static inline void tpm_chip_put(struct tpm_chip *chip)
{
@@ -411,6 +411,7 @@ void tpm_sysfs_del_device(struct tpm_chip *chip);

int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);

+void tpm_ppi_init(struct class *tpm_class);
#ifdef CONFIG_ACPI
extern int tpm_add_ppi(struct tpm_chip *chip);
extern void tpm_remove_ppi(struct tpm_chip *chip);
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
index 6ca9b5d..517a8b2 100644
--- a/drivers/char/tpm/tpm_ppi.c
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -50,10 +50,23 @@ tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type,
func, argv4, type);
}

+static struct tpm_chip *ppi_dev_to_chip(struct device *dev)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ chip = to_tpm_chip(chip);
+
+ return chip;
+}
+
static ssize_t tpm_show_ppi_version(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = ppi_dev_to_chip(dev);
+
+ if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+ return -EINVAL;

return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version);
}
@@ -63,7 +76,10 @@ static ssize_t tpm_show_ppi_request(struct device *dev,
{
ssize_t size = -EINVAL;
union acpi_object *obj;
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = ppi_dev_to_chip(dev);
+
+ if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+ return -EINVAL;

obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ,
ACPI_TYPE_PACKAGE, NULL);
@@ -100,7 +116,10 @@ static ssize_t tpm_store_ppi_request(struct device *dev,
int func = TPM_PPI_FN_SUBREQ;
union acpi_object *obj, tmp;
union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp);
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = ppi_dev_to_chip(dev);
+
+ if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+ return -EINVAL;

/*
* the function to submit TPM operation request to pre-os environment
@@ -156,7 +175,7 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev,
.buffer.length = 0,
.buffer.pointer = NULL
};
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = ppi_dev_to_chip(dev);

static char *info[] = {
"None",
@@ -166,6 +185,9 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev,
"Error",
};

+ if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+ return -EINVAL;
+
/*
* PPI spec defines params[3].type as empty package, but some platforms
* (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
@@ -197,7 +219,10 @@ static ssize_t tpm_show_ppi_response(struct device *dev,
acpi_status status = -EINVAL;
union acpi_object *obj, *ret_obj;
u64 req, res;
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = ppi_dev_to_chip(dev);
+
+ if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+ return -EINVAL;

obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP,
ACPI_TYPE_PACKAGE, NULL);
@@ -251,7 +276,7 @@ cleanup:
return status;
}

-static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start,
+static ssize_t show_ppi_operations(struct tpm_chip *chip, char *buf, u32 start,
u32 end)
{
int i;
@@ -268,14 +293,17 @@ static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start,
"User not required",
};

- if (!acpi_check_dsm(dev_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID,
- 1 << TPM_PPI_FN_GETOPR))
+ if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+ return -EINVAL;
+
+ if (!acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid,
+ TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_GETOPR))
return -EPERM;

tmp.integer.type = ACPI_TYPE_INTEGER;
for (i = start; i <= end; i++) {
tmp.integer.value = i;
- obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR,
+ obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETOPR,
ACPI_TYPE_INTEGER, &argv);
if (!obj) {
return -ENOMEM;
@@ -296,22 +324,57 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = ppi_dev_to_chip(dev);

- return show_ppi_operations(chip->acpi_dev_handle, buf, 0,
- PPI_TPM_REQ_MAX);
+ if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+ return -EINVAL;
+
+ return show_ppi_operations(chip, buf, 0, PPI_TPM_REQ_MAX);
}

static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct tpm_chip *chip = ppi_dev_to_chip(dev);
+
+ if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+ return -EINVAL;
+
+ return show_ppi_operations(chip, buf, PPI_VS_REQ_START, PPI_VS_REQ_END);
+}
+
+static DEVICE_ATTR(ppi_version, S_IRUGO, tpm_show_ppi_version, NULL);
+static DEVICE_ATTR(ppi_request, S_IRUGO | S_IWUSR | S_IWGRP,
+ tpm_show_ppi_request, tpm_store_ppi_request);
+static DEVICE_ATTR(ppi_transition_action, S_IRUGO,
+ tpm_show_ppi_transition_action, NULL);
+static DEVICE_ATTR(ppi_response, S_IRUGO, tpm_show_ppi_response, NULL);
+static DEVICE_ATTR(ppi_tcg_operations, S_IRUGO, tpm_show_ppi_tcg_operations,
+ NULL);
+static DEVICE_ATTR(ppi_vs_operations, S_IRUGO, tpm_show_ppi_vs_operations,
+ NULL);
+
+static struct attribute *tpm_attrs[] = {
+ &dev_attr_ppi_version.attr,
+ &dev_attr_ppi_request.attr,
+ &dev_attr_ppi_transition_action.attr,
+ &dev_attr_ppi_response.attr,
+ &dev_attr_ppi_tcg_operations.attr,
+ &dev_attr_ppi_vs_operations.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(tpm);

- return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START,
- PPI_VS_REQ_END);
+void __init tpm_ppi_init(struct class *tpm_class)
+{
+ tpm_class->dev_groups = tpm_groups;
}

+/* Legacy attributes and operations for backwards compatibility. These are
+ * only for TPM 1.x and are attached to the platform device.
+ */
+
static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
static DEVICE_ATTR(request, S_IRUGO | S_IWUSR | S_IWGRP,
tpm_show_ppi_request, tpm_store_ppi_request);
@@ -327,8 +390,10 @@ static struct attribute *ppi_attrs[] = {
&dev_attr_transition_action.attr,
&dev_attr_response.attr,
&dev_attr_tcg_operations.attr,
- &dev_attr_vs_operations.attr, NULL,
+ &dev_attr_vs_operations.attr,
+ NULL,
};
+
static struct attribute_group ppi_attr_grp = {
.name = "ppi",
.attrs = ppi_attrs
@@ -337,7 +402,7 @@ static struct attribute_group ppi_attr_grp = {
int tpm_add_ppi(struct tpm_chip *chip)
{
union acpi_object *obj;
- int rc;
+ int rc = 0;

if (!chip->acpi_dev_handle)
return 0;
@@ -356,7 +421,8 @@ int tpm_add_ppi(struct tpm_chip *chip)
ACPI_FREE(obj);
}

- rc = sysfs_create_group(&chip->pdev->kobj, &ppi_attr_grp);
+ if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
+ rc = sysfs_create_group(&chip->pdev->kobj, &ppi_attr_grp);

if (!rc)
chip->flags |= TPM_CHIP_FLAG_PPI;
@@ -366,6 +432,9 @@ int tpm_add_ppi(struct tpm_chip *chip)

void tpm_remove_ppi(struct tpm_chip *chip)
{
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
+ return;
+
if (chip->flags & TPM_CHIP_FLAG_PPI)
sysfs_remove_group(&chip->pdev->kobj, &ppi_attr_grp);
}
--
1.9.1


\
 
 \ /
  Last update: 2015-04-01 15:01    [W:0.072 / U:0.056 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site