Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932067AbbDAM3T (ORCPT ); Wed, 1 Apr 2015 08:29:19 -0400 Received: from mga11.intel.com ([192.55.52.93]:44406 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752850AbbDAM3Q (ORCPT ); Wed, 1 Apr 2015 08:29:16 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.11,503,1422950400"; d="scan'208";a="549523814" From: Jarkko Sakkinen To: Peter Huewe , Ashley Lai , Marcel Selhorst Cc: tpmdd-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org, christophe.ricard@gmail.com, jason.gunthorpe@obsidianresearch.com, stefanb@linux.vnet.ibm.com, Jarkko Sakkinen Subject: [PATCH] tpm: unified PPI interface for TPM 1.x/2.0 devices Date: Wed, 1 Apr 2015 15:28:52 +0300 Message-Id: <1427891332-16709-1-git-send-email-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.1.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9878 Lines: 326 Added PPI interface to the character device. PPI interface is also kept in the pdev for backwards compatibility. Signed-off-by: Jarkko Sakkinen --- 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 -- 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/