aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tpm/tpm-chip.c4
-rw-r--r--drivers/char/tpm/tpm.h17
-rw-r--r--drivers/char/tpm/tpm_ppi.c141
-rw-r--r--drivers/char/tpm/tpm_tis.c14
4 files changed, 112 insertions, 64 deletions
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 7dc9999e2d54..64102de91ca3 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -147,7 +147,7 @@ int tpm_chip_register(struct tpm_chip *chip)
147 if (rc) 147 if (rc)
148 goto del_misc; 148 goto del_misc;
149 149
150 rc = tpm_add_ppi(&chip->dev->kobj); 150 rc = tpm_add_ppi(chip);
151 if (rc) 151 if (rc)
152 goto del_sysfs; 152 goto del_sysfs;
153 153
@@ -191,7 +191,7 @@ void tpm_chip_unregister(struct tpm_chip *chip)
191 191
192 if (chip->bios_dir) 192 if (chip->bios_dir)
193 tpm_bios_log_teardown(chip->bios_dir); 193 tpm_bios_log_teardown(chip->bios_dir);
194 tpm_remove_ppi(&chip->dev->kobj); 194 tpm_remove_ppi(chip);
195 tpm_sysfs_del_device(chip); 195 tpm_sysfs_del_device(chip);
196 196
197 tpm_dev_del_device(chip); 197 tpm_dev_del_device(chip);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 72ff18c872d3..3409acf953f3 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -27,6 +27,7 @@
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/io.h> 28#include <linux/io.h>
29#include <linux/tpm.h> 29#include <linux/tpm.h>
30#include <linux/acpi.h>
30 31
31enum tpm_const { 32enum tpm_const {
32 TPM_MINOR = 224, /* officially assigned */ 33 TPM_MINOR = 224, /* officially assigned */
@@ -94,8 +95,11 @@ struct tpm_vendor_specific {
94#define TPM_VID_WINBOND 0x1050 95#define TPM_VID_WINBOND 0x1050
95#define TPM_VID_STM 0x104A 96#define TPM_VID_STM 0x104A
96 97
98#define TPM_PPI_VERSION_LEN 3
99
97enum tpm_chip_flags { 100enum tpm_chip_flags {
98 TPM_CHIP_FLAG_REGISTERED = BIT(0), 101 TPM_CHIP_FLAG_REGISTERED = BIT(0),
102 TPM_CHIP_FLAG_PPI = BIT(1),
99}; 103};
100 104
101struct tpm_chip { 105struct tpm_chip {
@@ -114,6 +118,11 @@ struct tpm_chip {
114 118
115 struct dentry **bios_dir; 119 struct dentry **bios_dir;
116 120
121#ifdef CONFIG_ACPI
122 acpi_handle acpi_dev_handle;
123 char ppi_version[TPM_PPI_VERSION_LEN + 1];
124#endif /* CONFIG_ACPI */
125
117 struct list_head list; 126 struct list_head list;
118}; 127};
119 128
@@ -345,15 +354,15 @@ void tpm_sysfs_del_device(struct tpm_chip *chip);
345int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); 354int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
346 355
347#ifdef CONFIG_ACPI 356#ifdef CONFIG_ACPI
348extern int tpm_add_ppi(struct kobject *); 357extern int tpm_add_ppi(struct tpm_chip *chip);
349extern void tpm_remove_ppi(struct kobject *); 358extern void tpm_remove_ppi(struct tpm_chip *chip);
350#else 359#else
351static inline int tpm_add_ppi(struct kobject *parent) 360static inline int tpm_add_ppi(struct tpm_chip *chip)
352{ 361{
353 return 0; 362 return 0;
354} 363}
355 364
356static inline void tpm_remove_ppi(struct kobject *parent) 365static inline void tpm_remove_ppi(struct tpm_chip *chip)
357{ 366{
358} 367}
359#endif 368#endif
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
index 61dcc8011ec7..af48c56f642f 100644
--- a/drivers/char/tpm/tpm_ppi.c
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -1,3 +1,22 @@
1/*
2 * Copyright (C) 2012-2014 Intel Corporation
3 *
4 * Authors:
5 * Xiaoyan Zhang <xiaoyan.zhang@intel.com>
6 * Jiang Liu <jiang.liu@linux.intel.com>
7 * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
8 *
9 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
10 *
11 * This file contains implementation of the sysfs interface for PPI.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; version 2
16 * of the License.
17 */
18
19
1#include <linux/acpi.h> 20#include <linux/acpi.h>
2#include "tpm.h" 21#include "tpm.h"
3 22
@@ -12,7 +31,6 @@
12#define PPI_TPM_REQ_MAX 22 31#define PPI_TPM_REQ_MAX 22
13#define PPI_VS_REQ_START 128 32#define PPI_VS_REQ_START 128
14#define PPI_VS_REQ_END 255 33#define PPI_VS_REQ_END 255
15#define PPI_VERSION_LEN 3
16 34
17static const u8 tpm_ppi_uuid[] = { 35static const u8 tpm_ppi_uuid[] = {
18 0xA6, 0xFA, 0xDD, 0x3D, 36 0xA6, 0xFA, 0xDD, 0x3D,
@@ -22,45 +40,22 @@ static const u8 tpm_ppi_uuid[] = {
22 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53 40 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53
23}; 41};
24 42
25static char tpm_ppi_version[PPI_VERSION_LEN + 1];
26static acpi_handle tpm_ppi_handle;
27
28static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
29 void **return_value)
30{
31 union acpi_object *obj;
32
33 if (!acpi_check_dsm(handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID,
34 1 << TPM_PPI_FN_VERSION))
35 return AE_OK;
36
37 /* Cache version string */
38 obj = acpi_evaluate_dsm_typed(handle, tpm_ppi_uuid,
39 TPM_PPI_REVISION_ID, TPM_PPI_FN_VERSION,
40 NULL, ACPI_TYPE_STRING);
41 if (obj) {
42 strlcpy(tpm_ppi_version, obj->string.pointer,
43 PPI_VERSION_LEN + 1);
44 ACPI_FREE(obj);
45 }
46
47 *return_value = handle;
48
49 return AE_CTRL_TERMINATE;
50}
51
52static inline union acpi_object * 43static inline union acpi_object *
53tpm_eval_dsm(int func, acpi_object_type type, union acpi_object *argv4) 44tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type,
45 union acpi_object *argv4)
54{ 46{
55 BUG_ON(!tpm_ppi_handle); 47 BUG_ON(!ppi_handle);
56 return acpi_evaluate_dsm_typed(tpm_ppi_handle, tpm_ppi_uuid, 48 return acpi_evaluate_dsm_typed(ppi_handle, tpm_ppi_uuid,
57 TPM_PPI_REVISION_ID, func, argv4, type); 49 TPM_PPI_REVISION_ID,
50 func, argv4, type);
58} 51}
59 52
60static ssize_t tpm_show_ppi_version(struct device *dev, 53static ssize_t tpm_show_ppi_version(struct device *dev,
61 struct device_attribute *attr, char *buf) 54 struct device_attribute *attr, char *buf)
62{ 55{
63 return scnprintf(buf, PAGE_SIZE, "%s\n", tpm_ppi_version); 56 struct tpm_chip *chip = dev_get_drvdata(dev);
57
58 return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version);
64} 59}
65 60
66static ssize_t tpm_show_ppi_request(struct device *dev, 61static ssize_t tpm_show_ppi_request(struct device *dev,
@@ -68,8 +63,10 @@ static ssize_t tpm_show_ppi_request(struct device *dev,
68{ 63{
69 ssize_t size = -EINVAL; 64 ssize_t size = -EINVAL;
70 union acpi_object *obj; 65 union acpi_object *obj;
66 struct tpm_chip *chip = dev_get_drvdata(dev);
71 67
72 obj = tpm_eval_dsm(TPM_PPI_FN_GETREQ, ACPI_TYPE_PACKAGE, NULL); 68 obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ,
69 ACPI_TYPE_PACKAGE, NULL);
73 if (!obj) 70 if (!obj)
74 return -ENXIO; 71 return -ENXIO;
75 72
@@ -103,14 +100,15 @@ static ssize_t tpm_store_ppi_request(struct device *dev,
103 int func = TPM_PPI_FN_SUBREQ; 100 int func = TPM_PPI_FN_SUBREQ;
104 union acpi_object *obj, tmp; 101 union acpi_object *obj, tmp;
105 union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp); 102 union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp);
103 struct tpm_chip *chip = dev_get_drvdata(dev);
106 104
107 /* 105 /*
108 * the function to submit TPM operation request to pre-os environment 106 * the function to submit TPM operation request to pre-os environment
109 * is updated with function index from SUBREQ to SUBREQ2 since PPI 107 * is updated with function index from SUBREQ to SUBREQ2 since PPI
110 * version 1.1 108 * version 1.1
111 */ 109 */
112 if (acpi_check_dsm(tpm_ppi_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, 110 if (acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid,
113 1 << TPM_PPI_FN_SUBREQ2)) 111 TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_SUBREQ2))
114 func = TPM_PPI_FN_SUBREQ2; 112 func = TPM_PPI_FN_SUBREQ2;
115 113
116 /* 114 /*
@@ -119,7 +117,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev,
119 * string/package type. For PPI version 1.0 and 1.1, use buffer type 117 * string/package type. For PPI version 1.0 and 1.1, use buffer type
120 * for compatibility, and use package type since 1.2 according to spec. 118 * for compatibility, and use package type since 1.2 according to spec.
121 */ 119 */
122 if (strcmp(tpm_ppi_version, "1.2") < 0) { 120 if (strcmp(chip->ppi_version, "1.2") < 0) {
123 if (sscanf(buf, "%d", &req) != 1) 121 if (sscanf(buf, "%d", &req) != 1)
124 return -EINVAL; 122 return -EINVAL;
125 argv4.type = ACPI_TYPE_BUFFER; 123 argv4.type = ACPI_TYPE_BUFFER;
@@ -131,7 +129,8 @@ static ssize_t tpm_store_ppi_request(struct device *dev,
131 return -EINVAL; 129 return -EINVAL;
132 } 130 }
133 131
134 obj = tpm_eval_dsm(func, ACPI_TYPE_INTEGER, &argv4); 132 obj = tpm_eval_dsm(chip->acpi_dev_handle, func, ACPI_TYPE_INTEGER,
133 &argv4);
135 if (!obj) { 134 if (!obj) {
136 return -ENXIO; 135 return -ENXIO;
137 } else { 136 } else {
@@ -157,6 +156,7 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev,
157 .buffer.length = 0, 156 .buffer.length = 0,
158 .buffer.pointer = NULL 157 .buffer.pointer = NULL
159 }; 158 };
159 struct tpm_chip *chip = dev_get_drvdata(dev);
160 160
161 static char *info[] = { 161 static char *info[] = {
162 "None", 162 "None",
@@ -171,9 +171,10 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev,
171 * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for 171 * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
172 * compatibility, define params[3].type as buffer, if PPI version < 1.2 172 * compatibility, define params[3].type as buffer, if PPI version < 1.2
173 */ 173 */
174 if (strcmp(tpm_ppi_version, "1.2") < 0) 174 if (strcmp(chip->ppi_version, "1.2") < 0)
175 obj = &tmp; 175 obj = &tmp;
176 obj = tpm_eval_dsm(TPM_PPI_FN_GETACT, ACPI_TYPE_INTEGER, obj); 176 obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETACT,
177 ACPI_TYPE_INTEGER, obj);
177 if (!obj) { 178 if (!obj) {
178 return -ENXIO; 179 return -ENXIO;
179 } else { 180 } else {
@@ -196,8 +197,10 @@ static ssize_t tpm_show_ppi_response(struct device *dev,
196 acpi_status status = -EINVAL; 197 acpi_status status = -EINVAL;
197 union acpi_object *obj, *ret_obj; 198 union acpi_object *obj, *ret_obj;
198 u64 req, res; 199 u64 req, res;
200 struct tpm_chip *chip = dev_get_drvdata(dev);
199 201
200 obj = tpm_eval_dsm(TPM_PPI_FN_GETRSP, ACPI_TYPE_PACKAGE, NULL); 202 obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP,
203 ACPI_TYPE_PACKAGE, NULL);
201 if (!obj) 204 if (!obj)
202 return -ENXIO; 205 return -ENXIO;
203 206
@@ -248,7 +251,8 @@ cleanup:
248 return status; 251 return status;
249} 252}
250 253
251static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) 254static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start,
255 u32 end)
252{ 256{
253 int i; 257 int i;
254 u32 ret; 258 u32 ret;
@@ -264,14 +268,15 @@ static ssize_t show_ppi_operations(char *buf, u32 start, u32 end)
264 "User not required", 268 "User not required",
265 }; 269 };
266 270
267 if (!acpi_check_dsm(tpm_ppi_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, 271 if (!acpi_check_dsm(dev_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID,
268 1 << TPM_PPI_FN_GETOPR)) 272 1 << TPM_PPI_FN_GETOPR))
269 return -EPERM; 273 return -EPERM;
270 274
271 tmp.integer.type = ACPI_TYPE_INTEGER; 275 tmp.integer.type = ACPI_TYPE_INTEGER;
272 for (i = start; i <= end; i++) { 276 for (i = start; i <= end; i++) {
273 tmp.integer.value = i; 277 tmp.integer.value = i;
274 obj = tpm_eval_dsm(TPM_PPI_FN_GETOPR, ACPI_TYPE_INTEGER, &argv); 278 obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR,
279 ACPI_TYPE_INTEGER, &argv);
275 if (!obj) { 280 if (!obj) {
276 return -ENOMEM; 281 return -ENOMEM;
277 } else { 282 } else {
@@ -291,14 +296,20 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
291 struct device_attribute *attr, 296 struct device_attribute *attr,
292 char *buf) 297 char *buf)
293{ 298{
294 return show_ppi_operations(buf, 0, PPI_TPM_REQ_MAX); 299 struct tpm_chip *chip = dev_get_drvdata(dev);
300
301 return show_ppi_operations(chip->acpi_dev_handle, buf, 0,
302 PPI_TPM_REQ_MAX);
295} 303}
296 304
297static ssize_t tpm_show_ppi_vs_operations(struct device *dev, 305static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
298 struct device_attribute *attr, 306 struct device_attribute *attr,
299 char *buf) 307 char *buf)
300{ 308{
301 return show_ppi_operations(buf, PPI_VS_REQ_START, PPI_VS_REQ_END); 309 struct tpm_chip *chip = dev_get_drvdata(dev);
310
311 return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START,
312 PPI_VS_REQ_END);
302} 313}
303 314
304static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL); 315static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
@@ -323,16 +334,38 @@ static struct attribute_group ppi_attr_grp = {
323 .attrs = ppi_attrs 334 .attrs = ppi_attrs
324}; 335};
325 336
326int tpm_add_ppi(struct kobject *parent) 337int tpm_add_ppi(struct tpm_chip *chip)
327{ 338{
328 /* Cache TPM ACPI handle and version string */ 339 union acpi_object *obj;
329 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 340 int rc;
330 ppi_callback, NULL, NULL, &tpm_ppi_handle); 341
331 return tpm_ppi_handle ? sysfs_create_group(parent, &ppi_attr_grp) : 0; 342 if (!chip->acpi_dev_handle)
343 return 0;
344
345 if (!acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid,
346 TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_VERSION))
347 return 0;
348
349 /* Cache PPI version string. */
350 obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, tpm_ppi_uuid,
351 TPM_PPI_REVISION_ID, TPM_PPI_FN_VERSION,
352 NULL, ACPI_TYPE_STRING);
353 if (obj) {
354 strlcpy(chip->ppi_version, obj->string.pointer,
355 sizeof(chip->ppi_version));
356 ACPI_FREE(obj);
357 }
358
359 rc = sysfs_create_group(&chip->dev->kobj, &ppi_attr_grp);
360
361 if (!rc)
362 chip->flags |= TPM_CHIP_FLAG_PPI;
363
364 return rc;
332} 365}
333 366
334void tpm_remove_ppi(struct kobject *parent) 367void tpm_remove_ppi(struct tpm_chip *chip)
335{ 368{
336 if (tpm_ppi_handle) 369 if (chip->flags & TPM_CHIP_FLAG_PPI)
337 sysfs_remove_group(parent, &ppi_attr_grp); 370 sysfs_remove_group(&chip->dev->kobj, &ppi_attr_grp);
338} 371}
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 36f4fec11c2a..9695850d2afa 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -580,8 +580,9 @@ static void tpm_tis_remove(struct tpm_chip *chip)
580 release_locality(chip, chip->vendor.locality, 1); 580 release_locality(chip, chip->vendor.locality, 1);
581} 581}
582 582
583static int tpm_tis_init(struct device *dev, resource_size_t start, 583static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
584 resource_size_t len, unsigned int irq) 584 resource_size_t start, resource_size_t len,
585 unsigned int irq)
585{ 586{
586 u32 vendor, intfcaps, intmask; 587 u32 vendor, intfcaps, intmask;
587 int rc, i, irq_s, irq_e, probe; 588 int rc, i, irq_s, irq_e, probe;
@@ -597,6 +598,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
597 return PTR_ERR(chip); 598 return PTR_ERR(chip);
598 599
599 chip->vendor.priv = priv; 600 chip->vendor.priv = priv;
601 chip->acpi_dev_handle = acpi_dev_handle;
600 602
601 chip->vendor.iobase = devm_ioremap(dev, start, len); 603 chip->vendor.iobase = devm_ioremap(dev, start, len);
602 if (!chip->vendor.iobase) 604 if (!chip->vendor.iobase)
@@ -827,6 +829,7 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
827{ 829{
828 resource_size_t start, len; 830 resource_size_t start, len;
829 unsigned int irq = 0; 831 unsigned int irq = 0;
832 acpi_handle acpi_dev_handle = NULL;
830 833
831 start = pnp_mem_start(pnp_dev, 0); 834 start = pnp_mem_start(pnp_dev, 0);
832 len = pnp_mem_len(pnp_dev, 0); 835 len = pnp_mem_len(pnp_dev, 0);
@@ -839,7 +842,10 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
839 if (is_itpm(pnp_dev)) 842 if (is_itpm(pnp_dev))
840 itpm = true; 843 itpm = true;
841 844
842 return tpm_tis_init(&pnp_dev->dev, start, len, irq); 845 if (pnp_acpi_device(pnp_dev))
846 acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle;
847
848 return tpm_tis_init(&pnp_dev->dev, acpi_dev_handle, start, len, irq);
843} 849}
844 850
845static struct pnp_device_id tpm_pnp_tbl[] = { 851static struct pnp_device_id tpm_pnp_tbl[] = {
@@ -907,7 +913,7 @@ static int __init init_tis(void)
907 rc = PTR_ERR(pdev); 913 rc = PTR_ERR(pdev);
908 goto err_dev; 914 goto err_dev;
909 } 915 }
910 rc = tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0); 916 rc = tpm_tis_init(&pdev->dev, NULL, TIS_MEM_BASE, TIS_MEM_LEN, 0);
911 if (rc) 917 if (rc)
912 goto err_init; 918 goto err_init;
913 return 0; 919 return 0;