diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-05 18:32:38 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-05 18:32:38 -0500 |
commit | 1873499e13648a2dd01a394ed3217c9290921b3d (patch) | |
tree | 3a662aadb3c02bbce2e9231a90da6e98b54d33d4 /drivers/char | |
parent | 3460b01b12aaf0011cb30f6f502edd05752f70eb (diff) | |
parent | ba94c3ff20c9c179f2a80f0e4c71e1571ebbf5c7 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem update from James Morris:
"This is mostly maintenance updates across the subsystem, with a
notable update for TPM 2.0, and addition of Jarkko Sakkinen as a
maintainer of that"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (40 commits)
apparmor: clarify CRYPTO dependency
selinux: Use a kmem_cache for allocation struct file_security_struct
selinux: ioctl_has_perm should be static
selinux: use sprintf return value
selinux: use kstrdup() in security_get_bools()
selinux: use kmemdup in security_sid_to_context_core()
selinux: remove pointless cast in selinux_inode_setsecurity()
selinux: introduce security_context_str_to_sid
selinux: do not check open perm on ftruncate call
selinux: change CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE default
KEYS: Merge the type-specific data with the payload data
KEYS: Provide a script to extract a module signature
KEYS: Provide a script to extract the sys cert list from a vmlinux file
keys: Be more consistent in selection of union members used
certs: add .gitignore to stop git nagging about x509_certificate_list
KEYS: use kvfree() in add_key
Smack: limited capability for changing process label
TPM: remove unnecessary little endian conversion
vTPM: support little endian guests
char: Drop owner assignment from i2c_driver
...
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/tpm/st33zp24/Kconfig | 2 | ||||
-rw-r--r-- | drivers/char/tpm/st33zp24/i2c.c | 1 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-chip.c | 24 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 76 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 134 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 250 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 39 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_eventlog.c | 78 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_eventlog.h | 6 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_i2c_atmel.c | 1 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_i2c_infineon.c | 1 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_i2c_nuvoton.c | 1 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_ibmvtpm.c | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_of.c | 6 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_ppi.c | 34 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 192 |
16 files changed, 720 insertions, 127 deletions
diff --git a/drivers/char/tpm/st33zp24/Kconfig b/drivers/char/tpm/st33zp24/Kconfig index 09cb727864f0..19c007461d1c 100644 --- a/drivers/char/tpm/st33zp24/Kconfig +++ b/drivers/char/tpm/st33zp24/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config TCG_TIS_ST33ZP24 | 1 | config TCG_TIS_ST33ZP24 |
2 | tristate "STMicroelectronics TPM Interface Specification 1.2 Interface" | 2 | tristate "STMicroelectronics TPM Interface Specification 1.2 Interface" |
3 | depends on GPIOLIB | 3 | depends on GPIOLIB || COMPILE_TEST |
4 | ---help--- | 4 | ---help--- |
5 | STMicroelectronics ST33ZP24 core driver. It implements the core | 5 | STMicroelectronics ST33ZP24 core driver. It implements the core |
6 | TPM1.2 logic and hooks into the TPM kernel APIs. Physical layers will | 6 | TPM1.2 logic and hooks into the TPM kernel APIs. Physical layers will |
diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c index ad1ee180e0c2..309d2767c6a1 100644 --- a/drivers/char/tpm/st33zp24/i2c.c +++ b/drivers/char/tpm/st33zp24/i2c.c | |||
@@ -258,7 +258,6 @@ static SIMPLE_DEV_PM_OPS(st33zp24_i2c_ops, st33zp24_pm_suspend, | |||
258 | 258 | ||
259 | static struct i2c_driver st33zp24_i2c_driver = { | 259 | static struct i2c_driver st33zp24_i2c_driver = { |
260 | .driver = { | 260 | .driver = { |
261 | .owner = THIS_MODULE, | ||
262 | .name = TPM_ST33_I2C, | 261 | .name = TPM_ST33_I2C, |
263 | .pm = &st33zp24_i2c_ops, | 262 | .pm = &st33zp24_i2c_ops, |
264 | .of_match_table = of_match_ptr(of_st33zp24_i2c_match), | 263 | .of_match_table = of_match_ptr(of_st33zp24_i2c_match), |
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 1082d4bb016a..f26b0ae23bea 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c | |||
@@ -119,6 +119,9 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, | |||
119 | chip->dev.class = tpm_class; | 119 | chip->dev.class = tpm_class; |
120 | chip->dev.release = tpm_dev_release; | 120 | chip->dev.release = tpm_dev_release; |
121 | chip->dev.parent = chip->pdev; | 121 | chip->dev.parent = chip->pdev; |
122 | #ifdef CONFIG_ACPI | ||
123 | chip->dev.groups = chip->groups; | ||
124 | #endif | ||
122 | 125 | ||
123 | if (chip->dev_num == 0) | 126 | if (chip->dev_num == 0) |
124 | chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR); | 127 | chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR); |
@@ -182,12 +185,6 @@ static int tpm1_chip_register(struct tpm_chip *chip) | |||
182 | if (rc) | 185 | if (rc) |
183 | return rc; | 186 | return rc; |
184 | 187 | ||
185 | rc = tpm_add_ppi(chip); | ||
186 | if (rc) { | ||
187 | tpm_sysfs_del_device(chip); | ||
188 | return rc; | ||
189 | } | ||
190 | |||
191 | chip->bios_dir = tpm_bios_log_setup(chip->devname); | 188 | chip->bios_dir = tpm_bios_log_setup(chip->devname); |
192 | 189 | ||
193 | return 0; | 190 | return 0; |
@@ -201,8 +198,6 @@ static void tpm1_chip_unregister(struct tpm_chip *chip) | |||
201 | if (chip->bios_dir) | 198 | if (chip->bios_dir) |
202 | tpm_bios_log_teardown(chip->bios_dir); | 199 | tpm_bios_log_teardown(chip->bios_dir); |
203 | 200 | ||
204 | tpm_remove_ppi(chip); | ||
205 | |||
206 | tpm_sysfs_del_device(chip); | 201 | tpm_sysfs_del_device(chip); |
207 | } | 202 | } |
208 | 203 | ||
@@ -225,10 +220,20 @@ int tpm_chip_register(struct tpm_chip *chip) | |||
225 | if (rc) | 220 | if (rc) |
226 | return rc; | 221 | return rc; |
227 | 222 | ||
223 | tpm_add_ppi(chip); | ||
224 | |||
228 | rc = tpm_dev_add_device(chip); | 225 | rc = tpm_dev_add_device(chip); |
229 | if (rc) | 226 | if (rc) |
230 | goto out_err; | 227 | goto out_err; |
231 | 228 | ||
229 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { | ||
230 | rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj, | ||
231 | &chip->dev.kobj, | ||
232 | "ppi"); | ||
233 | if (rc) | ||
234 | goto out_err; | ||
235 | } | ||
236 | |||
232 | /* Make the chip available. */ | 237 | /* Make the chip available. */ |
233 | spin_lock(&driver_lock); | 238 | spin_lock(&driver_lock); |
234 | list_add_rcu(&chip->list, &tpm_chip_list); | 239 | list_add_rcu(&chip->list, &tpm_chip_list); |
@@ -263,6 +268,9 @@ void tpm_chip_unregister(struct tpm_chip *chip) | |||
263 | spin_unlock(&driver_lock); | 268 | spin_unlock(&driver_lock); |
264 | synchronize_rcu(); | 269 | synchronize_rcu(); |
265 | 270 | ||
271 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) | ||
272 | sysfs_remove_link(&chip->pdev->kobj, "ppi"); | ||
273 | |||
266 | tpm1_chip_unregister(chip); | 274 | tpm1_chip_unregister(chip); |
267 | tpm_dev_del_device(chip); | 275 | tpm_dev_del_device(chip); |
268 | } | 276 | } |
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index e85d3416d899..c50637db3a8a 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
@@ -666,6 +666,30 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | |||
666 | } | 666 | } |
667 | 667 | ||
668 | /** | 668 | /** |
669 | * tpm_is_tpm2 - is the chip a TPM2 chip? | ||
670 | * @chip_num: tpm idx # or ANY | ||
671 | * | ||
672 | * Returns < 0 on error, and 1 or 0 on success depending whether the chip | ||
673 | * is a TPM2 chip. | ||
674 | */ | ||
675 | int tpm_is_tpm2(u32 chip_num) | ||
676 | { | ||
677 | struct tpm_chip *chip; | ||
678 | int rc; | ||
679 | |||
680 | chip = tpm_chip_find_get(chip_num); | ||
681 | if (chip == NULL) | ||
682 | return -ENODEV; | ||
683 | |||
684 | rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0; | ||
685 | |||
686 | tpm_chip_put(chip); | ||
687 | |||
688 | return rc; | ||
689 | } | ||
690 | EXPORT_SYMBOL_GPL(tpm_is_tpm2); | ||
691 | |||
692 | /** | ||
669 | * tpm_pcr_read - read a pcr value | 693 | * tpm_pcr_read - read a pcr value |
670 | * @chip_num: tpm idx # or ANY | 694 | * @chip_num: tpm idx # or ANY |
671 | * @pcr_idx: pcr idx to retrieve | 695 | * @pcr_idx: pcr idx to retrieve |
@@ -1021,6 +1045,58 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) | |||
1021 | } | 1045 | } |
1022 | EXPORT_SYMBOL_GPL(tpm_get_random); | 1046 | EXPORT_SYMBOL_GPL(tpm_get_random); |
1023 | 1047 | ||
1048 | /** | ||
1049 | * tpm_seal_trusted() - seal a trusted key | ||
1050 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | ||
1051 | * @options: authentication values and other options | ||
1052 | * @payload: the key data in clear and encrypted form | ||
1053 | * | ||
1054 | * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips | ||
1055 | * are supported. | ||
1056 | */ | ||
1057 | int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload, | ||
1058 | struct trusted_key_options *options) | ||
1059 | { | ||
1060 | struct tpm_chip *chip; | ||
1061 | int rc; | ||
1062 | |||
1063 | chip = tpm_chip_find_get(chip_num); | ||
1064 | if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2)) | ||
1065 | return -ENODEV; | ||
1066 | |||
1067 | rc = tpm2_seal_trusted(chip, payload, options); | ||
1068 | |||
1069 | tpm_chip_put(chip); | ||
1070 | return rc; | ||
1071 | } | ||
1072 | EXPORT_SYMBOL_GPL(tpm_seal_trusted); | ||
1073 | |||
1074 | /** | ||
1075 | * tpm_unseal_trusted() - unseal a trusted key | ||
1076 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | ||
1077 | * @options: authentication values and other options | ||
1078 | * @payload: the key data in clear and encrypted form | ||
1079 | * | ||
1080 | * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips | ||
1081 | * are supported. | ||
1082 | */ | ||
1083 | int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload, | ||
1084 | struct trusted_key_options *options) | ||
1085 | { | ||
1086 | struct tpm_chip *chip; | ||
1087 | int rc; | ||
1088 | |||
1089 | chip = tpm_chip_find_get(chip_num); | ||
1090 | if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2)) | ||
1091 | return -ENODEV; | ||
1092 | |||
1093 | rc = tpm2_unseal_trusted(chip, payload, options); | ||
1094 | |||
1095 | tpm_chip_put(chip); | ||
1096 | return rc; | ||
1097 | } | ||
1098 | EXPORT_SYMBOL_GPL(tpm_unseal_trusted); | ||
1099 | |||
1024 | static int __init tpm_init(void) | 1100 | static int __init tpm_init(void) |
1025 | { | 1101 | { |
1026 | int rc; | 1102 | int rc; |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index f8319a0860fd..a4257a32964f 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 IBM Corporation | 2 | * Copyright (C) 2004 IBM Corporation |
3 | * Copyright (C) 2015 Intel Corporation | ||
3 | * | 4 | * |
4 | * Authors: | 5 | * Authors: |
5 | * Leendert van Doorn <leendert@watson.ibm.com> | 6 | * Leendert van Doorn <leendert@watson.ibm.com> |
@@ -28,6 +29,7 @@ | |||
28 | #include <linux/tpm.h> | 29 | #include <linux/tpm.h> |
29 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
30 | #include <linux/cdev.h> | 31 | #include <linux/cdev.h> |
32 | #include <linux/highmem.h> | ||
31 | 33 | ||
32 | enum tpm_const { | 34 | enum tpm_const { |
33 | TPM_MINOR = 224, /* officially assigned */ | 35 | TPM_MINOR = 224, /* officially assigned */ |
@@ -88,6 +90,9 @@ enum tpm2_return_codes { | |||
88 | 90 | ||
89 | enum tpm2_algorithms { | 91 | enum tpm2_algorithms { |
90 | TPM2_ALG_SHA1 = 0x0004, | 92 | TPM2_ALG_SHA1 = 0x0004, |
93 | TPM2_ALG_KEYEDHASH = 0x0008, | ||
94 | TPM2_ALG_SHA256 = 0x000B, | ||
95 | TPM2_ALG_NULL = 0x0010 | ||
91 | }; | 96 | }; |
92 | 97 | ||
93 | enum tpm2_command_codes { | 98 | enum tpm2_command_codes { |
@@ -95,6 +100,10 @@ enum tpm2_command_codes { | |||
95 | TPM2_CC_SELF_TEST = 0x0143, | 100 | TPM2_CC_SELF_TEST = 0x0143, |
96 | TPM2_CC_STARTUP = 0x0144, | 101 | TPM2_CC_STARTUP = 0x0144, |
97 | TPM2_CC_SHUTDOWN = 0x0145, | 102 | TPM2_CC_SHUTDOWN = 0x0145, |
103 | TPM2_CC_CREATE = 0x0153, | ||
104 | TPM2_CC_LOAD = 0x0157, | ||
105 | TPM2_CC_UNSEAL = 0x015E, | ||
106 | TPM2_CC_FLUSH_CONTEXT = 0x0165, | ||
98 | TPM2_CC_GET_CAPABILITY = 0x017A, | 107 | TPM2_CC_GET_CAPABILITY = 0x017A, |
99 | TPM2_CC_GET_RANDOM = 0x017B, | 108 | TPM2_CC_GET_RANDOM = 0x017B, |
100 | TPM2_CC_PCR_READ = 0x017E, | 109 | TPM2_CC_PCR_READ = 0x017E, |
@@ -115,6 +124,13 @@ enum tpm2_startup_types { | |||
115 | TPM2_SU_STATE = 0x0001, | 124 | TPM2_SU_STATE = 0x0001, |
116 | }; | 125 | }; |
117 | 126 | ||
127 | enum tpm2_start_method { | ||
128 | TPM2_START_ACPI = 2, | ||
129 | TPM2_START_FIFO = 6, | ||
130 | TPM2_START_CRB = 7, | ||
131 | TPM2_START_CRB_WITH_ACPI = 8, | ||
132 | }; | ||
133 | |||
118 | struct tpm_chip; | 134 | struct tpm_chip; |
119 | 135 | ||
120 | struct tpm_vendor_specific { | 136 | struct tpm_vendor_specific { |
@@ -151,8 +167,7 @@ struct tpm_vendor_specific { | |||
151 | 167 | ||
152 | enum tpm_chip_flags { | 168 | enum tpm_chip_flags { |
153 | TPM_CHIP_FLAG_REGISTERED = BIT(0), | 169 | TPM_CHIP_FLAG_REGISTERED = BIT(0), |
154 | TPM_CHIP_FLAG_PPI = BIT(1), | 170 | TPM_CHIP_FLAG_TPM2 = BIT(1), |
155 | TPM_CHIP_FLAG_TPM2 = BIT(2), | ||
156 | }; | 171 | }; |
157 | 172 | ||
158 | struct tpm_chip { | 173 | struct tpm_chip { |
@@ -175,6 +190,8 @@ struct tpm_chip { | |||
175 | struct dentry **bios_dir; | 190 | struct dentry **bios_dir; |
176 | 191 | ||
177 | #ifdef CONFIG_ACPI | 192 | #ifdef CONFIG_ACPI |
193 | const struct attribute_group *groups[2]; | ||
194 | unsigned int groups_cnt; | ||
178 | acpi_handle acpi_dev_handle; | 195 | acpi_handle acpi_dev_handle; |
179 | char ppi_version[TPM_PPI_VERSION_LEN + 1]; | 196 | char ppi_version[TPM_PPI_VERSION_LEN + 1]; |
180 | #endif /* CONFIG_ACPI */ | 197 | #endif /* CONFIG_ACPI */ |
@@ -182,7 +199,7 @@ struct tpm_chip { | |||
182 | struct list_head list; | 199 | struct list_head list; |
183 | }; | 200 | }; |
184 | 201 | ||
185 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) | 202 | #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) |
186 | 203 | ||
187 | static inline void tpm_chip_put(struct tpm_chip *chip) | 204 | static inline void tpm_chip_put(struct tpm_chip *chip) |
188 | { | 205 | { |
@@ -382,6 +399,101 @@ struct tpm_cmd_t { | |||
382 | tpm_cmd_params params; | 399 | tpm_cmd_params params; |
383 | } __packed; | 400 | } __packed; |
384 | 401 | ||
402 | /* A string buffer type for constructing TPM commands. This is based on the | ||
403 | * ideas of string buffer code in security/keys/trusted.h but is heap based | ||
404 | * in order to keep the stack usage minimal. | ||
405 | */ | ||
406 | |||
407 | enum tpm_buf_flags { | ||
408 | TPM_BUF_OVERFLOW = BIT(0), | ||
409 | }; | ||
410 | |||
411 | struct tpm_buf { | ||
412 | struct page *data_page; | ||
413 | unsigned int flags; | ||
414 | u8 *data; | ||
415 | }; | ||
416 | |||
417 | static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) | ||
418 | { | ||
419 | struct tpm_input_header *head; | ||
420 | |||
421 | buf->data_page = alloc_page(GFP_HIGHUSER); | ||
422 | if (!buf->data_page) | ||
423 | return -ENOMEM; | ||
424 | |||
425 | buf->flags = 0; | ||
426 | buf->data = kmap(buf->data_page); | ||
427 | |||
428 | head = (struct tpm_input_header *) buf->data; | ||
429 | |||
430 | head->tag = cpu_to_be16(tag); | ||
431 | head->length = cpu_to_be32(sizeof(*head)); | ||
432 | head->ordinal = cpu_to_be32(ordinal); | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static inline void tpm_buf_destroy(struct tpm_buf *buf) | ||
438 | { | ||
439 | kunmap(buf->data_page); | ||
440 | __free_page(buf->data_page); | ||
441 | } | ||
442 | |||
443 | static inline u32 tpm_buf_length(struct tpm_buf *buf) | ||
444 | { | ||
445 | struct tpm_input_header *head = (struct tpm_input_header *) buf->data; | ||
446 | |||
447 | return be32_to_cpu(head->length); | ||
448 | } | ||
449 | |||
450 | static inline u16 tpm_buf_tag(struct tpm_buf *buf) | ||
451 | { | ||
452 | struct tpm_input_header *head = (struct tpm_input_header *) buf->data; | ||
453 | |||
454 | return be16_to_cpu(head->tag); | ||
455 | } | ||
456 | |||
457 | static inline void tpm_buf_append(struct tpm_buf *buf, | ||
458 | const unsigned char *new_data, | ||
459 | unsigned int new_len) | ||
460 | { | ||
461 | struct tpm_input_header *head = (struct tpm_input_header *) buf->data; | ||
462 | u32 len = tpm_buf_length(buf); | ||
463 | |||
464 | /* Return silently if overflow has already happened. */ | ||
465 | if (buf->flags & TPM_BUF_OVERFLOW) | ||
466 | return; | ||
467 | |||
468 | if ((len + new_len) > PAGE_SIZE) { | ||
469 | WARN(1, "tpm_buf: overflow\n"); | ||
470 | buf->flags |= TPM_BUF_OVERFLOW; | ||
471 | return; | ||
472 | } | ||
473 | |||
474 | memcpy(&buf->data[len], new_data, new_len); | ||
475 | head->length = cpu_to_be32(len + new_len); | ||
476 | } | ||
477 | |||
478 | static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value) | ||
479 | { | ||
480 | tpm_buf_append(buf, &value, 1); | ||
481 | } | ||
482 | |||
483 | static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value) | ||
484 | { | ||
485 | __be16 value2 = cpu_to_be16(value); | ||
486 | |||
487 | tpm_buf_append(buf, (u8 *) &value2, 2); | ||
488 | } | ||
489 | |||
490 | static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value) | ||
491 | { | ||
492 | __be32 value2 = cpu_to_be32(value); | ||
493 | |||
494 | tpm_buf_append(buf, (u8 *) &value2, 4); | ||
495 | } | ||
496 | |||
385 | extern struct class *tpm_class; | 497 | extern struct class *tpm_class; |
386 | extern dev_t tpm_devt; | 498 | extern dev_t tpm_devt; |
387 | extern const struct file_operations tpm_fops; | 499 | extern const struct file_operations tpm_fops; |
@@ -412,15 +524,9 @@ void tpm_sysfs_del_device(struct tpm_chip *chip); | |||
412 | int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); | 524 | int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); |
413 | 525 | ||
414 | #ifdef CONFIG_ACPI | 526 | #ifdef CONFIG_ACPI |
415 | extern int tpm_add_ppi(struct tpm_chip *chip); | 527 | extern void tpm_add_ppi(struct tpm_chip *chip); |
416 | extern void tpm_remove_ppi(struct tpm_chip *chip); | ||
417 | #else | 528 | #else |
418 | static inline int tpm_add_ppi(struct tpm_chip *chip) | 529 | static inline void tpm_add_ppi(struct tpm_chip *chip) |
419 | { | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static inline void tpm_remove_ppi(struct tpm_chip *chip) | ||
424 | { | 530 | { |
425 | } | 531 | } |
426 | #endif | 532 | #endif |
@@ -428,6 +534,12 @@ static inline void tpm_remove_ppi(struct tpm_chip *chip) | |||
428 | int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); | 534 | int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); |
429 | int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash); | 535 | int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash); |
430 | int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max); | 536 | int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max); |
537 | int tpm2_seal_trusted(struct tpm_chip *chip, | ||
538 | struct trusted_key_payload *payload, | ||
539 | struct trusted_key_options *options); | ||
540 | int tpm2_unseal_trusted(struct tpm_chip *chip, | ||
541 | struct trusted_key_payload *payload, | ||
542 | struct trusted_key_options *options); | ||
431 | ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, | 543 | ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, |
432 | u32 *value, const char *desc); | 544 | u32 *value, const char *desc); |
433 | 545 | ||
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 011909a9be96..bd7039fafa8a 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2014 Intel Corporation | 2 | * Copyright (C) 2014, 2015 Intel Corporation |
3 | * | 3 | * |
4 | * Authors: | 4 | * Authors: |
5 | * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | 5 | * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
@@ -16,6 +16,11 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "tpm.h" | 18 | #include "tpm.h" |
19 | #include <keys/trusted-type.h> | ||
20 | |||
21 | enum tpm2_object_attributes { | ||
22 | TPM2_ATTR_USER_WITH_AUTH = BIT(6), | ||
23 | }; | ||
19 | 24 | ||
20 | struct tpm2_startup_in { | 25 | struct tpm2_startup_in { |
21 | __be16 startup_type; | 26 | __be16 startup_type; |
@@ -381,6 +386,249 @@ static const struct tpm_input_header tpm2_get_tpm_pt_header = { | |||
381 | }; | 386 | }; |
382 | 387 | ||
383 | /** | 388 | /** |
389 | * Append TPMS_AUTH_COMMAND to the buffer. The buffer must be allocated with | ||
390 | * tpm_buf_alloc(). | ||
391 | * | ||
392 | * @param buf: an allocated tpm_buf instance | ||
393 | * @param nonce: the session nonce, may be NULL if not used | ||
394 | * @param nonce_len: the session nonce length, may be 0 if not used | ||
395 | * @param attributes: the session attributes | ||
396 | * @param hmac: the session HMAC or password, may be NULL if not used | ||
397 | * @param hmac_len: the session HMAC or password length, maybe 0 if not used | ||
398 | */ | ||
399 | static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle, | ||
400 | const u8 *nonce, u16 nonce_len, | ||
401 | u8 attributes, | ||
402 | const u8 *hmac, u16 hmac_len) | ||
403 | { | ||
404 | tpm_buf_append_u32(buf, 9 + nonce_len + hmac_len); | ||
405 | tpm_buf_append_u32(buf, session_handle); | ||
406 | tpm_buf_append_u16(buf, nonce_len); | ||
407 | |||
408 | if (nonce && nonce_len) | ||
409 | tpm_buf_append(buf, nonce, nonce_len); | ||
410 | |||
411 | tpm_buf_append_u8(buf, attributes); | ||
412 | tpm_buf_append_u16(buf, hmac_len); | ||
413 | |||
414 | if (hmac && hmac_len) | ||
415 | tpm_buf_append(buf, hmac, hmac_len); | ||
416 | } | ||
417 | |||
418 | /** | ||
419 | * tpm2_seal_trusted() - seal a trusted key | ||
420 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | ||
421 | * @options: authentication values and other options | ||
422 | * @payload: the key data in clear and encrypted form | ||
423 | * | ||
424 | * Returns < 0 on error and 0 on success. | ||
425 | */ | ||
426 | int tpm2_seal_trusted(struct tpm_chip *chip, | ||
427 | struct trusted_key_payload *payload, | ||
428 | struct trusted_key_options *options) | ||
429 | { | ||
430 | unsigned int blob_len; | ||
431 | struct tpm_buf buf; | ||
432 | int rc; | ||
433 | |||
434 | rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); | ||
435 | if (rc) | ||
436 | return rc; | ||
437 | |||
438 | tpm_buf_append_u32(&buf, options->keyhandle); | ||
439 | tpm2_buf_append_auth(&buf, TPM2_RS_PW, | ||
440 | NULL /* nonce */, 0, | ||
441 | 0 /* session_attributes */, | ||
442 | options->keyauth /* hmac */, | ||
443 | TPM_DIGEST_SIZE); | ||
444 | |||
445 | /* sensitive */ | ||
446 | tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len); | ||
447 | |||
448 | tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE); | ||
449 | tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE); | ||
450 | tpm_buf_append_u16(&buf, payload->key_len); | ||
451 | tpm_buf_append(&buf, payload->key, payload->key_len); | ||
452 | |||
453 | /* public */ | ||
454 | tpm_buf_append_u16(&buf, 14); | ||
455 | |||
456 | tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH); | ||
457 | tpm_buf_append_u16(&buf, TPM2_ALG_SHA256); | ||
458 | tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH); | ||
459 | tpm_buf_append_u16(&buf, 0); /* policy digest size */ | ||
460 | tpm_buf_append_u16(&buf, TPM2_ALG_NULL); | ||
461 | tpm_buf_append_u16(&buf, 0); | ||
462 | |||
463 | /* outside info */ | ||
464 | tpm_buf_append_u16(&buf, 0); | ||
465 | |||
466 | /* creation PCR */ | ||
467 | tpm_buf_append_u32(&buf, 0); | ||
468 | |||
469 | if (buf.flags & TPM_BUF_OVERFLOW) { | ||
470 | rc = -E2BIG; | ||
471 | goto out; | ||
472 | } | ||
473 | |||
474 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "sealing data"); | ||
475 | if (rc) | ||
476 | goto out; | ||
477 | |||
478 | blob_len = be32_to_cpup((__be32 *) &buf.data[TPM_HEADER_SIZE]); | ||
479 | if (blob_len > MAX_BLOB_SIZE) { | ||
480 | rc = -E2BIG; | ||
481 | goto out; | ||
482 | } | ||
483 | |||
484 | memcpy(payload->blob, &buf.data[TPM_HEADER_SIZE + 4], blob_len); | ||
485 | payload->blob_len = blob_len; | ||
486 | |||
487 | out: | ||
488 | tpm_buf_destroy(&buf); | ||
489 | |||
490 | if (rc > 0) | ||
491 | rc = -EPERM; | ||
492 | |||
493 | return rc; | ||
494 | } | ||
495 | |||
496 | static int tpm2_load(struct tpm_chip *chip, | ||
497 | struct trusted_key_payload *payload, | ||
498 | struct trusted_key_options *options, | ||
499 | u32 *blob_handle) | ||
500 | { | ||
501 | struct tpm_buf buf; | ||
502 | unsigned int private_len; | ||
503 | unsigned int public_len; | ||
504 | unsigned int blob_len; | ||
505 | int rc; | ||
506 | |||
507 | private_len = be16_to_cpup((__be16 *) &payload->blob[0]); | ||
508 | if (private_len > (payload->blob_len - 2)) | ||
509 | return -E2BIG; | ||
510 | |||
511 | public_len = be16_to_cpup((__be16 *) &payload->blob[2 + private_len]); | ||
512 | blob_len = private_len + public_len + 4; | ||
513 | if (blob_len > payload->blob_len) | ||
514 | return -E2BIG; | ||
515 | |||
516 | rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD); | ||
517 | if (rc) | ||
518 | return rc; | ||
519 | |||
520 | tpm_buf_append_u32(&buf, options->keyhandle); | ||
521 | tpm2_buf_append_auth(&buf, TPM2_RS_PW, | ||
522 | NULL /* nonce */, 0, | ||
523 | 0 /* session_attributes */, | ||
524 | options->keyauth /* hmac */, | ||
525 | TPM_DIGEST_SIZE); | ||
526 | |||
527 | tpm_buf_append(&buf, payload->blob, blob_len); | ||
528 | |||
529 | if (buf.flags & TPM_BUF_OVERFLOW) { | ||
530 | rc = -E2BIG; | ||
531 | goto out; | ||
532 | } | ||
533 | |||
534 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "loading blob"); | ||
535 | if (!rc) | ||
536 | *blob_handle = be32_to_cpup( | ||
537 | (__be32 *) &buf.data[TPM_HEADER_SIZE]); | ||
538 | |||
539 | out: | ||
540 | tpm_buf_destroy(&buf); | ||
541 | |||
542 | if (rc > 0) | ||
543 | rc = -EPERM; | ||
544 | |||
545 | return rc; | ||
546 | } | ||
547 | |||
548 | static void tpm2_flush_context(struct tpm_chip *chip, u32 handle) | ||
549 | { | ||
550 | struct tpm_buf buf; | ||
551 | int rc; | ||
552 | |||
553 | rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT); | ||
554 | if (rc) { | ||
555 | dev_warn(chip->pdev, "0x%08x was not flushed, out of memory\n", | ||
556 | handle); | ||
557 | return; | ||
558 | } | ||
559 | |||
560 | tpm_buf_append_u32(&buf, handle); | ||
561 | |||
562 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context"); | ||
563 | if (rc) | ||
564 | dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle, | ||
565 | rc); | ||
566 | |||
567 | tpm_buf_destroy(&buf); | ||
568 | } | ||
569 | |||
570 | static int tpm2_unseal(struct tpm_chip *chip, | ||
571 | struct trusted_key_payload *payload, | ||
572 | struct trusted_key_options *options, | ||
573 | u32 blob_handle) | ||
574 | { | ||
575 | struct tpm_buf buf; | ||
576 | int rc; | ||
577 | |||
578 | rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); | ||
579 | if (rc) | ||
580 | return rc; | ||
581 | |||
582 | tpm_buf_append_u32(&buf, blob_handle); | ||
583 | tpm2_buf_append_auth(&buf, TPM2_RS_PW, | ||
584 | NULL /* nonce */, 0, | ||
585 | 0 /* session_attributes */, | ||
586 | options->blobauth /* hmac */, | ||
587 | TPM_DIGEST_SIZE); | ||
588 | |||
589 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "unsealing"); | ||
590 | if (rc > 0) | ||
591 | rc = -EPERM; | ||
592 | |||
593 | if (!rc) { | ||
594 | payload->key_len = be16_to_cpup( | ||
595 | (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]); | ||
596 | |||
597 | memcpy(payload->key, &buf.data[TPM_HEADER_SIZE + 6], | ||
598 | payload->key_len); | ||
599 | } | ||
600 | |||
601 | tpm_buf_destroy(&buf); | ||
602 | return rc; | ||
603 | } | ||
604 | |||
605 | /** | ||
606 | * tpm_unseal_trusted() - unseal a trusted key | ||
607 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | ||
608 | * @options: authentication values and other options | ||
609 | * @payload: the key data in clear and encrypted form | ||
610 | * | ||
611 | * Returns < 0 on error and 0 on success. | ||
612 | */ | ||
613 | int tpm2_unseal_trusted(struct tpm_chip *chip, | ||
614 | struct trusted_key_payload *payload, | ||
615 | struct trusted_key_options *options) | ||
616 | { | ||
617 | u32 blob_handle; | ||
618 | int rc; | ||
619 | |||
620 | rc = tpm2_load(chip, payload, options, &blob_handle); | ||
621 | if (rc) | ||
622 | return rc; | ||
623 | |||
624 | rc = tpm2_unseal(chip, payload, options, blob_handle); | ||
625 | |||
626 | tpm2_flush_context(chip, blob_handle); | ||
627 | |||
628 | return rc; | ||
629 | } | ||
630 | |||
631 | /** | ||
384 | * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property | 632 | * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property |
385 | * @chip: TPM chip to use. | 633 | * @chip: TPM chip to use. |
386 | * @property_id: property ID. | 634 | * @property_id: property ID. |
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 1267322595da..4bb9727c1047 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
@@ -34,12 +34,6 @@ enum crb_defaults { | |||
34 | CRB_ACPI_START_INDEX = 1, | 34 | CRB_ACPI_START_INDEX = 1, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | enum crb_start_method { | ||
38 | CRB_SM_ACPI_START = 2, | ||
39 | CRB_SM_CRB = 7, | ||
40 | CRB_SM_CRB_WITH_ACPI_START = 8, | ||
41 | }; | ||
42 | |||
43 | struct acpi_tpm2 { | 37 | struct acpi_tpm2 { |
44 | struct acpi_table_header hdr; | 38 | struct acpi_table_header hdr; |
45 | u16 platform_class; | 39 | u16 platform_class; |
@@ -74,7 +68,8 @@ struct crb_control_area { | |||
74 | u32 int_enable; | 68 | u32 int_enable; |
75 | u32 int_sts; | 69 | u32 int_sts; |
76 | u32 cmd_size; | 70 | u32 cmd_size; |
77 | u64 cmd_pa; | 71 | u32 cmd_pa_low; |
72 | u32 cmd_pa_high; | ||
78 | u32 rsp_size; | 73 | u32 rsp_size; |
79 | u64 rsp_pa; | 74 | u64 rsp_pa; |
80 | } __packed; | 75 | } __packed; |
@@ -220,12 +215,6 @@ static int crb_acpi_add(struct acpi_device *device) | |||
220 | u64 pa; | 215 | u64 pa; |
221 | int rc; | 216 | int rc; |
222 | 217 | ||
223 | chip = tpmm_chip_alloc(dev, &tpm_crb); | ||
224 | if (IS_ERR(chip)) | ||
225 | return PTR_ERR(chip); | ||
226 | |||
227 | chip->flags = TPM_CHIP_FLAG_TPM2; | ||
228 | |||
229 | status = acpi_get_table(ACPI_SIG_TPM2, 1, | 218 | status = acpi_get_table(ACPI_SIG_TPM2, 1, |
230 | (struct acpi_table_header **) &buf); | 219 | (struct acpi_table_header **) &buf); |
231 | if (ACPI_FAILURE(status)) { | 220 | if (ACPI_FAILURE(status)) { |
@@ -233,13 +222,15 @@ static int crb_acpi_add(struct acpi_device *device) | |||
233 | return -ENODEV; | 222 | return -ENODEV; |
234 | } | 223 | } |
235 | 224 | ||
236 | /* At least some versions of AMI BIOS have a bug that TPM2 table has | 225 | /* Should the FIFO driver handle this? */ |
237 | * zero address for the control area and therefore we must fail. | 226 | if (buf->start_method == TPM2_START_FIFO) |
238 | */ | 227 | return -ENODEV; |
239 | if (!buf->control_area_pa) { | 228 | |
240 | dev_err(dev, "TPM2 ACPI table has a zero address for the control area\n"); | 229 | chip = tpmm_chip_alloc(dev, &tpm_crb); |
241 | return -EINVAL; | 230 | if (IS_ERR(chip)) |
242 | } | 231 | return PTR_ERR(chip); |
232 | |||
233 | chip->flags = TPM_CHIP_FLAG_TPM2; | ||
243 | 234 | ||
244 | if (buf->hdr.length < sizeof(struct acpi_tpm2)) { | 235 | if (buf->hdr.length < sizeof(struct acpi_tpm2)) { |
245 | dev_err(dev, "TPM2 ACPI table has wrong size"); | 236 | dev_err(dev, "TPM2 ACPI table has wrong size"); |
@@ -259,11 +250,11 @@ static int crb_acpi_add(struct acpi_device *device) | |||
259 | * report only ACPI start but in practice seems to require both | 250 | * report only ACPI start but in practice seems to require both |
260 | * ACPI start and CRB start. | 251 | * ACPI start and CRB start. |
261 | */ | 252 | */ |
262 | if (sm == CRB_SM_CRB || sm == CRB_SM_CRB_WITH_ACPI_START || | 253 | if (sm == TPM2_START_CRB || sm == TPM2_START_FIFO || |
263 | !strcmp(acpi_device_hid(device), "MSFT0101")) | 254 | !strcmp(acpi_device_hid(device), "MSFT0101")) |
264 | priv->flags |= CRB_FL_CRB_START; | 255 | priv->flags |= CRB_FL_CRB_START; |
265 | 256 | ||
266 | if (sm == CRB_SM_ACPI_START || sm == CRB_SM_CRB_WITH_ACPI_START) | 257 | if (sm == TPM2_START_ACPI || sm == TPM2_START_CRB_WITH_ACPI) |
267 | priv->flags |= CRB_FL_ACPI_START; | 258 | priv->flags |= CRB_FL_ACPI_START; |
268 | 259 | ||
269 | priv->cca = (struct crb_control_area __iomem *) | 260 | priv->cca = (struct crb_control_area __iomem *) |
@@ -273,8 +264,8 @@ static int crb_acpi_add(struct acpi_device *device) | |||
273 | return -ENOMEM; | 264 | return -ENOMEM; |
274 | } | 265 | } |
275 | 266 | ||
276 | memcpy_fromio(&pa, &priv->cca->cmd_pa, 8); | 267 | pa = ((u64) le32_to_cpu(ioread32(&priv->cca->cmd_pa_high)) << 32) | |
277 | pa = le64_to_cpu(pa); | 268 | (u64) le32_to_cpu(ioread32(&priv->cca->cmd_pa_low)); |
278 | priv->cmd = devm_ioremap_nocache(dev, pa, | 269 | priv->cmd = devm_ioremap_nocache(dev, pa, |
279 | ioread32(&priv->cca->cmd_size)); | 270 | ioread32(&priv->cca->cmd_size)); |
280 | if (!priv->cmd) { | 271 | if (!priv->cmd) { |
diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c index 3a56a131586c..bd72fb04225e 100644 --- a/drivers/char/tpm/tpm_eventlog.c +++ b/drivers/char/tpm/tpm_eventlog.c | |||
@@ -76,15 +76,25 @@ static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos) | |||
76 | void *addr = log->bios_event_log; | 76 | void *addr = log->bios_event_log; |
77 | void *limit = log->bios_event_log_end; | 77 | void *limit = log->bios_event_log_end; |
78 | struct tcpa_event *event; | 78 | struct tcpa_event *event; |
79 | u32 converted_event_size; | ||
80 | u32 converted_event_type; | ||
81 | |||
79 | 82 | ||
80 | /* read over *pos measurements */ | 83 | /* read over *pos measurements */ |
81 | for (i = 0; i < *pos; i++) { | 84 | for (i = 0; i < *pos; i++) { |
82 | event = addr; | 85 | event = addr; |
83 | 86 | ||
87 | converted_event_size = | ||
88 | do_endian_conversion(event->event_size); | ||
89 | converted_event_type = | ||
90 | do_endian_conversion(event->event_type); | ||
91 | |||
84 | if ((addr + sizeof(struct tcpa_event)) < limit) { | 92 | if ((addr + sizeof(struct tcpa_event)) < limit) { |
85 | if (event->event_type == 0 && event->event_size == 0) | 93 | if ((converted_event_type == 0) && |
94 | (converted_event_size == 0)) | ||
86 | return NULL; | 95 | return NULL; |
87 | addr += sizeof(struct tcpa_event) + event->event_size; | 96 | addr += (sizeof(struct tcpa_event) + |
97 | converted_event_size); | ||
88 | } | 98 | } |
89 | } | 99 | } |
90 | 100 | ||
@@ -94,8 +104,12 @@ static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos) | |||
94 | 104 | ||
95 | event = addr; | 105 | event = addr; |
96 | 106 | ||
97 | if ((event->event_type == 0 && event->event_size == 0) || | 107 | converted_event_size = do_endian_conversion(event->event_size); |
98 | ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit)) | 108 | converted_event_type = do_endian_conversion(event->event_type); |
109 | |||
110 | if (((converted_event_type == 0) && (converted_event_size == 0)) | ||
111 | || ((addr + sizeof(struct tcpa_event) + converted_event_size) | ||
112 | >= limit)) | ||
99 | return NULL; | 113 | return NULL; |
100 | 114 | ||
101 | return addr; | 115 | return addr; |
@@ -107,8 +121,12 @@ static void *tpm_bios_measurements_next(struct seq_file *m, void *v, | |||
107 | struct tcpa_event *event = v; | 121 | struct tcpa_event *event = v; |
108 | struct tpm_bios_log *log = m->private; | 122 | struct tpm_bios_log *log = m->private; |
109 | void *limit = log->bios_event_log_end; | 123 | void *limit = log->bios_event_log_end; |
124 | u32 converted_event_size; | ||
125 | u32 converted_event_type; | ||
110 | 126 | ||
111 | v += sizeof(struct tcpa_event) + event->event_size; | 127 | converted_event_size = do_endian_conversion(event->event_size); |
128 | |||
129 | v += sizeof(struct tcpa_event) + converted_event_size; | ||
112 | 130 | ||
113 | /* now check if current entry is valid */ | 131 | /* now check if current entry is valid */ |
114 | if ((v + sizeof(struct tcpa_event)) >= limit) | 132 | if ((v + sizeof(struct tcpa_event)) >= limit) |
@@ -116,11 +134,11 @@ static void *tpm_bios_measurements_next(struct seq_file *m, void *v, | |||
116 | 134 | ||
117 | event = v; | 135 | event = v; |
118 | 136 | ||
119 | if (event->event_type == 0 && event->event_size == 0) | 137 | converted_event_size = do_endian_conversion(event->event_size); |
120 | return NULL; | 138 | converted_event_type = do_endian_conversion(event->event_type); |
121 | 139 | ||
122 | if ((event->event_type == 0 && event->event_size == 0) || | 140 | if (((converted_event_type == 0) && (converted_event_size == 0)) || |
123 | ((v + sizeof(struct tcpa_event) + event->event_size) >= limit)) | 141 | ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit)) |
124 | return NULL; | 142 | return NULL; |
125 | 143 | ||
126 | (*pos)++; | 144 | (*pos)++; |
@@ -140,7 +158,7 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
140 | int i, n_len = 0, d_len = 0; | 158 | int i, n_len = 0, d_len = 0; |
141 | struct tcpa_pc_event *pc_event; | 159 | struct tcpa_pc_event *pc_event; |
142 | 160 | ||
143 | switch(event->event_type) { | 161 | switch (do_endian_conversion(event->event_type)) { |
144 | case PREBOOT: | 162 | case PREBOOT: |
145 | case POST_CODE: | 163 | case POST_CODE: |
146 | case UNUSED: | 164 | case UNUSED: |
@@ -156,14 +174,16 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
156 | case NONHOST_CODE: | 174 | case NONHOST_CODE: |
157 | case NONHOST_CONFIG: | 175 | case NONHOST_CONFIG: |
158 | case NONHOST_INFO: | 176 | case NONHOST_INFO: |
159 | name = tcpa_event_type_strings[event->event_type]; | 177 | name = tcpa_event_type_strings[do_endian_conversion |
178 | (event->event_type)]; | ||
160 | n_len = strlen(name); | 179 | n_len = strlen(name); |
161 | break; | 180 | break; |
162 | case SEPARATOR: | 181 | case SEPARATOR: |
163 | case ACTION: | 182 | case ACTION: |
164 | if (MAX_TEXT_EVENT > event->event_size) { | 183 | if (MAX_TEXT_EVENT > |
184 | do_endian_conversion(event->event_size)) { | ||
165 | name = event_entry; | 185 | name = event_entry; |
166 | n_len = event->event_size; | 186 | n_len = do_endian_conversion(event->event_size); |
167 | } | 187 | } |
168 | break; | 188 | break; |
169 | case EVENT_TAG: | 189 | case EVENT_TAG: |
@@ -171,7 +191,7 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
171 | 191 | ||
172 | /* ToDo Row data -> Base64 */ | 192 | /* ToDo Row data -> Base64 */ |
173 | 193 | ||
174 | switch (pc_event->event_id) { | 194 | switch (do_endian_conversion(pc_event->event_id)) { |
175 | case SMBIOS: | 195 | case SMBIOS: |
176 | case BIS_CERT: | 196 | case BIS_CERT: |
177 | case CMOS: | 197 | case CMOS: |
@@ -179,7 +199,8 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
179 | case OPTION_ROM_EXEC: | 199 | case OPTION_ROM_EXEC: |
180 | case OPTION_ROM_CONFIG: | 200 | case OPTION_ROM_CONFIG: |
181 | case S_CRTM_VERSION: | 201 | case S_CRTM_VERSION: |
182 | name = tcpa_pc_event_id_strings[pc_event->event_id]; | 202 | name = tcpa_pc_event_id_strings[do_endian_conversion |
203 | (pc_event->event_id)]; | ||
183 | n_len = strlen(name); | 204 | n_len = strlen(name); |
184 | break; | 205 | break; |
185 | /* hash data */ | 206 | /* hash data */ |
@@ -188,7 +209,8 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
188 | case OPTION_ROM_MICROCODE: | 209 | case OPTION_ROM_MICROCODE: |
189 | case S_CRTM_CONTENTS: | 210 | case S_CRTM_CONTENTS: |
190 | case POST_CONTENTS: | 211 | case POST_CONTENTS: |
191 | name = tcpa_pc_event_id_strings[pc_event->event_id]; | 212 | name = tcpa_pc_event_id_strings[do_endian_conversion |
213 | (pc_event->event_id)]; | ||
192 | n_len = strlen(name); | 214 | n_len = strlen(name); |
193 | for (i = 0; i < 20; i++) | 215 | for (i = 0; i < 20; i++) |
194 | d_len += sprintf(&data[2*i], "%02x", | 216 | d_len += sprintf(&data[2*i], "%02x", |
@@ -209,13 +231,24 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
209 | static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) | 231 | static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) |
210 | { | 232 | { |
211 | struct tcpa_event *event = v; | 233 | struct tcpa_event *event = v; |
212 | char *data = v; | 234 | struct tcpa_event temp_event; |
235 | char *tempPtr; | ||
213 | int i; | 236 | int i; |
214 | 237 | ||
215 | for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++) | 238 | memcpy(&temp_event, event, sizeof(struct tcpa_event)); |
216 | seq_putc(m, data[i]); | 239 | |
240 | /* convert raw integers for endianness */ | ||
241 | temp_event.pcr_index = do_endian_conversion(event->pcr_index); | ||
242 | temp_event.event_type = do_endian_conversion(event->event_type); | ||
243 | temp_event.event_size = do_endian_conversion(event->event_size); | ||
244 | |||
245 | tempPtr = (char *)&temp_event; | ||
246 | |||
247 | for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++) | ||
248 | seq_putc(m, tempPtr[i]); | ||
217 | 249 | ||
218 | return 0; | 250 | return 0; |
251 | |||
219 | } | 252 | } |
220 | 253 | ||
221 | static int tpm_bios_measurements_release(struct inode *inode, | 254 | static int tpm_bios_measurements_release(struct inode *inode, |
@@ -238,7 +271,7 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) | |||
238 | char *eventname; | 271 | char *eventname; |
239 | struct tcpa_event *event = v; | 272 | struct tcpa_event *event = v; |
240 | unsigned char *event_entry = | 273 | unsigned char *event_entry = |
241 | (unsigned char *) (v + sizeof(struct tcpa_event)); | 274 | (unsigned char *)(v + sizeof(struct tcpa_event)); |
242 | 275 | ||
243 | eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); | 276 | eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); |
244 | if (!eventname) { | 277 | if (!eventname) { |
@@ -247,13 +280,14 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) | |||
247 | return -EFAULT; | 280 | return -EFAULT; |
248 | } | 281 | } |
249 | 282 | ||
250 | seq_printf(m, "%2d ", event->pcr_index); | 283 | /* 1st: PCR */ |
284 | seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index)); | ||
251 | 285 | ||
252 | /* 2nd: SHA1 */ | 286 | /* 2nd: SHA1 */ |
253 | seq_printf(m, "%20phN", event->pcr_value); | 287 | seq_printf(m, "%20phN", event->pcr_value); |
254 | 288 | ||
255 | /* 3rd: event type identifier */ | 289 | /* 3rd: event type identifier */ |
256 | seq_printf(m, " %02x", event->event_type); | 290 | seq_printf(m, " %02x", do_endian_conversion(event->event_type)); |
257 | 291 | ||
258 | len += get_event_name(eventname, event, event_entry); | 292 | len += get_event_name(eventname, event, event_entry); |
259 | 293 | ||
diff --git a/drivers/char/tpm/tpm_eventlog.h b/drivers/char/tpm/tpm_eventlog.h index e7da086d6928..267bfbd1b7bb 100644 --- a/drivers/char/tpm/tpm_eventlog.h +++ b/drivers/char/tpm/tpm_eventlog.h | |||
@@ -6,6 +6,12 @@ | |||
6 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ | 6 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ |
7 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ | 7 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ |
8 | 8 | ||
9 | #ifdef CONFIG_PPC64 | ||
10 | #define do_endian_conversion(x) be32_to_cpu(x) | ||
11 | #else | ||
12 | #define do_endian_conversion(x) x | ||
13 | #endif | ||
14 | |||
9 | enum bios_platform_class { | 15 | enum bios_platform_class { |
10 | BIOS_CLIENT = 0x00, | 16 | BIOS_CLIENT = 0x00, |
11 | BIOS_SERVER = 0x01, | 17 | BIOS_SERVER = 0x01, |
diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c index 7a0ca78ad3c6..8dfb88b9739c 100644 --- a/drivers/char/tpm/tpm_i2c_atmel.c +++ b/drivers/char/tpm/tpm_i2c_atmel.c | |||
@@ -217,7 +217,6 @@ static struct i2c_driver i2c_atmel_driver = { | |||
217 | .remove = i2c_atmel_remove, | 217 | .remove = i2c_atmel_remove, |
218 | .driver = { | 218 | .driver = { |
219 | .name = I2C_DRIVER_NAME, | 219 | .name = I2C_DRIVER_NAME, |
220 | .owner = THIS_MODULE, | ||
221 | .pm = &i2c_atmel_pm_ops, | 220 | .pm = &i2c_atmel_pm_ops, |
222 | .of_match_table = of_match_ptr(i2c_atmel_of_match), | 221 | .of_match_table = of_match_ptr(i2c_atmel_of_match), |
223 | }, | 222 | }, |
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 33c5f360ab01..63d5d22e9e60 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c | |||
@@ -711,7 +711,6 @@ static struct i2c_driver tpm_tis_i2c_driver = { | |||
711 | .remove = tpm_tis_i2c_remove, | 711 | .remove = tpm_tis_i2c_remove, |
712 | .driver = { | 712 | .driver = { |
713 | .name = "tpm_i2c_infineon", | 713 | .name = "tpm_i2c_infineon", |
714 | .owner = THIS_MODULE, | ||
715 | .pm = &tpm_tis_i2c_ops, | 714 | .pm = &tpm_tis_i2c_ops, |
716 | .of_match_table = of_match_ptr(tpm_tis_i2c_of_match), | 715 | .of_match_table = of_match_ptr(tpm_tis_i2c_of_match), |
717 | }, | 716 | }, |
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index 9d42b7d78e50..847f1597fe9b 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c | |||
@@ -641,7 +641,6 @@ static struct i2c_driver i2c_nuvoton_driver = { | |||
641 | .remove = i2c_nuvoton_remove, | 641 | .remove = i2c_nuvoton_remove, |
642 | .driver = { | 642 | .driver = { |
643 | .name = I2C_DRIVER_NAME, | 643 | .name = I2C_DRIVER_NAME, |
644 | .owner = THIS_MODULE, | ||
645 | .pm = &i2c_nuvoton_pm_ops, | 644 | .pm = &i2c_nuvoton_pm_ops, |
646 | .of_match_table = of_match_ptr(i2c_nuvoton_of_match), | 645 | .of_match_table = of_match_ptr(i2c_nuvoton_of_match), |
647 | }, | 646 | }, |
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index 27ebf9511cb4..3e6a22658b63 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c | |||
@@ -491,7 +491,7 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, | |||
491 | } | 491 | } |
492 | ibmvtpm->rtce_size = be16_to_cpu(crq->len); | 492 | ibmvtpm->rtce_size = be16_to_cpu(crq->len); |
493 | ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, | 493 | ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, |
494 | GFP_KERNEL); | 494 | GFP_ATOMIC); |
495 | if (!ibmvtpm->rtce_buf) { | 495 | if (!ibmvtpm->rtce_buf) { |
496 | dev_err(ibmvtpm->dev, "Failed to allocate memory for rtce buffer\n"); | 496 | dev_err(ibmvtpm->dev, "Failed to allocate memory for rtce buffer\n"); |
497 | return; | 497 | return; |
diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c index eebe6256918f..1141456a4b1f 100644 --- a/drivers/char/tpm/tpm_of.c +++ b/drivers/char/tpm/tpm_of.c | |||
@@ -24,14 +24,14 @@ int read_log(struct tpm_bios_log *log) | |||
24 | { | 24 | { |
25 | struct device_node *np; | 25 | struct device_node *np; |
26 | const u32 *sizep; | 26 | const u32 *sizep; |
27 | const __be64 *basep; | 27 | const u64 *basep; |
28 | 28 | ||
29 | if (log->bios_event_log != NULL) { | 29 | if (log->bios_event_log != NULL) { |
30 | pr_err("%s: ERROR - Eventlog already initialized\n", __func__); | 30 | pr_err("%s: ERROR - Eventlog already initialized\n", __func__); |
31 | return -EFAULT; | 31 | return -EFAULT; |
32 | } | 32 | } |
33 | 33 | ||
34 | np = of_find_node_by_name(NULL, "ibm,vtpm"); | 34 | np = of_find_node_by_name(NULL, "vtpm"); |
35 | if (!np) { | 35 | if (!np) { |
36 | pr_err("%s: ERROR - IBMVTPM not supported\n", __func__); | 36 | pr_err("%s: ERROR - IBMVTPM not supported\n", __func__); |
37 | return -ENODEV; | 37 | return -ENODEV; |
@@ -63,7 +63,7 @@ int read_log(struct tpm_bios_log *log) | |||
63 | 63 | ||
64 | log->bios_event_log_end = log->bios_event_log + *sizep; | 64 | log->bios_event_log_end = log->bios_event_log + *sizep; |
65 | 65 | ||
66 | memcpy(log->bios_event_log, __va(be64_to_cpup(basep)), *sizep); | 66 | memcpy(log->bios_event_log, __va(*basep), *sizep); |
67 | 67 | ||
68 | return 0; | 68 | return 0; |
69 | 69 | ||
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index 6ca9b5d78144..692a2c6ae036 100644 --- a/drivers/char/tpm/tpm_ppi.c +++ b/drivers/char/tpm/tpm_ppi.c | |||
@@ -53,7 +53,7 @@ tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type, | |||
53 | static ssize_t tpm_show_ppi_version(struct device *dev, | 53 | static ssize_t tpm_show_ppi_version(struct device *dev, |
54 | struct device_attribute *attr, char *buf) | 54 | struct device_attribute *attr, char *buf) |
55 | { | 55 | { |
56 | struct tpm_chip *chip = dev_get_drvdata(dev); | 56 | struct tpm_chip *chip = to_tpm_chip(dev); |
57 | 57 | ||
58 | return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version); | 58 | return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version); |
59 | } | 59 | } |
@@ -63,7 +63,7 @@ static ssize_t tpm_show_ppi_request(struct device *dev, | |||
63 | { | 63 | { |
64 | ssize_t size = -EINVAL; | 64 | ssize_t size = -EINVAL; |
65 | union acpi_object *obj; | 65 | union acpi_object *obj; |
66 | struct tpm_chip *chip = dev_get_drvdata(dev); | 66 | struct tpm_chip *chip = to_tpm_chip(dev); |
67 | 67 | ||
68 | obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ, | 68 | obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ, |
69 | ACPI_TYPE_PACKAGE, NULL); | 69 | ACPI_TYPE_PACKAGE, NULL); |
@@ -100,7 +100,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev, | |||
100 | int func = TPM_PPI_FN_SUBREQ; | 100 | int func = TPM_PPI_FN_SUBREQ; |
101 | union acpi_object *obj, tmp; | 101 | union acpi_object *obj, tmp; |
102 | 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); | 103 | struct tpm_chip *chip = to_tpm_chip(dev); |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * the function to submit TPM operation request to pre-os environment | 106 | * the function to submit TPM operation request to pre-os environment |
@@ -156,7 +156,7 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev, | |||
156 | .buffer.length = 0, | 156 | .buffer.length = 0, |
157 | .buffer.pointer = NULL | 157 | .buffer.pointer = NULL |
158 | }; | 158 | }; |
159 | struct tpm_chip *chip = dev_get_drvdata(dev); | 159 | struct tpm_chip *chip = to_tpm_chip(dev); |
160 | 160 | ||
161 | static char *info[] = { | 161 | static char *info[] = { |
162 | "None", | 162 | "None", |
@@ -197,7 +197,7 @@ static ssize_t tpm_show_ppi_response(struct device *dev, | |||
197 | acpi_status status = -EINVAL; | 197 | acpi_status status = -EINVAL; |
198 | union acpi_object *obj, *ret_obj; | 198 | union acpi_object *obj, *ret_obj; |
199 | u64 req, res; | 199 | u64 req, res; |
200 | struct tpm_chip *chip = dev_get_drvdata(dev); | 200 | struct tpm_chip *chip = to_tpm_chip(dev); |
201 | 201 | ||
202 | obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP, | 202 | obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP, |
203 | ACPI_TYPE_PACKAGE, NULL); | 203 | ACPI_TYPE_PACKAGE, NULL); |
@@ -296,7 +296,7 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device *dev, | |||
296 | struct device_attribute *attr, | 296 | struct device_attribute *attr, |
297 | char *buf) | 297 | char *buf) |
298 | { | 298 | { |
299 | struct tpm_chip *chip = dev_get_drvdata(dev); | 299 | struct tpm_chip *chip = to_tpm_chip(dev); |
300 | 300 | ||
301 | return show_ppi_operations(chip->acpi_dev_handle, buf, 0, | 301 | return show_ppi_operations(chip->acpi_dev_handle, buf, 0, |
302 | PPI_TPM_REQ_MAX); | 302 | PPI_TPM_REQ_MAX); |
@@ -306,7 +306,7 @@ static ssize_t tpm_show_ppi_vs_operations(struct device *dev, | |||
306 | struct device_attribute *attr, | 306 | struct device_attribute *attr, |
307 | char *buf) | 307 | char *buf) |
308 | { | 308 | { |
309 | struct tpm_chip *chip = dev_get_drvdata(dev); | 309 | struct tpm_chip *chip = to_tpm_chip(dev); |
310 | 310 | ||
311 | return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START, | 311 | return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START, |
312 | PPI_VS_REQ_END); | 312 | PPI_VS_REQ_END); |
@@ -334,17 +334,16 @@ static struct attribute_group ppi_attr_grp = { | |||
334 | .attrs = ppi_attrs | 334 | .attrs = ppi_attrs |
335 | }; | 335 | }; |
336 | 336 | ||
337 | int tpm_add_ppi(struct tpm_chip *chip) | 337 | void tpm_add_ppi(struct tpm_chip *chip) |
338 | { | 338 | { |
339 | union acpi_object *obj; | 339 | union acpi_object *obj; |
340 | int rc; | ||
341 | 340 | ||
342 | if (!chip->acpi_dev_handle) | 341 | if (!chip->acpi_dev_handle) |
343 | return 0; | 342 | return; |
344 | 343 | ||
345 | if (!acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid, | 344 | if (!acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid, |
346 | TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_VERSION)) | 345 | TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_VERSION)) |
347 | return 0; | 346 | return; |
348 | 347 | ||
349 | /* Cache PPI version string. */ | 348 | /* Cache PPI version string. */ |
350 | obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, tpm_ppi_uuid, | 349 | obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, tpm_ppi_uuid, |
@@ -356,16 +355,5 @@ int tpm_add_ppi(struct tpm_chip *chip) | |||
356 | ACPI_FREE(obj); | 355 | ACPI_FREE(obj); |
357 | } | 356 | } |
358 | 357 | ||
359 | rc = sysfs_create_group(&chip->pdev->kobj, &ppi_attr_grp); | 358 | chip->groups[chip->groups_cnt++] = &ppi_attr_grp; |
360 | |||
361 | if (!rc) | ||
362 | chip->flags |= TPM_CHIP_FLAG_PPI; | ||
363 | |||
364 | return rc; | ||
365 | } | ||
366 | |||
367 | void tpm_remove_ppi(struct tpm_chip *chip) | ||
368 | { | ||
369 | if (chip->flags & TPM_CHIP_FLAG_PPI) | ||
370 | sysfs_remove_group(&chip->pdev->kobj, &ppi_attr_grp); | ||
371 | } | 359 | } |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index f2dffa770b8e..696ef1d56b4f 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2005, 2006 IBM Corporation | 2 | * Copyright (C) 2005, 2006 IBM Corporation |
3 | * Copyright (C) 2014 Intel Corporation | 3 | * Copyright (C) 2014, 2015 Intel Corporation |
4 | * | 4 | * |
5 | * Authors: | 5 | * Authors: |
6 | * Leendert van Doorn <leendert@watson.ibm.com> | 6 | * Leendert van Doorn <leendert@watson.ibm.com> |
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
29 | #include <linux/acpi.h> | 29 | #include <linux/acpi.h> |
30 | #include <linux/freezer.h> | 30 | #include <linux/freezer.h> |
31 | #include <acpi/actbl2.h> | ||
31 | #include "tpm.h" | 32 | #include "tpm.h" |
32 | 33 | ||
33 | enum tis_access { | 34 | enum tis_access { |
@@ -65,6 +66,17 @@ enum tis_defaults { | |||
65 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ | 66 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ |
66 | }; | 67 | }; |
67 | 68 | ||
69 | struct tpm_info { | ||
70 | unsigned long start; | ||
71 | unsigned long len; | ||
72 | unsigned int irq; | ||
73 | }; | ||
74 | |||
75 | static struct tpm_info tis_default_info = { | ||
76 | .start = TIS_MEM_BASE, | ||
77 | .len = TIS_MEM_LEN, | ||
78 | .irq = 0, | ||
79 | }; | ||
68 | 80 | ||
69 | /* Some timeout values are needed before it is known whether the chip is | 81 | /* Some timeout values are needed before it is known whether the chip is |
70 | * TPM 1.0 or TPM 2.0. | 82 | * TPM 1.0 or TPM 2.0. |
@@ -91,26 +103,54 @@ struct priv_data { | |||
91 | }; | 103 | }; |
92 | 104 | ||
93 | #if defined(CONFIG_PNP) && defined(CONFIG_ACPI) | 105 | #if defined(CONFIG_PNP) && defined(CONFIG_ACPI) |
94 | static int is_itpm(struct pnp_dev *dev) | 106 | static int has_hid(struct acpi_device *dev, const char *hid) |
95 | { | 107 | { |
96 | struct acpi_device *acpi = pnp_acpi_device(dev); | ||
97 | struct acpi_hardware_id *id; | 108 | struct acpi_hardware_id *id; |
98 | 109 | ||
99 | if (!acpi) | 110 | list_for_each_entry(id, &dev->pnp.ids, list) |
100 | return 0; | 111 | if (!strcmp(hid, id->id)) |
101 | |||
102 | list_for_each_entry(id, &acpi->pnp.ids, list) { | ||
103 | if (!strcmp("INTC0102", id->id)) | ||
104 | return 1; | 112 | return 1; |
105 | } | ||
106 | 113 | ||
107 | return 0; | 114 | return 0; |
108 | } | 115 | } |
116 | |||
117 | static inline int is_itpm(struct acpi_device *dev) | ||
118 | { | ||
119 | return has_hid(dev, "INTC0102"); | ||
120 | } | ||
121 | |||
122 | static inline int is_fifo(struct acpi_device *dev) | ||
123 | { | ||
124 | struct acpi_table_tpm2 *tbl; | ||
125 | acpi_status st; | ||
126 | |||
127 | /* TPM 1.2 FIFO */ | ||
128 | if (!has_hid(dev, "MSFT0101")) | ||
129 | return 1; | ||
130 | |||
131 | st = acpi_get_table(ACPI_SIG_TPM2, 1, | ||
132 | (struct acpi_table_header **) &tbl); | ||
133 | if (ACPI_FAILURE(st)) { | ||
134 | dev_err(&dev->dev, "failed to get TPM2 ACPI table\n"); | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | if (le32_to_cpu(tbl->start_method) != TPM2_START_FIFO) | ||
139 | return 0; | ||
140 | |||
141 | /* TPM 2.0 FIFO */ | ||
142 | return 1; | ||
143 | } | ||
109 | #else | 144 | #else |
110 | static inline int is_itpm(struct pnp_dev *dev) | 145 | static inline int is_itpm(struct acpi_device *dev) |
111 | { | 146 | { |
112 | return 0; | 147 | return 0; |
113 | } | 148 | } |
149 | |||
150 | static inline int is_fifo(struct acpi_device *dev) | ||
151 | { | ||
152 | return 1; | ||
153 | } | ||
114 | #endif | 154 | #endif |
115 | 155 | ||
116 | /* Before we attempt to access the TPM we must see that the valid bit is set. | 156 | /* Before we attempt to access the TPM we must see that the valid bit is set. |
@@ -600,9 +640,8 @@ static void tpm_tis_remove(struct tpm_chip *chip) | |||
600 | release_locality(chip, chip->vendor.locality, 1); | 640 | release_locality(chip, chip->vendor.locality, 1); |
601 | } | 641 | } |
602 | 642 | ||
603 | static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | 643 | static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, |
604 | resource_size_t start, resource_size_t len, | 644 | acpi_handle acpi_dev_handle) |
605 | unsigned int irq) | ||
606 | { | 645 | { |
607 | u32 vendor, intfcaps, intmask; | 646 | u32 vendor, intfcaps, intmask; |
608 | int rc, i, irq_s, irq_e, probe; | 647 | int rc, i, irq_s, irq_e, probe; |
@@ -622,7 +661,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | |||
622 | chip->acpi_dev_handle = acpi_dev_handle; | 661 | chip->acpi_dev_handle = acpi_dev_handle; |
623 | #endif | 662 | #endif |
624 | 663 | ||
625 | chip->vendor.iobase = devm_ioremap(dev, start, len); | 664 | chip->vendor.iobase = devm_ioremap(dev, tpm_info->start, tpm_info->len); |
626 | if (!chip->vendor.iobase) | 665 | if (!chip->vendor.iobase) |
627 | return -EIO; | 666 | return -EIO; |
628 | 667 | ||
@@ -707,7 +746,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | |||
707 | chip->vendor.iobase + | 746 | chip->vendor.iobase + |
708 | TPM_INT_ENABLE(chip->vendor.locality)); | 747 | TPM_INT_ENABLE(chip->vendor.locality)); |
709 | if (interrupts) | 748 | if (interrupts) |
710 | chip->vendor.irq = irq; | 749 | chip->vendor.irq = tpm_info->irq; |
711 | if (interrupts && !chip->vendor.irq) { | 750 | if (interrupts && !chip->vendor.irq) { |
712 | irq_s = | 751 | irq_s = |
713 | ioread8(chip->vendor.iobase + | 752 | ioread8(chip->vendor.iobase + |
@@ -890,27 +929,27 @@ static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); | |||
890 | static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | 929 | static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, |
891 | const struct pnp_device_id *pnp_id) | 930 | const struct pnp_device_id *pnp_id) |
892 | { | 931 | { |
893 | resource_size_t start, len; | 932 | struct tpm_info tpm_info = tis_default_info; |
894 | unsigned int irq = 0; | ||
895 | acpi_handle acpi_dev_handle = NULL; | 933 | acpi_handle acpi_dev_handle = NULL; |
896 | 934 | ||
897 | start = pnp_mem_start(pnp_dev, 0); | 935 | tpm_info.start = pnp_mem_start(pnp_dev, 0); |
898 | len = pnp_mem_len(pnp_dev, 0); | 936 | tpm_info.len = pnp_mem_len(pnp_dev, 0); |
899 | 937 | ||
900 | if (pnp_irq_valid(pnp_dev, 0)) | 938 | if (pnp_irq_valid(pnp_dev, 0)) |
901 | irq = pnp_irq(pnp_dev, 0); | 939 | tpm_info.irq = pnp_irq(pnp_dev, 0); |
902 | else | 940 | else |
903 | interrupts = false; | 941 | interrupts = false; |
904 | 942 | ||
905 | if (is_itpm(pnp_dev)) | ||
906 | itpm = true; | ||
907 | |||
908 | #ifdef CONFIG_ACPI | 943 | #ifdef CONFIG_ACPI |
909 | if (pnp_acpi_device(pnp_dev)) | 944 | if (pnp_acpi_device(pnp_dev)) { |
945 | if (is_itpm(pnp_acpi_device(pnp_dev))) | ||
946 | itpm = true; | ||
947 | |||
910 | acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle; | 948 | acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle; |
949 | } | ||
911 | #endif | 950 | #endif |
912 | 951 | ||
913 | return tpm_tis_init(&pnp_dev->dev, acpi_dev_handle, start, len, irq); | 952 | return tpm_tis_init(&pnp_dev->dev, &tpm_info, acpi_dev_handle); |
914 | } | 953 | } |
915 | 954 | ||
916 | static struct pnp_device_id tpm_pnp_tbl[] = { | 955 | static struct pnp_device_id tpm_pnp_tbl[] = { |
@@ -930,6 +969,7 @@ MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); | |||
930 | static void tpm_tis_pnp_remove(struct pnp_dev *dev) | 969 | static void tpm_tis_pnp_remove(struct pnp_dev *dev) |
931 | { | 970 | { |
932 | struct tpm_chip *chip = pnp_get_drvdata(dev); | 971 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
972 | |||
933 | tpm_chip_unregister(chip); | 973 | tpm_chip_unregister(chip); |
934 | tpm_tis_remove(chip); | 974 | tpm_tis_remove(chip); |
935 | } | 975 | } |
@@ -950,6 +990,79 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | |||
950 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | 990 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); |
951 | #endif | 991 | #endif |
952 | 992 | ||
993 | #ifdef CONFIG_ACPI | ||
994 | static int tpm_check_resource(struct acpi_resource *ares, void *data) | ||
995 | { | ||
996 | struct tpm_info *tpm_info = (struct tpm_info *) data; | ||
997 | struct resource res; | ||
998 | |||
999 | if (acpi_dev_resource_interrupt(ares, 0, &res)) { | ||
1000 | tpm_info->irq = res.start; | ||
1001 | } else if (acpi_dev_resource_memory(ares, &res)) { | ||
1002 | tpm_info->start = res.start; | ||
1003 | tpm_info->len = resource_size(&res); | ||
1004 | } | ||
1005 | |||
1006 | return 1; | ||
1007 | } | ||
1008 | |||
1009 | static int tpm_tis_acpi_init(struct acpi_device *acpi_dev) | ||
1010 | { | ||
1011 | struct list_head resources; | ||
1012 | struct tpm_info tpm_info = tis_default_info; | ||
1013 | int ret; | ||
1014 | |||
1015 | if (!is_fifo(acpi_dev)) | ||
1016 | return -ENODEV; | ||
1017 | |||
1018 | INIT_LIST_HEAD(&resources); | ||
1019 | ret = acpi_dev_get_resources(acpi_dev, &resources, tpm_check_resource, | ||
1020 | &tpm_info); | ||
1021 | if (ret < 0) | ||
1022 | return ret; | ||
1023 | |||
1024 | acpi_dev_free_resource_list(&resources); | ||
1025 | |||
1026 | if (!tpm_info.irq) | ||
1027 | interrupts = false; | ||
1028 | |||
1029 | if (is_itpm(acpi_dev)) | ||
1030 | itpm = true; | ||
1031 | |||
1032 | return tpm_tis_init(&acpi_dev->dev, &tpm_info, acpi_dev->handle); | ||
1033 | } | ||
1034 | |||
1035 | static int tpm_tis_acpi_remove(struct acpi_device *dev) | ||
1036 | { | ||
1037 | struct tpm_chip *chip = dev_get_drvdata(&dev->dev); | ||
1038 | |||
1039 | tpm_chip_unregister(chip); | ||
1040 | tpm_tis_remove(chip); | ||
1041 | |||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static struct acpi_device_id tpm_acpi_tbl[] = { | ||
1046 | {"MSFT0101", 0}, /* TPM 2.0 */ | ||
1047 | /* Add new here */ | ||
1048 | {"", 0}, /* User Specified */ | ||
1049 | {"", 0} /* Terminator */ | ||
1050 | }; | ||
1051 | MODULE_DEVICE_TABLE(acpi, tpm_acpi_tbl); | ||
1052 | |||
1053 | static struct acpi_driver tis_acpi_driver = { | ||
1054 | .name = "tpm_tis", | ||
1055 | .ids = tpm_acpi_tbl, | ||
1056 | .ops = { | ||
1057 | .add = tpm_tis_acpi_init, | ||
1058 | .remove = tpm_tis_acpi_remove, | ||
1059 | }, | ||
1060 | .drv = { | ||
1061 | .pm = &tpm_tis_pm, | ||
1062 | }, | ||
1063 | }; | ||
1064 | #endif | ||
1065 | |||
953 | static struct platform_driver tis_drv = { | 1066 | static struct platform_driver tis_drv = { |
954 | .driver = { | 1067 | .driver = { |
955 | .name = "tpm_tis", | 1068 | .name = "tpm_tis", |
@@ -966,9 +1079,25 @@ static int __init init_tis(void) | |||
966 | { | 1079 | { |
967 | int rc; | 1080 | int rc; |
968 | #ifdef CONFIG_PNP | 1081 | #ifdef CONFIG_PNP |
969 | if (!force) | 1082 | if (!force) { |
970 | return pnp_register_driver(&tis_pnp_driver); | 1083 | rc = pnp_register_driver(&tis_pnp_driver); |
1084 | if (rc) | ||
1085 | return rc; | ||
1086 | } | ||
1087 | #endif | ||
1088 | #ifdef CONFIG_ACPI | ||
1089 | if (!force) { | ||
1090 | rc = acpi_bus_register_driver(&tis_acpi_driver); | ||
1091 | if (rc) { | ||
1092 | #ifdef CONFIG_PNP | ||
1093 | pnp_unregister_driver(&tis_pnp_driver); | ||
971 | #endif | 1094 | #endif |
1095 | return rc; | ||
1096 | } | ||
1097 | } | ||
1098 | #endif | ||
1099 | if (!force) | ||
1100 | return 0; | ||
972 | 1101 | ||
973 | rc = platform_driver_register(&tis_drv); | 1102 | rc = platform_driver_register(&tis_drv); |
974 | if (rc < 0) | 1103 | if (rc < 0) |
@@ -978,7 +1107,7 @@ static int __init init_tis(void) | |||
978 | rc = PTR_ERR(pdev); | 1107 | rc = PTR_ERR(pdev); |
979 | goto err_dev; | 1108 | goto err_dev; |
980 | } | 1109 | } |
981 | rc = tpm_tis_init(&pdev->dev, NULL, TIS_MEM_BASE, TIS_MEM_LEN, 0); | 1110 | rc = tpm_tis_init(&pdev->dev, &tis_default_info, NULL); |
982 | if (rc) | 1111 | if (rc) |
983 | goto err_init; | 1112 | goto err_init; |
984 | return 0; | 1113 | return 0; |
@@ -992,9 +1121,14 @@ err_dev: | |||
992 | static void __exit cleanup_tis(void) | 1121 | static void __exit cleanup_tis(void) |
993 | { | 1122 | { |
994 | struct tpm_chip *chip; | 1123 | struct tpm_chip *chip; |
995 | #ifdef CONFIG_PNP | 1124 | #if defined(CONFIG_PNP) || defined(CONFIG_ACPI) |
996 | if (!force) { | 1125 | if (!force) { |
1126 | #ifdef CONFIG_ACPI | ||
1127 | acpi_bus_unregister_driver(&tis_acpi_driver); | ||
1128 | #endif | ||
1129 | #ifdef CONFIG_PNP | ||
997 | pnp_unregister_driver(&tis_pnp_driver); | 1130 | pnp_unregister_driver(&tis_pnp_driver); |
1131 | #endif | ||
998 | return; | 1132 | return; |
999 | } | 1133 | } |
1000 | #endif | 1134 | #endif |