diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-11 23:25:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-11 23:25:11 -0500 |
commit | 8cc748aa76c921d8834ef00f762f31acd2c93aa8 (patch) | |
tree | 764b0ba9b9c16658bbb1077458605dc3faac0411 | |
parent | 7184487f14eb7c2fcf8337bb16c6a63b6db1252e (diff) | |
parent | 04f81f0154e4bf002be6f4d85668ce1257efa4d9 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security layer updates from James Morris:
"Highlights:
- Smack adds secmark support for Netfilter
- /proc/keys is now mandatory if CONFIG_KEYS=y
- TPM gets its own device class
- Added TPM 2.0 support
- Smack file hook rework (all Smack users should review this!)"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (64 commits)
cipso: don't use IPCB() to locate the CIPSO IP option
SELinux: fix error code in policydb_init()
selinux: add security in-core xattr support for pstore and debugfs
selinux: quiet the filesystem labeling behavior message
selinux: Remove unused function avc_sidcmp()
ima: /proc/keys is now mandatory
Smack: Repair netfilter dependency
X.509: silence asn1 compiler debug output
X.509: shut up about included cert for silent build
KEYS: Make /proc/keys unconditional if CONFIG_KEYS=y
MAINTAINERS: email update
tpm/tpm_tis: Add missing ifdef CONFIG_ACPI for pnp_acpi_device
smack: fix possible use after frees in task_security() callers
smack: Add missing logging in bidirectional UDS connect check
Smack: secmark support for netfilter
Smack: Rework file hooks
tpm: fix format string error in tpm-chip.c
char/tpm/tpm_crb: fix build error
smack: Fix a bidirectional UDS connect check typo
smack: introduce a special case for tmpfs in smack_d_instantiate()
...
45 files changed, 2658 insertions, 1082 deletions
diff --git a/Documentation/ABI/stable/sysfs-class-tpm b/Documentation/ABI/stable/sysfs-class-tpm index a60b45e2493b..9f790eebb5d2 100644 --- a/Documentation/ABI/stable/sysfs-class-tpm +++ b/Documentation/ABI/stable/sysfs-class-tpm | |||
@@ -1,4 +1,4 @@ | |||
1 | What: /sys/class/misc/tpmX/device/ | 1 | What: /sys/class/tpm/tpmX/device/ |
2 | Date: April 2005 | 2 | Date: April 2005 |
3 | KernelVersion: 2.6.12 | 3 | KernelVersion: 2.6.12 |
4 | Contact: tpmdd-devel@lists.sf.net | 4 | Contact: tpmdd-devel@lists.sf.net |
@@ -6,7 +6,7 @@ Description: The device/ directory under a specific TPM instance exposes | |||
6 | the properties of that TPM chip | 6 | the properties of that TPM chip |
7 | 7 | ||
8 | 8 | ||
9 | What: /sys/class/misc/tpmX/device/active | 9 | What: /sys/class/tpm/tpmX/device/active |
10 | Date: April 2006 | 10 | Date: April 2006 |
11 | KernelVersion: 2.6.17 | 11 | KernelVersion: 2.6.17 |
12 | Contact: tpmdd-devel@lists.sf.net | 12 | Contact: tpmdd-devel@lists.sf.net |
@@ -18,7 +18,7 @@ Description: The "active" property prints a '1' if the TPM chip is accepting | |||
18 | section 17 for more information on which commands are | 18 | section 17 for more information on which commands are |
19 | available. | 19 | available. |
20 | 20 | ||
21 | What: /sys/class/misc/tpmX/device/cancel | 21 | What: /sys/class/tpm/tpmX/device/cancel |
22 | Date: June 2005 | 22 | Date: June 2005 |
23 | KernelVersion: 2.6.13 | 23 | KernelVersion: 2.6.13 |
24 | Contact: tpmdd-devel@lists.sf.net | 24 | Contact: tpmdd-devel@lists.sf.net |
@@ -26,7 +26,7 @@ Description: The "cancel" property allows you to cancel the currently | |||
26 | pending TPM command. Writing any value to cancel will call the | 26 | pending TPM command. Writing any value to cancel will call the |
27 | TPM vendor specific cancel operation. | 27 | TPM vendor specific cancel operation. |
28 | 28 | ||
29 | What: /sys/class/misc/tpmX/device/caps | 29 | What: /sys/class/tpm/tpmX/device/caps |
30 | Date: April 2005 | 30 | Date: April 2005 |
31 | KernelVersion: 2.6.12 | 31 | KernelVersion: 2.6.12 |
32 | Contact: tpmdd-devel@lists.sf.net | 32 | Contact: tpmdd-devel@lists.sf.net |
@@ -43,7 +43,7 @@ Description: The "caps" property contains TPM manufacturer and version info. | |||
43 | the chip supports. Firmware version is that of the chip and | 43 | the chip supports. Firmware version is that of the chip and |
44 | is manufacturer specific. | 44 | is manufacturer specific. |
45 | 45 | ||
46 | What: /sys/class/misc/tpmX/device/durations | 46 | What: /sys/class/tpm/tpmX/device/durations |
47 | Date: March 2011 | 47 | Date: March 2011 |
48 | KernelVersion: 3.1 | 48 | KernelVersion: 3.1 |
49 | Contact: tpmdd-devel@lists.sf.net | 49 | Contact: tpmdd-devel@lists.sf.net |
@@ -66,7 +66,7 @@ Description: The "durations" property shows the 3 vendor-specific values | |||
66 | scaled to be displayed in usecs. In this case "[adjusted]" | 66 | scaled to be displayed in usecs. In this case "[adjusted]" |
67 | will be displayed in place of "[original]". | 67 | will be displayed in place of "[original]". |
68 | 68 | ||
69 | What: /sys/class/misc/tpmX/device/enabled | 69 | What: /sys/class/tpm/tpmX/device/enabled |
70 | Date: April 2006 | 70 | Date: April 2006 |
71 | KernelVersion: 2.6.17 | 71 | KernelVersion: 2.6.17 |
72 | Contact: tpmdd-devel@lists.sf.net | 72 | Contact: tpmdd-devel@lists.sf.net |
@@ -75,7 +75,7 @@ Description: The "enabled" property prints a '1' if the TPM chip is enabled, | |||
75 | may be visible but produce a '0' after some operation that | 75 | may be visible but produce a '0' after some operation that |
76 | disables the TPM. | 76 | disables the TPM. |
77 | 77 | ||
78 | What: /sys/class/misc/tpmX/device/owned | 78 | What: /sys/class/tpm/tpmX/device/owned |
79 | Date: April 2006 | 79 | Date: April 2006 |
80 | KernelVersion: 2.6.17 | 80 | KernelVersion: 2.6.17 |
81 | Contact: tpmdd-devel@lists.sf.net | 81 | Contact: tpmdd-devel@lists.sf.net |
@@ -83,7 +83,7 @@ Description: The "owned" property produces a '1' if the TPM_TakeOwnership | |||
83 | ordinal has been executed successfully in the chip. A '0' | 83 | ordinal has been executed successfully in the chip. A '0' |
84 | indicates that ownership hasn't been taken. | 84 | indicates that ownership hasn't been taken. |
85 | 85 | ||
86 | What: /sys/class/misc/tpmX/device/pcrs | 86 | What: /sys/class/tpm/tpmX/device/pcrs |
87 | Date: April 2005 | 87 | Date: April 2005 |
88 | KernelVersion: 2.6.12 | 88 | KernelVersion: 2.6.12 |
89 | Contact: tpmdd-devel@lists.sf.net | 89 | Contact: tpmdd-devel@lists.sf.net |
@@ -106,7 +106,7 @@ Description: The "pcrs" property will dump the current value of all Platform | |||
106 | 1.2 chips, PCRs represent SHA-1 hashes, which are 20 bytes | 106 | 1.2 chips, PCRs represent SHA-1 hashes, which are 20 bytes |
107 | long. Use the "caps" property to determine TPM version. | 107 | long. Use the "caps" property to determine TPM version. |
108 | 108 | ||
109 | What: /sys/class/misc/tpmX/device/pubek | 109 | What: /sys/class/tpm/tpmX/device/pubek |
110 | Date: April 2005 | 110 | Date: April 2005 |
111 | KernelVersion: 2.6.12 | 111 | KernelVersion: 2.6.12 |
112 | Contact: tpmdd-devel@lists.sf.net | 112 | Contact: tpmdd-devel@lists.sf.net |
@@ -158,7 +158,7 @@ Description: The "pubek" property will return the TPM's public endorsement | |||
158 | Modulus Length: 256 (bytes) | 158 | Modulus Length: 256 (bytes) |
159 | Modulus: The 256 byte Endorsement Key modulus | 159 | Modulus: The 256 byte Endorsement Key modulus |
160 | 160 | ||
161 | What: /sys/class/misc/tpmX/device/temp_deactivated | 161 | What: /sys/class/tpm/tpmX/device/temp_deactivated |
162 | Date: April 2006 | 162 | Date: April 2006 |
163 | KernelVersion: 2.6.17 | 163 | KernelVersion: 2.6.17 |
164 | Contact: tpmdd-devel@lists.sf.net | 164 | Contact: tpmdd-devel@lists.sf.net |
@@ -167,7 +167,7 @@ Description: The "temp_deactivated" property returns a '1' if the chip has | |||
167 | cycle. Whether a warm boot (reboot) will clear a TPM chip | 167 | cycle. Whether a warm boot (reboot) will clear a TPM chip |
168 | from a temp_deactivated state is platform specific. | 168 | from a temp_deactivated state is platform specific. |
169 | 169 | ||
170 | What: /sys/class/misc/tpmX/device/timeouts | 170 | What: /sys/class/tpm/tpmX/device/timeouts |
171 | Date: March 2011 | 171 | Date: March 2011 |
172 | KernelVersion: 3.1 | 172 | KernelVersion: 3.1 |
173 | Contact: tpmdd-devel@lists.sf.net | 173 | Contact: tpmdd-devel@lists.sf.net |
diff --git a/Documentation/devicetree/bindings/security/tpm/st33zp24-i2c.txt b/Documentation/devicetree/bindings/security/tpm/st33zp24-i2c.txt new file mode 100644 index 000000000000..3ad115efed1e --- /dev/null +++ b/Documentation/devicetree/bindings/security/tpm/st33zp24-i2c.txt | |||
@@ -0,0 +1,36 @@ | |||
1 | * STMicroelectronics SAS. ST33ZP24 TPM SoC | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "st,st33zp24-i2c". | ||
5 | - clock-frequency: I²C work frequency. | ||
6 | - reg: address on the bus | ||
7 | |||
8 | Optional ST33ZP24 Properties: | ||
9 | - interrupt-parent: phandle for the interrupt gpio controller | ||
10 | - interrupts: GPIO interrupt to which the chip is connected | ||
11 | - lpcpd-gpios: Output GPIO pin used for ST33ZP24 power management D1/D2 state. | ||
12 | If set, power must be present when the platform is going into sleep/hibernate mode. | ||
13 | |||
14 | Optional SoC Specific Properties: | ||
15 | - pinctrl-names: Contains only one value - "default". | ||
16 | - pintctrl-0: Specifies the pin control groups used for this controller. | ||
17 | |||
18 | Example (for ARM-based BeagleBoard xM with ST33ZP24 on I2C2): | ||
19 | |||
20 | &i2c2 { | ||
21 | |||
22 | status = "okay"; | ||
23 | |||
24 | st33zp24: st33zp24@13 { | ||
25 | |||
26 | compatible = "st,st33zp24-i2c"; | ||
27 | |||
28 | reg = <0x13>; | ||
29 | clock-frequency = <400000>; | ||
30 | |||
31 | interrupt-parent = <&gpio5>; | ||
32 | interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; | ||
33 | |||
34 | lpcpd-gpios = <&gpio5 15 GPIO_ACTIVE_HIGH>; | ||
35 | }; | ||
36 | }; | ||
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 821c936e1a63..c9e7f4f223a5 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt | |||
@@ -323,8 +323,6 @@ about the status of the key service: | |||
323 | U Under construction by callback to userspace | 323 | U Under construction by callback to userspace |
324 | N Negative key | 324 | N Negative key |
325 | 325 | ||
326 | This file must be enabled at kernel configuration time as it allows anyone | ||
327 | to list the keys database. | ||
328 | 326 | ||
329 | (*) /proc/key-users | 327 | (*) /proc/key-users |
330 | 328 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 37c10098a627..c4a8703ab493 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4917,7 +4917,7 @@ F: drivers/ipack/ | |||
4917 | 4917 | ||
4918 | INTEGRITY MEASUREMENT ARCHITECTURE (IMA) | 4918 | INTEGRITY MEASUREMENT ARCHITECTURE (IMA) |
4919 | M: Mimi Zohar <zohar@linux.vnet.ibm.com> | 4919 | M: Mimi Zohar <zohar@linux.vnet.ibm.com> |
4920 | M: Dmitry Kasatkin <d.kasatkin@samsung.com> | 4920 | M: Dmitry Kasatkin <dmitry.kasatkin@gmail.com> |
4921 | L: linux-ima-devel@lists.sourceforge.net | 4921 | L: linux-ima-devel@lists.sourceforge.net |
4922 | L: linux-ima-user@lists.sourceforge.net | 4922 | L: linux-ima-user@lists.sourceforge.net |
4923 | L: linux-security-module@vger.kernel.org | 4923 | L: linux-security-module@vger.kernel.org |
@@ -9817,13 +9817,21 @@ F: drivers/media/pci/tw68/ | |||
9817 | 9817 | ||
9818 | TPM DEVICE DRIVER | 9818 | TPM DEVICE DRIVER |
9819 | M: Peter Huewe <peterhuewe@gmx.de> | 9819 | M: Peter Huewe <peterhuewe@gmx.de> |
9820 | M: Ashley Lai <ashley@ashleylai.com> | ||
9821 | M: Marcel Selhorst <tpmdd@selhorst.net> | 9820 | M: Marcel Selhorst <tpmdd@selhorst.net> |
9822 | W: http://tpmdd.sourceforge.net | 9821 | W: http://tpmdd.sourceforge.net |
9823 | L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers) | 9822 | L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers) |
9823 | Q: git git://github.com/PeterHuewe/linux-tpmdd.git | ||
9824 | T: https://github.com/PeterHuewe/linux-tpmdd | ||
9824 | S: Maintained | 9825 | S: Maintained |
9825 | F: drivers/char/tpm/ | 9826 | F: drivers/char/tpm/ |
9826 | 9827 | ||
9828 | TPM IBM_VTPM DEVICE DRIVER | ||
9829 | M: Ashley Lai <ashleydlai@gmail.com> | ||
9830 | W: http://tpmdd.sourceforge.net | ||
9831 | L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers) | ||
9832 | S: Maintained | ||
9833 | F: drivers/char/tpm/tpm_ibmvtpm* | ||
9834 | |||
9827 | TRACING | 9835 | TRACING |
9828 | M: Steven Rostedt <rostedt@goodmis.org> | 9836 | M: Steven Rostedt <rostedt@goodmis.org> |
9829 | M: Ingo Molnar <mingo@redhat.com> | 9837 | M: Ingo Molnar <mingo@redhat.com> |
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index c54cac3f8bc8..9d4e37549eb2 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -100,15 +100,15 @@ config TCG_IBMVTPM | |||
100 | will be accessible from within Linux. To compile this driver | 100 | will be accessible from within Linux. To compile this driver |
101 | as a module, choose M here; the module will be called tpm_ibmvtpm. | 101 | as a module, choose M here; the module will be called tpm_ibmvtpm. |
102 | 102 | ||
103 | config TCG_ST33_I2C | 103 | config TCG_TIS_I2C_ST33 |
104 | tristate "STMicroelectronics ST33 I2C TPM" | 104 | tristate "TPM Interface Specification 1.2 Interface (I2C - STMicroelectronics)" |
105 | depends on I2C | 105 | depends on I2C |
106 | depends on GPIOLIB | 106 | depends on GPIOLIB |
107 | ---help--- | 107 | ---help--- |
108 | If you have a TPM security chip from STMicroelectronics working with | 108 | If you have a TPM security chip from STMicroelectronics working with |
109 | an I2C bus say Yes and it will be accessible from within Linux. | 109 | an I2C bus say Yes and it will be accessible from within Linux. |
110 | To compile this driver as a module, choose M here; the module will be | 110 | To compile this driver as a module, choose M here; the module will be |
111 | called tpm_stm_st33_i2c. | 111 | called tpm_i2c_stm_st33. |
112 | 112 | ||
113 | config TCG_XEN | 113 | config TCG_XEN |
114 | tristate "XEN TPM Interface" | 114 | tristate "XEN TPM Interface" |
@@ -122,4 +122,13 @@ config TCG_XEN | |||
122 | To compile this driver as a module, choose M here; the module | 122 | To compile this driver as a module, choose M here; the module |
123 | will be called xen-tpmfront. | 123 | will be called xen-tpmfront. |
124 | 124 | ||
125 | config TCG_CRB | ||
126 | tristate "TPM 2.0 CRB Interface" | ||
127 | depends on X86 && ACPI | ||
128 | ---help--- | ||
129 | If you have a TPM security chip that is compliant with the | ||
130 | TCG CRB 2.0 TPM specification say Yes and it will be accessible | ||
131 | from within Linux. To compile this driver as a module, choose | ||
132 | M here; the module will be called tpm_crb. | ||
133 | |||
125 | endif # TCG_TPM | 134 | endif # TCG_TPM |
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 4d85dd681b81..990cf183931d 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the kernel tpm device drivers. | 2 | # Makefile for the kernel tpm device drivers. |
3 | # | 3 | # |
4 | obj-$(CONFIG_TCG_TPM) += tpm.o | 4 | obj-$(CONFIG_TCG_TPM) += tpm.o |
5 | tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o | 5 | tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o |
6 | tpm-$(CONFIG_ACPI) += tpm_ppi.o | 6 | tpm-$(CONFIG_ACPI) += tpm_ppi.o |
7 | 7 | ||
8 | ifdef CONFIG_ACPI | 8 | ifdef CONFIG_ACPI |
@@ -20,5 +20,6 @@ obj-$(CONFIG_TCG_NSC) += tpm_nsc.o | |||
20 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o | 20 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o |
21 | obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o | 21 | obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o |
22 | obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o | 22 | obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o |
23 | obj-$(CONFIG_TCG_ST33_I2C) += tpm_i2c_stm_st33.o | 23 | obj-$(CONFIG_TCG_TIS_I2C_ST33) += tpm_i2c_stm_st33.o |
24 | obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o | 24 | obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o |
25 | obj-$(CONFIG_TCG_CRB) += tpm_crb.o | ||
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c new file mode 100644 index 000000000000..1d278ccd751f --- /dev/null +++ b/drivers/char/tpm/tpm-chip.c | |||
@@ -0,0 +1,256 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 IBM Corporation | ||
3 | * Copyright (C) 2014 Intel Corporation | ||
4 | * | ||
5 | * Authors: | ||
6 | * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | ||
7 | * Leendert van Doorn <leendert@watson.ibm.com> | ||
8 | * Dave Safford <safford@watson.ibm.com> | ||
9 | * Reiner Sailer <sailer@watson.ibm.com> | ||
10 | * Kylene Hall <kjhall@us.ibm.com> | ||
11 | * | ||
12 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
13 | * | ||
14 | * TPM chip management routines. | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or | ||
17 | * modify it under the terms of the GNU General Public License as | ||
18 | * published by the Free Software Foundation, version 2 of the | ||
19 | * License. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/poll.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/freezer.h> | ||
28 | #include <linux/major.h> | ||
29 | #include "tpm.h" | ||
30 | #include "tpm_eventlog.h" | ||
31 | |||
32 | static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); | ||
33 | static LIST_HEAD(tpm_chip_list); | ||
34 | static DEFINE_SPINLOCK(driver_lock); | ||
35 | |||
36 | struct class *tpm_class; | ||
37 | dev_t tpm_devt; | ||
38 | |||
39 | /* | ||
40 | * tpm_chip_find_get - return tpm_chip for a given chip number | ||
41 | * @chip_num the device number for the chip | ||
42 | */ | ||
43 | struct tpm_chip *tpm_chip_find_get(int chip_num) | ||
44 | { | ||
45 | struct tpm_chip *pos, *chip = NULL; | ||
46 | |||
47 | rcu_read_lock(); | ||
48 | list_for_each_entry_rcu(pos, &tpm_chip_list, list) { | ||
49 | if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) | ||
50 | continue; | ||
51 | |||
52 | if (try_module_get(pos->pdev->driver->owner)) { | ||
53 | chip = pos; | ||
54 | break; | ||
55 | } | ||
56 | } | ||
57 | rcu_read_unlock(); | ||
58 | return chip; | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * tpm_dev_release() - free chip memory and the device number | ||
63 | * @dev: the character device for the TPM chip | ||
64 | * | ||
65 | * This is used as the release function for the character device. | ||
66 | */ | ||
67 | static void tpm_dev_release(struct device *dev) | ||
68 | { | ||
69 | struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev); | ||
70 | |||
71 | spin_lock(&driver_lock); | ||
72 | clear_bit(chip->dev_num, dev_mask); | ||
73 | spin_unlock(&driver_lock); | ||
74 | kfree(chip); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * tpmm_chip_alloc() - allocate a new struct tpm_chip instance | ||
79 | * @dev: device to which the chip is associated | ||
80 | * @ops: struct tpm_class_ops instance | ||
81 | * | ||
82 | * Allocates a new struct tpm_chip instance and assigns a free | ||
83 | * device number for it. Caller does not have to worry about | ||
84 | * freeing the allocated resources. When the devices is removed | ||
85 | * devres calls tpmm_chip_remove() to do the job. | ||
86 | */ | ||
87 | struct tpm_chip *tpmm_chip_alloc(struct device *dev, | ||
88 | const struct tpm_class_ops *ops) | ||
89 | { | ||
90 | struct tpm_chip *chip; | ||
91 | |||
92 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
93 | if (chip == NULL) | ||
94 | return ERR_PTR(-ENOMEM); | ||
95 | |||
96 | mutex_init(&chip->tpm_mutex); | ||
97 | INIT_LIST_HEAD(&chip->list); | ||
98 | |||
99 | chip->ops = ops; | ||
100 | |||
101 | spin_lock(&driver_lock); | ||
102 | chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); | ||
103 | spin_unlock(&driver_lock); | ||
104 | |||
105 | if (chip->dev_num >= TPM_NUM_DEVICES) { | ||
106 | dev_err(dev, "No available tpm device numbers\n"); | ||
107 | kfree(chip); | ||
108 | return ERR_PTR(-ENOMEM); | ||
109 | } | ||
110 | |||
111 | set_bit(chip->dev_num, dev_mask); | ||
112 | |||
113 | scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num); | ||
114 | |||
115 | chip->pdev = dev; | ||
116 | |||
117 | dev_set_drvdata(dev, chip); | ||
118 | |||
119 | chip->dev.class = tpm_class; | ||
120 | chip->dev.release = tpm_dev_release; | ||
121 | chip->dev.parent = chip->pdev; | ||
122 | |||
123 | if (chip->dev_num == 0) | ||
124 | chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR); | ||
125 | else | ||
126 | chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num); | ||
127 | |||
128 | dev_set_name(&chip->dev, "%s", chip->devname); | ||
129 | |||
130 | device_initialize(&chip->dev); | ||
131 | |||
132 | chip->cdev.owner = chip->pdev->driver->owner; | ||
133 | cdev_init(&chip->cdev, &tpm_fops); | ||
134 | |||
135 | return chip; | ||
136 | } | ||
137 | EXPORT_SYMBOL_GPL(tpmm_chip_alloc); | ||
138 | |||
139 | static int tpm_dev_add_device(struct tpm_chip *chip) | ||
140 | { | ||
141 | int rc; | ||
142 | |||
143 | rc = device_add(&chip->dev); | ||
144 | if (rc) { | ||
145 | dev_err(&chip->dev, | ||
146 | "unable to device_register() %s, major %d, minor %d, err=%d\n", | ||
147 | chip->devname, MAJOR(chip->dev.devt), | ||
148 | MINOR(chip->dev.devt), rc); | ||
149 | |||
150 | return rc; | ||
151 | } | ||
152 | |||
153 | rc = cdev_add(&chip->cdev, chip->dev.devt, 1); | ||
154 | if (rc) { | ||
155 | dev_err(&chip->dev, | ||
156 | "unable to cdev_add() %s, major %d, minor %d, err=%d\n", | ||
157 | chip->devname, MAJOR(chip->dev.devt), | ||
158 | MINOR(chip->dev.devt), rc); | ||
159 | |||
160 | device_unregister(&chip->dev); | ||
161 | return rc; | ||
162 | } | ||
163 | |||
164 | return rc; | ||
165 | } | ||
166 | |||
167 | static void tpm_dev_del_device(struct tpm_chip *chip) | ||
168 | { | ||
169 | cdev_del(&chip->cdev); | ||
170 | device_unregister(&chip->dev); | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * tpm_chip_register() - create a character device for the TPM chip | ||
175 | * @chip: TPM chip to use. | ||
176 | * | ||
177 | * Creates a character device for the TPM chip and adds sysfs interfaces for | ||
178 | * the device, PPI and TCPA. As the last step this function adds the | ||
179 | * chip to the list of TPM chips available for use. | ||
180 | * | ||
181 | * NOTE: This function should be only called after the chip initialization | ||
182 | * is complete. | ||
183 | * | ||
184 | * Called from tpm_<specific>.c probe function only for devices | ||
185 | * the driver has determined it should claim. Prior to calling | ||
186 | * this function the specific probe function has called pci_enable_device | ||
187 | * upon errant exit from this function specific probe function should call | ||
188 | * pci_disable_device | ||
189 | */ | ||
190 | int tpm_chip_register(struct tpm_chip *chip) | ||
191 | { | ||
192 | int rc; | ||
193 | |||
194 | rc = tpm_dev_add_device(chip); | ||
195 | if (rc) | ||
196 | return rc; | ||
197 | |||
198 | /* Populate sysfs for TPM1 devices. */ | ||
199 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { | ||
200 | rc = tpm_sysfs_add_device(chip); | ||
201 | if (rc) | ||
202 | goto del_misc; | ||
203 | |||
204 | rc = tpm_add_ppi(chip); | ||
205 | if (rc) | ||
206 | goto del_sysfs; | ||
207 | |||
208 | chip->bios_dir = tpm_bios_log_setup(chip->devname); | ||
209 | } | ||
210 | |||
211 | /* Make the chip available. */ | ||
212 | spin_lock(&driver_lock); | ||
213 | list_add_rcu(&chip->list, &tpm_chip_list); | ||
214 | spin_unlock(&driver_lock); | ||
215 | |||
216 | chip->flags |= TPM_CHIP_FLAG_REGISTERED; | ||
217 | |||
218 | return 0; | ||
219 | del_sysfs: | ||
220 | tpm_sysfs_del_device(chip); | ||
221 | del_misc: | ||
222 | tpm_dev_del_device(chip); | ||
223 | return rc; | ||
224 | } | ||
225 | EXPORT_SYMBOL_GPL(tpm_chip_register); | ||
226 | |||
227 | /* | ||
228 | * tpm_chip_unregister() - release the TPM driver | ||
229 | * @chip: TPM chip to use. | ||
230 | * | ||
231 | * Takes the chip first away from the list of available TPM chips and then | ||
232 | * cleans up all the resources reserved by tpm_chip_register(). | ||
233 | * | ||
234 | * NOTE: This function should be only called before deinitializing chip | ||
235 | * resources. | ||
236 | */ | ||
237 | void tpm_chip_unregister(struct tpm_chip *chip) | ||
238 | { | ||
239 | if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED)) | ||
240 | return; | ||
241 | |||
242 | spin_lock(&driver_lock); | ||
243 | list_del_rcu(&chip->list); | ||
244 | spin_unlock(&driver_lock); | ||
245 | synchronize_rcu(); | ||
246 | |||
247 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { | ||
248 | if (chip->bios_dir) | ||
249 | tpm_bios_log_teardown(chip->bios_dir); | ||
250 | tpm_remove_ppi(chip); | ||
251 | tpm_sysfs_del_device(chip); | ||
252 | } | ||
253 | |||
254 | tpm_dev_del_device(chip); | ||
255 | } | ||
256 | EXPORT_SYMBOL_GPL(tpm_chip_unregister); | ||
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c index d9b774e02a1f..de0337ebd658 100644 --- a/drivers/char/tpm/tpm-dev.c +++ b/drivers/char/tpm/tpm-dev.c | |||
@@ -17,7 +17,6 @@ | |||
17 | * License. | 17 | * License. |
18 | * | 18 | * |
19 | */ | 19 | */ |
20 | #include <linux/miscdevice.h> | ||
21 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
22 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
23 | #include "tpm.h" | 22 | #include "tpm.h" |
@@ -54,16 +53,15 @@ static void timeout_work(struct work_struct *work) | |||
54 | 53 | ||
55 | static int tpm_open(struct inode *inode, struct file *file) | 54 | static int tpm_open(struct inode *inode, struct file *file) |
56 | { | 55 | { |
57 | struct miscdevice *misc = file->private_data; | 56 | struct tpm_chip *chip = |
58 | struct tpm_chip *chip = container_of(misc, struct tpm_chip, | 57 | container_of(inode->i_cdev, struct tpm_chip, cdev); |
59 | vendor.miscdev); | ||
60 | struct file_priv *priv; | 58 | struct file_priv *priv; |
61 | 59 | ||
62 | /* It's assured that the chip will be opened just once, | 60 | /* It's assured that the chip will be opened just once, |
63 | * by the check of is_open variable, which is protected | 61 | * by the check of is_open variable, which is protected |
64 | * by driver_lock. */ | 62 | * by driver_lock. */ |
65 | if (test_and_set_bit(0, &chip->is_open)) { | 63 | if (test_and_set_bit(0, &chip->is_open)) { |
66 | dev_dbg(chip->dev, "Another process owns this TPM\n"); | 64 | dev_dbg(chip->pdev, "Another process owns this TPM\n"); |
67 | return -EBUSY; | 65 | return -EBUSY; |
68 | } | 66 | } |
69 | 67 | ||
@@ -81,7 +79,7 @@ static int tpm_open(struct inode *inode, struct file *file) | |||
81 | INIT_WORK(&priv->work, timeout_work); | 79 | INIT_WORK(&priv->work, timeout_work); |
82 | 80 | ||
83 | file->private_data = priv; | 81 | file->private_data = priv; |
84 | get_device(chip->dev); | 82 | get_device(chip->pdev); |
85 | return 0; | 83 | return 0; |
86 | } | 84 | } |
87 | 85 | ||
@@ -168,12 +166,12 @@ static int tpm_release(struct inode *inode, struct file *file) | |||
168 | file->private_data = NULL; | 166 | file->private_data = NULL; |
169 | atomic_set(&priv->data_pending, 0); | 167 | atomic_set(&priv->data_pending, 0); |
170 | clear_bit(0, &priv->chip->is_open); | 168 | clear_bit(0, &priv->chip->is_open); |
171 | put_device(priv->chip->dev); | 169 | put_device(priv->chip->pdev); |
172 | kfree(priv); | 170 | kfree(priv); |
173 | return 0; | 171 | return 0; |
174 | } | 172 | } |
175 | 173 | ||
176 | static const struct file_operations tpm_fops = { | 174 | const struct file_operations tpm_fops = { |
177 | .owner = THIS_MODULE, | 175 | .owner = THIS_MODULE, |
178 | .llseek = no_llseek, | 176 | .llseek = no_llseek, |
179 | .open = tpm_open, | 177 | .open = tpm_open, |
@@ -182,32 +180,4 @@ static const struct file_operations tpm_fops = { | |||
182 | .release = tpm_release, | 180 | .release = tpm_release, |
183 | }; | 181 | }; |
184 | 182 | ||
185 | int tpm_dev_add_device(struct tpm_chip *chip) | ||
186 | { | ||
187 | int rc; | ||
188 | 183 | ||
189 | chip->vendor.miscdev.fops = &tpm_fops; | ||
190 | if (chip->dev_num == 0) | ||
191 | chip->vendor.miscdev.minor = TPM_MINOR; | ||
192 | else | ||
193 | chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR; | ||
194 | |||
195 | chip->vendor.miscdev.name = chip->devname; | ||
196 | chip->vendor.miscdev.parent = chip->dev; | ||
197 | |||
198 | rc = misc_register(&chip->vendor.miscdev); | ||
199 | if (rc) { | ||
200 | chip->vendor.miscdev.name = NULL; | ||
201 | dev_err(chip->dev, | ||
202 | "unable to misc_register %s, minor %d err=%d\n", | ||
203 | chip->vendor.miscdev.name, | ||
204 | chip->vendor.miscdev.minor, rc); | ||
205 | } | ||
206 | return rc; | ||
207 | } | ||
208 | |||
209 | void tpm_dev_del_device(struct tpm_chip *chip) | ||
210 | { | ||
211 | if (chip->vendor.miscdev.name) | ||
212 | misc_deregister(&chip->vendor.miscdev); | ||
213 | } | ||
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 6af17002a115..bf53a3771da5 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 IBM Corporation | 2 | * Copyright (C) 2004 IBM Corporation |
3 | * Copyright (C) 2014 Intel Corporation | ||
3 | * | 4 | * |
4 | * Authors: | 5 | * Authors: |
5 | * Leendert van Doorn <leendert@watson.ibm.com> | 6 | * Leendert van Doorn <leendert@watson.ibm.com> |
@@ -47,10 +48,6 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); | |||
47 | MODULE_PARM_DESC(suspend_pcr, | 48 | MODULE_PARM_DESC(suspend_pcr, |
48 | "PCR to use for dummy writes to faciltate flush on suspend."); | 49 | "PCR to use for dummy writes to faciltate flush on suspend."); |
49 | 50 | ||
50 | static LIST_HEAD(tpm_chip_list); | ||
51 | static DEFINE_SPINLOCK(driver_lock); | ||
52 | static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); | ||
53 | |||
54 | /* | 51 | /* |
55 | * Array with one entry per ordinal defining the maximum amount | 52 | * Array with one entry per ordinal defining the maximum amount |
56 | * of time the chip could take to return the result. The ordinal | 53 | * of time the chip could take to return the result. The ordinal |
@@ -346,7 +343,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
346 | if (count == 0) | 343 | if (count == 0) |
347 | return -ENODATA; | 344 | return -ENODATA; |
348 | if (count > bufsiz) { | 345 | if (count > bufsiz) { |
349 | dev_err(chip->dev, | 346 | dev_err(chip->pdev, |
350 | "invalid count value %x %zx\n", count, bufsiz); | 347 | "invalid count value %x %zx\n", count, bufsiz); |
351 | return -E2BIG; | 348 | return -E2BIG; |
352 | } | 349 | } |
@@ -355,7 +352,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
355 | 352 | ||
356 | rc = chip->ops->send(chip, (u8 *) buf, count); | 353 | rc = chip->ops->send(chip, (u8 *) buf, count); |
357 | if (rc < 0) { | 354 | if (rc < 0) { |
358 | dev_err(chip->dev, | 355 | dev_err(chip->pdev, |
359 | "tpm_transmit: tpm_send: error %zd\n", rc); | 356 | "tpm_transmit: tpm_send: error %zd\n", rc); |
360 | goto out; | 357 | goto out; |
361 | } | 358 | } |
@@ -363,7 +360,10 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
363 | if (chip->vendor.irq) | 360 | if (chip->vendor.irq) |
364 | goto out_recv; | 361 | goto out_recv; |
365 | 362 | ||
366 | stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); | 363 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
364 | stop = jiffies + tpm2_calc_ordinal_duration(chip, ordinal); | ||
365 | else | ||
366 | stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); | ||
367 | do { | 367 | do { |
368 | u8 status = chip->ops->status(chip); | 368 | u8 status = chip->ops->status(chip); |
369 | if ((status & chip->ops->req_complete_mask) == | 369 | if ((status & chip->ops->req_complete_mask) == |
@@ -371,7 +371,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
371 | goto out_recv; | 371 | goto out_recv; |
372 | 372 | ||
373 | if (chip->ops->req_canceled(chip, status)) { | 373 | if (chip->ops->req_canceled(chip, status)) { |
374 | dev_err(chip->dev, "Operation Canceled\n"); | 374 | dev_err(chip->pdev, "Operation Canceled\n"); |
375 | rc = -ECANCELED; | 375 | rc = -ECANCELED; |
376 | goto out; | 376 | goto out; |
377 | } | 377 | } |
@@ -381,14 +381,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
381 | } while (time_before(jiffies, stop)); | 381 | } while (time_before(jiffies, stop)); |
382 | 382 | ||
383 | chip->ops->cancel(chip); | 383 | chip->ops->cancel(chip); |
384 | dev_err(chip->dev, "Operation Timed out\n"); | 384 | dev_err(chip->pdev, "Operation Timed out\n"); |
385 | rc = -ETIME; | 385 | rc = -ETIME; |
386 | goto out; | 386 | goto out; |
387 | 387 | ||
388 | out_recv: | 388 | out_recv: |
389 | rc = chip->ops->recv(chip, (u8 *) buf, bufsiz); | 389 | rc = chip->ops->recv(chip, (u8 *) buf, bufsiz); |
390 | if (rc < 0) | 390 | if (rc < 0) |
391 | dev_err(chip->dev, | 391 | dev_err(chip->pdev, |
392 | "tpm_transmit: tpm_recv: error %zd\n", rc); | 392 | "tpm_transmit: tpm_recv: error %zd\n", rc); |
393 | out: | 393 | out: |
394 | mutex_unlock(&chip->tpm_mutex); | 394 | mutex_unlock(&chip->tpm_mutex); |
@@ -398,9 +398,10 @@ out: | |||
398 | #define TPM_DIGEST_SIZE 20 | 398 | #define TPM_DIGEST_SIZE 20 |
399 | #define TPM_RET_CODE_IDX 6 | 399 | #define TPM_RET_CODE_IDX 6 |
400 | 400 | ||
401 | static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, | 401 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, |
402 | int len, const char *desc) | 402 | int len, const char *desc) |
403 | { | 403 | { |
404 | struct tpm_output_header *header; | ||
404 | int err; | 405 | int err; |
405 | 406 | ||
406 | len = tpm_transmit(chip, (u8 *) cmd, len); | 407 | len = tpm_transmit(chip, (u8 *) cmd, len); |
@@ -409,9 +410,12 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, | |||
409 | else if (len < TPM_HEADER_SIZE) | 410 | else if (len < TPM_HEADER_SIZE) |
410 | return -EFAULT; | 411 | return -EFAULT; |
411 | 412 | ||
412 | err = be32_to_cpu(cmd->header.out.return_code); | 413 | header = cmd; |
414 | |||
415 | err = be32_to_cpu(header->return_code); | ||
413 | if (err != 0 && desc) | 416 | if (err != 0 && desc) |
414 | dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); | 417 | dev_err(chip->pdev, "A TPM error (%d) occurred %s\n", err, |
418 | desc); | ||
415 | 419 | ||
416 | return err; | 420 | return err; |
417 | } | 421 | } |
@@ -448,7 +452,7 @@ ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap, | |||
448 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 452 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
449 | tpm_cmd.params.getcap_in.subcap = subcap_id; | 453 | tpm_cmd.params.getcap_in.subcap = subcap_id; |
450 | } | 454 | } |
451 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc); | 455 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc); |
452 | if (!rc) | 456 | if (!rc) |
453 | *cap = tpm_cmd.params.getcap_out.cap; | 457 | *cap = tpm_cmd.params.getcap_out.cap; |
454 | return rc; | 458 | return rc; |
@@ -464,8 +468,8 @@ void tpm_gen_interrupt(struct tpm_chip *chip) | |||
464 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 468 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
465 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | 469 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; |
466 | 470 | ||
467 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | 471 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
468 | "attempting to determine the timeouts"); | 472 | "attempting to determine the timeouts"); |
469 | } | 473 | } |
470 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); | 474 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); |
471 | 475 | ||
@@ -483,9 +487,10 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) | |||
483 | { | 487 | { |
484 | struct tpm_cmd_t start_cmd; | 488 | struct tpm_cmd_t start_cmd; |
485 | start_cmd.header.in = tpm_startup_header; | 489 | start_cmd.header.in = tpm_startup_header; |
490 | |||
486 | start_cmd.params.startup_in.startup_type = startup_type; | 491 | start_cmd.params.startup_in.startup_type = startup_type; |
487 | return transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, | 492 | return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, |
488 | "attempting to start the TPM"); | 493 | "attempting to start the TPM"); |
489 | } | 494 | } |
490 | 495 | ||
491 | int tpm_get_timeouts(struct tpm_chip *chip) | 496 | int tpm_get_timeouts(struct tpm_chip *chip) |
@@ -500,12 +505,12 @@ int tpm_get_timeouts(struct tpm_chip *chip) | |||
500 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; | 505 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
501 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 506 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
502 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | 507 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; |
503 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL); | 508 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL); |
504 | 509 | ||
505 | if (rc == TPM_ERR_INVALID_POSTINIT) { | 510 | if (rc == TPM_ERR_INVALID_POSTINIT) { |
506 | /* The TPM is not started, we are the first to talk to it. | 511 | /* The TPM is not started, we are the first to talk to it. |
507 | Execute a startup command. */ | 512 | Execute a startup command. */ |
508 | dev_info(chip->dev, "Issuing TPM_STARTUP"); | 513 | dev_info(chip->pdev, "Issuing TPM_STARTUP"); |
509 | if (tpm_startup(chip, TPM_ST_CLEAR)) | 514 | if (tpm_startup(chip, TPM_ST_CLEAR)) |
510 | return rc; | 515 | return rc; |
511 | 516 | ||
@@ -513,11 +518,11 @@ int tpm_get_timeouts(struct tpm_chip *chip) | |||
513 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; | 518 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
514 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 519 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
515 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | 520 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; |
516 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | 521 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
517 | NULL); | 522 | NULL); |
518 | } | 523 | } |
519 | if (rc) { | 524 | if (rc) { |
520 | dev_err(chip->dev, | 525 | dev_err(chip->pdev, |
521 | "A TPM error (%zd) occurred attempting to determine the timeouts\n", | 526 | "A TPM error (%zd) occurred attempting to determine the timeouts\n", |
522 | rc); | 527 | rc); |
523 | goto duration; | 528 | goto duration; |
@@ -556,7 +561,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) | |||
556 | 561 | ||
557 | /* Report adjusted timeouts */ | 562 | /* Report adjusted timeouts */ |
558 | if (chip->vendor.timeout_adjusted) { | 563 | if (chip->vendor.timeout_adjusted) { |
559 | dev_info(chip->dev, | 564 | dev_info(chip->pdev, |
560 | HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", | 565 | HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", |
561 | old_timeout[0], new_timeout[0], | 566 | old_timeout[0], new_timeout[0], |
562 | old_timeout[1], new_timeout[1], | 567 | old_timeout[1], new_timeout[1], |
@@ -575,8 +580,8 @@ duration: | |||
575 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 580 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
576 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; | 581 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; |
577 | 582 | ||
578 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | 583 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
579 | "attempting to determine the durations"); | 584 | "attempting to determine the durations"); |
580 | if (rc) | 585 | if (rc) |
581 | return rc; | 586 | return rc; |
582 | 587 | ||
@@ -603,7 +608,7 @@ duration: | |||
603 | chip->vendor.duration[TPM_MEDIUM] *= 1000; | 608 | chip->vendor.duration[TPM_MEDIUM] *= 1000; |
604 | chip->vendor.duration[TPM_LONG] *= 1000; | 609 | chip->vendor.duration[TPM_LONG] *= 1000; |
605 | chip->vendor.duration_adjusted = true; | 610 | chip->vendor.duration_adjusted = true; |
606 | dev_info(chip->dev, "Adjusting TPM timeout parameters."); | 611 | dev_info(chip->pdev, "Adjusting TPM timeout parameters."); |
607 | } | 612 | } |
608 | return 0; | 613 | return 0; |
609 | } | 614 | } |
@@ -631,32 +636,11 @@ static int tpm_continue_selftest(struct tpm_chip *chip) | |||
631 | struct tpm_cmd_t cmd; | 636 | struct tpm_cmd_t cmd; |
632 | 637 | ||
633 | cmd.header.in = continue_selftest_header; | 638 | cmd.header.in = continue_selftest_header; |
634 | rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, | 639 | rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, |
635 | "continue selftest"); | 640 | "continue selftest"); |
636 | return rc; | 641 | return rc; |
637 | } | 642 | } |
638 | 643 | ||
639 | /* | ||
640 | * tpm_chip_find_get - return tpm_chip for given chip number | ||
641 | */ | ||
642 | static struct tpm_chip *tpm_chip_find_get(int chip_num) | ||
643 | { | ||
644 | struct tpm_chip *pos, *chip = NULL; | ||
645 | |||
646 | rcu_read_lock(); | ||
647 | list_for_each_entry_rcu(pos, &tpm_chip_list, list) { | ||
648 | if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) | ||
649 | continue; | ||
650 | |||
651 | if (try_module_get(pos->dev->driver->owner)) { | ||
652 | chip = pos; | ||
653 | break; | ||
654 | } | ||
655 | } | ||
656 | rcu_read_unlock(); | ||
657 | return chip; | ||
658 | } | ||
659 | |||
660 | #define TPM_ORDINAL_PCRREAD cpu_to_be32(21) | 644 | #define TPM_ORDINAL_PCRREAD cpu_to_be32(21) |
661 | #define READ_PCR_RESULT_SIZE 30 | 645 | #define READ_PCR_RESULT_SIZE 30 |
662 | static struct tpm_input_header pcrread_header = { | 646 | static struct tpm_input_header pcrread_header = { |
@@ -672,8 +656,8 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | |||
672 | 656 | ||
673 | cmd.header.in = pcrread_header; | 657 | cmd.header.in = pcrread_header; |
674 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); | 658 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); |
675 | rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, | 659 | rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, |
676 | "attempting to read a pcr value"); | 660 | "attempting to read a pcr value"); |
677 | 661 | ||
678 | if (rc == 0) | 662 | if (rc == 0) |
679 | memcpy(res_buf, cmd.params.pcrread_out.pcr_result, | 663 | memcpy(res_buf, cmd.params.pcrread_out.pcr_result, |
@@ -700,7 +684,10 @@ int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) | |||
700 | chip = tpm_chip_find_get(chip_num); | 684 | chip = tpm_chip_find_get(chip_num); |
701 | if (chip == NULL) | 685 | if (chip == NULL) |
702 | return -ENODEV; | 686 | return -ENODEV; |
703 | rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf); | 687 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
688 | rc = tpm2_pcr_read(chip, pcr_idx, res_buf); | ||
689 | else | ||
690 | rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf); | ||
704 | tpm_chip_put(chip); | 691 | tpm_chip_put(chip); |
705 | return rc; | 692 | return rc; |
706 | } | 693 | } |
@@ -734,11 +721,17 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | |||
734 | if (chip == NULL) | 721 | if (chip == NULL) |
735 | return -ENODEV; | 722 | return -ENODEV; |
736 | 723 | ||
724 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | ||
725 | rc = tpm2_pcr_extend(chip, pcr_idx, hash); | ||
726 | tpm_chip_put(chip); | ||
727 | return rc; | ||
728 | } | ||
729 | |||
737 | cmd.header.in = pcrextend_header; | 730 | cmd.header.in = pcrextend_header; |
738 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); | 731 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); |
739 | memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); | 732 | memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); |
740 | rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, | 733 | rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, |
741 | "attempting extend a PCR value"); | 734 | "attempting extend a PCR value"); |
742 | 735 | ||
743 | tpm_chip_put(chip); | 736 | tpm_chip_put(chip); |
744 | return rc; | 737 | return rc; |
@@ -781,7 +774,7 @@ int tpm_do_selftest(struct tpm_chip *chip) | |||
781 | * around 300ms while the self test is ongoing, keep trying | 774 | * around 300ms while the self test is ongoing, keep trying |
782 | * until the self test duration expires. */ | 775 | * until the self test duration expires. */ |
783 | if (rc == -ETIME) { | 776 | if (rc == -ETIME) { |
784 | dev_info(chip->dev, HW_ERR "TPM command timed out during continue self test"); | 777 | dev_info(chip->pdev, HW_ERR "TPM command timed out during continue self test"); |
785 | msleep(delay_msec); | 778 | msleep(delay_msec); |
786 | continue; | 779 | continue; |
787 | } | 780 | } |
@@ -791,7 +784,7 @@ int tpm_do_selftest(struct tpm_chip *chip) | |||
791 | 784 | ||
792 | rc = be32_to_cpu(cmd.header.out.return_code); | 785 | rc = be32_to_cpu(cmd.header.out.return_code); |
793 | if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { | 786 | if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { |
794 | dev_info(chip->dev, | 787 | dev_info(chip->pdev, |
795 | "TPM is disabled/deactivated (0x%X)\n", rc); | 788 | "TPM is disabled/deactivated (0x%X)\n", rc); |
796 | /* TPM is disabled and/or deactivated; driver can | 789 | /* TPM is disabled and/or deactivated; driver can |
797 | * proceed and TPM does handle commands for | 790 | * proceed and TPM does handle commands for |
@@ -817,7 +810,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen) | |||
817 | if (chip == NULL) | 810 | if (chip == NULL) |
818 | return -ENODEV; | 811 | return -ENODEV; |
819 | 812 | ||
820 | rc = transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd"); | 813 | rc = tpm_transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd"); |
821 | 814 | ||
822 | tpm_chip_put(chip); | 815 | tpm_chip_put(chip); |
823 | return rc; | 816 | return rc; |
@@ -884,30 +877,6 @@ again: | |||
884 | } | 877 | } |
885 | EXPORT_SYMBOL_GPL(wait_for_tpm_stat); | 878 | EXPORT_SYMBOL_GPL(wait_for_tpm_stat); |
886 | 879 | ||
887 | void tpm_remove_hardware(struct device *dev) | ||
888 | { | ||
889 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
890 | |||
891 | if (chip == NULL) { | ||
892 | dev_err(dev, "No device data found\n"); | ||
893 | return; | ||
894 | } | ||
895 | |||
896 | spin_lock(&driver_lock); | ||
897 | list_del_rcu(&chip->list); | ||
898 | spin_unlock(&driver_lock); | ||
899 | synchronize_rcu(); | ||
900 | |||
901 | tpm_dev_del_device(chip); | ||
902 | tpm_sysfs_del_device(chip); | ||
903 | tpm_remove_ppi(&dev->kobj); | ||
904 | tpm_bios_log_teardown(chip->bios_dir); | ||
905 | |||
906 | /* write it this way to be explicit (chip->dev == dev) */ | ||
907 | put_device(chip->dev); | ||
908 | } | ||
909 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); | ||
910 | |||
911 | #define TPM_ORD_SAVESTATE cpu_to_be32(152) | 880 | #define TPM_ORD_SAVESTATE cpu_to_be32(152) |
912 | #define SAVESTATE_RESULT_SIZE 10 | 881 | #define SAVESTATE_RESULT_SIZE 10 |
913 | 882 | ||
@@ -932,20 +901,23 @@ int tpm_pm_suspend(struct device *dev) | |||
932 | if (chip == NULL) | 901 | if (chip == NULL) |
933 | return -ENODEV; | 902 | return -ENODEV; |
934 | 903 | ||
904 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | ||
905 | return tpm2_shutdown(chip, TPM2_SU_CLEAR); | ||
906 | |||
935 | /* for buggy tpm, flush pcrs with extend to selected dummy */ | 907 | /* for buggy tpm, flush pcrs with extend to selected dummy */ |
936 | if (tpm_suspend_pcr) { | 908 | if (tpm_suspend_pcr) { |
937 | cmd.header.in = pcrextend_header; | 909 | cmd.header.in = pcrextend_header; |
938 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); | 910 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); |
939 | memcpy(cmd.params.pcrextend_in.hash, dummy_hash, | 911 | memcpy(cmd.params.pcrextend_in.hash, dummy_hash, |
940 | TPM_DIGEST_SIZE); | 912 | TPM_DIGEST_SIZE); |
941 | rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, | 913 | rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, |
942 | "extending dummy pcr before suspend"); | 914 | "extending dummy pcr before suspend"); |
943 | } | 915 | } |
944 | 916 | ||
945 | /* now do the actual savestate */ | 917 | /* now do the actual savestate */ |
946 | for (try = 0; try < TPM_RETRY; try++) { | 918 | for (try = 0; try < TPM_RETRY; try++) { |
947 | cmd.header.in = savestate_header; | 919 | cmd.header.in = savestate_header; |
948 | rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL); | 920 | rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL); |
949 | 921 | ||
950 | /* | 922 | /* |
951 | * If the TPM indicates that it is too busy to respond to | 923 | * If the TPM indicates that it is too busy to respond to |
@@ -963,10 +935,10 @@ int tpm_pm_suspend(struct device *dev) | |||
963 | } | 935 | } |
964 | 936 | ||
965 | if (rc) | 937 | if (rc) |
966 | dev_err(chip->dev, | 938 | dev_err(chip->pdev, |
967 | "Error (%d) sending savestate before suspend\n", rc); | 939 | "Error (%d) sending savestate before suspend\n", rc); |
968 | else if (try > 0) | 940 | else if (try > 0) |
969 | dev_warn(chip->dev, "TPM savestate took %dms\n", | 941 | dev_warn(chip->pdev, "TPM savestate took %dms\n", |
970 | try * TPM_TIMEOUT_RETRY); | 942 | try * TPM_TIMEOUT_RETRY); |
971 | 943 | ||
972 | return rc; | 944 | return rc; |
@@ -1018,11 +990,17 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) | |||
1018 | if (chip == NULL) | 990 | if (chip == NULL) |
1019 | return -ENODEV; | 991 | return -ENODEV; |
1020 | 992 | ||
993 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | ||
994 | err = tpm2_get_random(chip, out, max); | ||
995 | tpm_chip_put(chip); | ||
996 | return err; | ||
997 | } | ||
998 | |||
1021 | do { | 999 | do { |
1022 | tpm_cmd.header.in = tpm_getrandom_header; | 1000 | tpm_cmd.header.in = tpm_getrandom_header; |
1023 | tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); | 1001 | tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); |
1024 | 1002 | ||
1025 | err = transmit_cmd(chip, &tpm_cmd, | 1003 | err = tpm_transmit_cmd(chip, &tpm_cmd, |
1026 | TPM_GETRANDOM_RESULT_SIZE + num_bytes, | 1004 | TPM_GETRANDOM_RESULT_SIZE + num_bytes, |
1027 | "attempting get random"); | 1005 | "attempting get random"); |
1028 | if (err) | 1006 | if (err) |
@@ -1041,103 +1019,34 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) | |||
1041 | } | 1019 | } |
1042 | EXPORT_SYMBOL_GPL(tpm_get_random); | 1020 | EXPORT_SYMBOL_GPL(tpm_get_random); |
1043 | 1021 | ||
1044 | /* In case vendor provided release function, call it too.*/ | 1022 | static int __init tpm_init(void) |
1045 | |||
1046 | void tpm_dev_vendor_release(struct tpm_chip *chip) | ||
1047 | { | 1023 | { |
1048 | if (!chip) | 1024 | int rc; |
1049 | return; | ||
1050 | |||
1051 | clear_bit(chip->dev_num, dev_mask); | ||
1052 | } | ||
1053 | EXPORT_SYMBOL_GPL(tpm_dev_vendor_release); | ||
1054 | |||
1055 | |||
1056 | /* | ||
1057 | * Once all references to platform device are down to 0, | ||
1058 | * release all allocated structures. | ||
1059 | */ | ||
1060 | static void tpm_dev_release(struct device *dev) | ||
1061 | { | ||
1062 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
1063 | 1025 | ||
1064 | if (!chip) | 1026 | tpm_class = class_create(THIS_MODULE, "tpm"); |
1065 | return; | 1027 | if (IS_ERR(tpm_class)) { |
1028 | pr_err("couldn't create tpm class\n"); | ||
1029 | return PTR_ERR(tpm_class); | ||
1030 | } | ||
1066 | 1031 | ||
1067 | tpm_dev_vendor_release(chip); | 1032 | rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES, "tpm"); |
1033 | if (rc < 0) { | ||
1034 | pr_err("tpm: failed to allocate char dev region\n"); | ||
1035 | class_destroy(tpm_class); | ||
1036 | return rc; | ||
1037 | } | ||
1068 | 1038 | ||
1069 | chip->release(dev); | 1039 | return 0; |
1070 | kfree(chip); | ||
1071 | } | 1040 | } |
1072 | 1041 | ||
1073 | /* | 1042 | static void __exit tpm_exit(void) |
1074 | * Called from tpm_<specific>.c probe function only for devices | ||
1075 | * the driver has determined it should claim. Prior to calling | ||
1076 | * this function the specific probe function has called pci_enable_device | ||
1077 | * upon errant exit from this function specific probe function should call | ||
1078 | * pci_disable_device | ||
1079 | */ | ||
1080 | struct tpm_chip *tpm_register_hardware(struct device *dev, | ||
1081 | const struct tpm_class_ops *ops) | ||
1082 | { | 1043 | { |
1083 | struct tpm_chip *chip; | 1044 | class_destroy(tpm_class); |
1084 | 1045 | unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES); | |
1085 | /* Driver specific per-device data */ | ||
1086 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
1087 | |||
1088 | if (chip == NULL) | ||
1089 | return NULL; | ||
1090 | |||
1091 | mutex_init(&chip->tpm_mutex); | ||
1092 | INIT_LIST_HEAD(&chip->list); | ||
1093 | |||
1094 | chip->ops = ops; | ||
1095 | chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); | ||
1096 | |||
1097 | if (chip->dev_num >= TPM_NUM_DEVICES) { | ||
1098 | dev_err(dev, "No available tpm device numbers\n"); | ||
1099 | goto out_free; | ||
1100 | } | ||
1101 | |||
1102 | set_bit(chip->dev_num, dev_mask); | ||
1103 | |||
1104 | scnprintf(chip->devname, sizeof(chip->devname), "%s%d", "tpm", | ||
1105 | chip->dev_num); | ||
1106 | |||
1107 | chip->dev = get_device(dev); | ||
1108 | chip->release = dev->release; | ||
1109 | dev->release = tpm_dev_release; | ||
1110 | dev_set_drvdata(dev, chip); | ||
1111 | |||
1112 | if (tpm_dev_add_device(chip)) | ||
1113 | goto put_device; | ||
1114 | |||
1115 | if (tpm_sysfs_add_device(chip)) | ||
1116 | goto del_misc; | ||
1117 | |||
1118 | if (tpm_add_ppi(&dev->kobj)) | ||
1119 | goto del_sysfs; | ||
1120 | |||
1121 | chip->bios_dir = tpm_bios_log_setup(chip->devname); | ||
1122 | |||
1123 | /* Make chip available */ | ||
1124 | spin_lock(&driver_lock); | ||
1125 | list_add_rcu(&chip->list, &tpm_chip_list); | ||
1126 | spin_unlock(&driver_lock); | ||
1127 | |||
1128 | return chip; | ||
1129 | |||
1130 | del_sysfs: | ||
1131 | tpm_sysfs_del_device(chip); | ||
1132 | del_misc: | ||
1133 | tpm_dev_del_device(chip); | ||
1134 | put_device: | ||
1135 | put_device(chip->dev); | ||
1136 | out_free: | ||
1137 | kfree(chip); | ||
1138 | return NULL; | ||
1139 | } | 1046 | } |
1140 | EXPORT_SYMBOL_GPL(tpm_register_hardware); | 1047 | |
1048 | subsys_initcall(tpm_init); | ||
1049 | module_exit(tpm_exit); | ||
1141 | 1050 | ||
1142 | MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); | 1051 | MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); |
1143 | MODULE_DESCRIPTION("TPM Driver"); | 1052 | MODULE_DESCRIPTION("TPM Driver"); |
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 01730a27ae07..ee66fd4673f3 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c | |||
@@ -20,25 +20,6 @@ | |||
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include "tpm.h" | 21 | #include "tpm.h" |
22 | 22 | ||
23 | /* XXX for now this helper is duplicated in tpm-interface.c */ | ||
24 | static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, | ||
25 | int len, const char *desc) | ||
26 | { | ||
27 | int err; | ||
28 | |||
29 | len = tpm_transmit(chip, (u8 *) cmd, len); | ||
30 | if (len < 0) | ||
31 | return len; | ||
32 | else if (len < TPM_HEADER_SIZE) | ||
33 | return -EFAULT; | ||
34 | |||
35 | err = be32_to_cpu(cmd->header.out.return_code); | ||
36 | if (err != 0 && desc) | ||
37 | dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); | ||
38 | |||
39 | return err; | ||
40 | } | ||
41 | |||
42 | #define READ_PUBEK_RESULT_SIZE 314 | 23 | #define READ_PUBEK_RESULT_SIZE 314 |
43 | #define TPM_ORD_READPUBEK cpu_to_be32(124) | 24 | #define TPM_ORD_READPUBEK cpu_to_be32(124) |
44 | static struct tpm_input_header tpm_readpubek_header = { | 25 | static struct tpm_input_header tpm_readpubek_header = { |
@@ -58,8 +39,8 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | |||
58 | struct tpm_chip *chip = dev_get_drvdata(dev); | 39 | struct tpm_chip *chip = dev_get_drvdata(dev); |
59 | 40 | ||
60 | tpm_cmd.header.in = tpm_readpubek_header; | 41 | tpm_cmd.header.in = tpm_readpubek_header; |
61 | err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, | 42 | err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, |
62 | "attempting to read the PUBEK"); | 43 | "attempting to read the PUBEK"); |
63 | if (err) | 44 | if (err) |
64 | goto out; | 45 | goto out; |
65 | 46 | ||
@@ -303,16 +284,16 @@ static const struct attribute_group tpm_dev_group = { | |||
303 | int tpm_sysfs_add_device(struct tpm_chip *chip) | 284 | int tpm_sysfs_add_device(struct tpm_chip *chip) |
304 | { | 285 | { |
305 | int err; | 286 | int err; |
306 | err = sysfs_create_group(&chip->dev->kobj, | 287 | err = sysfs_create_group(&chip->pdev->kobj, |
307 | &tpm_dev_group); | 288 | &tpm_dev_group); |
308 | 289 | ||
309 | if (err) | 290 | if (err) |
310 | dev_err(chip->dev, | 291 | dev_err(chip->pdev, |
311 | "failed to create sysfs attributes, %d\n", err); | 292 | "failed to create sysfs attributes, %d\n", err); |
312 | return err; | 293 | return err; |
313 | } | 294 | } |
314 | 295 | ||
315 | void tpm_sysfs_del_device(struct tpm_chip *chip) | 296 | void tpm_sysfs_del_device(struct tpm_chip *chip) |
316 | { | 297 | { |
317 | sysfs_remove_group(&chip->dev->kobj, &tpm_dev_group); | 298 | sysfs_remove_group(&chip->pdev->kobj, &tpm_dev_group); |
318 | } | 299 | } |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index e4d0888d2eab..7b0727c5e803 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -10,23 +10,24 @@ | |||
10 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | 10 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> |
11 | * | 11 | * |
12 | * Device driver for TCG/TCPA TPM (trusted platform module). | 12 | * Device driver for TCG/TCPA TPM (trusted platform module). |
13 | * Specifications at www.trustedcomputinggroup.org | 13 | * Specifications at www.trustedcomputinggroup.org |
14 | * | 14 | * |
15 | * This program is free software; you can redistribute it and/or | 15 | * This program is free software; you can redistribute it and/or |
16 | * modify it under the terms of the GNU General Public License as | 16 | * modify it under the terms of the GNU General Public License as |
17 | * published by the Free Software Foundation, version 2 of the | 17 | * published by the Free Software Foundation, version 2 of the |
18 | * License. | 18 | * License. |
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
24 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
25 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
26 | #include <linux/miscdevice.h> | ||
27 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
28 | #include <linux/io.h> | 27 | #include <linux/io.h> |
29 | #include <linux/tpm.h> | 28 | #include <linux/tpm.h> |
29 | #include <linux/acpi.h> | ||
30 | #include <linux/cdev.h> | ||
30 | 31 | ||
31 | enum tpm_const { | 32 | enum tpm_const { |
32 | TPM_MINOR = 224, /* officially assigned */ | 33 | TPM_MINOR = 224, /* officially assigned */ |
@@ -61,6 +62,59 @@ enum tpm_duration { | |||
61 | #define TPM_ERR_INVALID_POSTINIT 38 | 62 | #define TPM_ERR_INVALID_POSTINIT 38 |
62 | 63 | ||
63 | #define TPM_HEADER_SIZE 10 | 64 | #define TPM_HEADER_SIZE 10 |
65 | |||
66 | enum tpm2_const { | ||
67 | TPM2_PLATFORM_PCR = 24, | ||
68 | TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8), | ||
69 | TPM2_TIMEOUT_A = 750, | ||
70 | TPM2_TIMEOUT_B = 2000, | ||
71 | TPM2_TIMEOUT_C = 200, | ||
72 | TPM2_TIMEOUT_D = 30, | ||
73 | TPM2_DURATION_SHORT = 20, | ||
74 | TPM2_DURATION_MEDIUM = 750, | ||
75 | TPM2_DURATION_LONG = 2000, | ||
76 | }; | ||
77 | |||
78 | enum tpm2_structures { | ||
79 | TPM2_ST_NO_SESSIONS = 0x8001, | ||
80 | TPM2_ST_SESSIONS = 0x8002, | ||
81 | }; | ||
82 | |||
83 | enum tpm2_return_codes { | ||
84 | TPM2_RC_INITIALIZE = 0x0100, | ||
85 | TPM2_RC_TESTING = 0x090A, | ||
86 | TPM2_RC_DISABLED = 0x0120, | ||
87 | }; | ||
88 | |||
89 | enum tpm2_algorithms { | ||
90 | TPM2_ALG_SHA1 = 0x0004, | ||
91 | }; | ||
92 | |||
93 | enum tpm2_command_codes { | ||
94 | TPM2_CC_FIRST = 0x011F, | ||
95 | TPM2_CC_SELF_TEST = 0x0143, | ||
96 | TPM2_CC_STARTUP = 0x0144, | ||
97 | TPM2_CC_SHUTDOWN = 0x0145, | ||
98 | TPM2_CC_GET_CAPABILITY = 0x017A, | ||
99 | TPM2_CC_GET_RANDOM = 0x017B, | ||
100 | TPM2_CC_PCR_READ = 0x017E, | ||
101 | TPM2_CC_PCR_EXTEND = 0x0182, | ||
102 | TPM2_CC_LAST = 0x018F, | ||
103 | }; | ||
104 | |||
105 | enum tpm2_permanent_handles { | ||
106 | TPM2_RS_PW = 0x40000009, | ||
107 | }; | ||
108 | |||
109 | enum tpm2_capabilities { | ||
110 | TPM2_CAP_TPM_PROPERTIES = 6, | ||
111 | }; | ||
112 | |||
113 | enum tpm2_startup_types { | ||
114 | TPM2_SU_CLEAR = 0x0000, | ||
115 | TPM2_SU_STATE = 0x0001, | ||
116 | }; | ||
117 | |||
64 | struct tpm_chip; | 118 | struct tpm_chip; |
65 | 119 | ||
66 | struct tpm_vendor_specific { | 120 | struct tpm_vendor_specific { |
@@ -73,7 +127,6 @@ struct tpm_vendor_specific { | |||
73 | int region_size; | 127 | int region_size; |
74 | int have_region; | 128 | int have_region; |
75 | 129 | ||
76 | struct miscdevice miscdev; | ||
77 | struct list_head list; | 130 | struct list_head list; |
78 | int locality; | 131 | int locality; |
79 | unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ | 132 | unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ |
@@ -88,15 +141,27 @@ struct tpm_vendor_specific { | |||
88 | u16 manufacturer_id; | 141 | u16 manufacturer_id; |
89 | }; | 142 | }; |
90 | 143 | ||
91 | #define TPM_VPRIV(c) (c)->vendor.priv | 144 | #define TPM_VPRIV(c) ((c)->vendor.priv) |
92 | 145 | ||
93 | #define TPM_VID_INTEL 0x8086 | 146 | #define TPM_VID_INTEL 0x8086 |
94 | #define TPM_VID_WINBOND 0x1050 | 147 | #define TPM_VID_WINBOND 0x1050 |
95 | #define TPM_VID_STM 0x104A | 148 | #define TPM_VID_STM 0x104A |
96 | 149 | ||
150 | #define TPM_PPI_VERSION_LEN 3 | ||
151 | |||
152 | enum tpm_chip_flags { | ||
153 | TPM_CHIP_FLAG_REGISTERED = BIT(0), | ||
154 | TPM_CHIP_FLAG_PPI = BIT(1), | ||
155 | TPM_CHIP_FLAG_TPM2 = BIT(2), | ||
156 | }; | ||
157 | |||
97 | struct tpm_chip { | 158 | struct tpm_chip { |
98 | struct device *dev; /* Device stuff */ | 159 | struct device *pdev; /* Device stuff */ |
160 | struct device dev; | ||
161 | struct cdev cdev; | ||
162 | |||
99 | const struct tpm_class_ops *ops; | 163 | const struct tpm_class_ops *ops; |
164 | unsigned int flags; | ||
100 | 165 | ||
101 | int dev_num; /* /dev/tpm# */ | 166 | int dev_num; /* /dev/tpm# */ |
102 | char devname[7]; | 167 | char devname[7]; |
@@ -109,15 +174,19 @@ struct tpm_chip { | |||
109 | 174 | ||
110 | struct dentry **bios_dir; | 175 | struct dentry **bios_dir; |
111 | 176 | ||
177 | #ifdef CONFIG_ACPI | ||
178 | acpi_handle acpi_dev_handle; | ||
179 | char ppi_version[TPM_PPI_VERSION_LEN + 1]; | ||
180 | #endif /* CONFIG_ACPI */ | ||
181 | |||
112 | struct list_head list; | 182 | struct list_head list; |
113 | void (*release) (struct device *); | ||
114 | }; | 183 | }; |
115 | 184 | ||
116 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) | 185 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) |
117 | 186 | ||
118 | static inline void tpm_chip_put(struct tpm_chip *chip) | 187 | static inline void tpm_chip_put(struct tpm_chip *chip) |
119 | { | 188 | { |
120 | module_put(chip->dev->driver->owner); | 189 | module_put(chip->pdev->driver->owner); |
121 | } | 190 | } |
122 | 191 | ||
123 | static inline int tpm_read_index(int base, int index) | 192 | static inline int tpm_read_index(int base, int index) |
@@ -313,40 +382,57 @@ struct tpm_cmd_t { | |||
313 | tpm_cmd_params params; | 382 | tpm_cmd_params params; |
314 | } __packed; | 383 | } __packed; |
315 | 384 | ||
316 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); | 385 | extern struct class *tpm_class; |
386 | extern dev_t tpm_devt; | ||
387 | extern const struct file_operations tpm_fops; | ||
317 | 388 | ||
389 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); | ||
318 | ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | 390 | ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, |
319 | size_t bufsiz); | 391 | size_t bufsiz); |
392 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, int len, | ||
393 | const char *desc); | ||
320 | extern int tpm_get_timeouts(struct tpm_chip *); | 394 | extern int tpm_get_timeouts(struct tpm_chip *); |
321 | extern void tpm_gen_interrupt(struct tpm_chip *); | 395 | extern void tpm_gen_interrupt(struct tpm_chip *); |
322 | extern int tpm_do_selftest(struct tpm_chip *); | 396 | extern int tpm_do_selftest(struct tpm_chip *); |
323 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); | 397 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); |
324 | extern struct tpm_chip* tpm_register_hardware(struct device *, | ||
325 | const struct tpm_class_ops *ops); | ||
326 | extern void tpm_dev_vendor_release(struct tpm_chip *); | ||
327 | extern void tpm_remove_hardware(struct device *); | ||
328 | extern int tpm_pm_suspend(struct device *); | 398 | extern int tpm_pm_suspend(struct device *); |
329 | extern int tpm_pm_resume(struct device *); | 399 | extern int tpm_pm_resume(struct device *); |
330 | extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, | 400 | extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, |
331 | wait_queue_head_t *, bool); | 401 | wait_queue_head_t *, bool); |
332 | 402 | ||
333 | int tpm_dev_add_device(struct tpm_chip *chip); | 403 | struct tpm_chip *tpm_chip_find_get(int chip_num); |
334 | void tpm_dev_del_device(struct tpm_chip *chip); | 404 | extern struct tpm_chip *tpmm_chip_alloc(struct device *dev, |
405 | const struct tpm_class_ops *ops); | ||
406 | extern int tpm_chip_register(struct tpm_chip *chip); | ||
407 | extern void tpm_chip_unregister(struct tpm_chip *chip); | ||
408 | |||
335 | int tpm_sysfs_add_device(struct tpm_chip *chip); | 409 | int tpm_sysfs_add_device(struct tpm_chip *chip); |
336 | void tpm_sysfs_del_device(struct tpm_chip *chip); | 410 | void tpm_sysfs_del_device(struct tpm_chip *chip); |
337 | 411 | ||
338 | int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); | 412 | int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); |
339 | 413 | ||
340 | #ifdef CONFIG_ACPI | 414 | #ifdef CONFIG_ACPI |
341 | extern int tpm_add_ppi(struct kobject *); | 415 | extern int tpm_add_ppi(struct tpm_chip *chip); |
342 | extern void tpm_remove_ppi(struct kobject *); | 416 | extern void tpm_remove_ppi(struct tpm_chip *chip); |
343 | #else | 417 | #else |
344 | static inline int tpm_add_ppi(struct kobject *parent) | 418 | static inline int tpm_add_ppi(struct tpm_chip *chip) |
345 | { | 419 | { |
346 | return 0; | 420 | return 0; |
347 | } | 421 | } |
348 | 422 | ||
349 | static inline void tpm_remove_ppi(struct kobject *parent) | 423 | static inline void tpm_remove_ppi(struct tpm_chip *chip) |
350 | { | 424 | { |
351 | } | 425 | } |
352 | #endif | 426 | #endif |
427 | |||
428 | 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); | ||
430 | int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max); | ||
431 | ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, | ||
432 | u32 *value, const char *desc); | ||
433 | |||
434 | extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type); | ||
435 | extern int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); | ||
436 | extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); | ||
437 | extern int tpm2_do_selftest(struct tpm_chip *chip); | ||
438 | extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet); | ||
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c new file mode 100644 index 000000000000..1abe6502219f --- /dev/null +++ b/drivers/char/tpm/tpm2-cmd.c | |||
@@ -0,0 +1,617 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Intel Corporation | ||
3 | * | ||
4 | * Authors: | ||
5 | * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | ||
6 | * | ||
7 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
8 | * | ||
9 | * This file contains TPM2 protocol implementations of the commands | ||
10 | * used by the kernel internally. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; version 2 | ||
15 | * of the License. | ||
16 | */ | ||
17 | |||
18 | #include "tpm.h" | ||
19 | |||
20 | struct tpm2_startup_in { | ||
21 | __be16 startup_type; | ||
22 | } __packed; | ||
23 | |||
24 | struct tpm2_self_test_in { | ||
25 | u8 full_test; | ||
26 | } __packed; | ||
27 | |||
28 | struct tpm2_pcr_read_in { | ||
29 | __be32 pcr_selects_cnt; | ||
30 | __be16 hash_alg; | ||
31 | u8 pcr_select_size; | ||
32 | u8 pcr_select[TPM2_PCR_SELECT_MIN]; | ||
33 | } __packed; | ||
34 | |||
35 | struct tpm2_pcr_read_out { | ||
36 | __be32 update_cnt; | ||
37 | __be32 pcr_selects_cnt; | ||
38 | __be16 hash_alg; | ||
39 | u8 pcr_select_size; | ||
40 | u8 pcr_select[TPM2_PCR_SELECT_MIN]; | ||
41 | __be32 digests_cnt; | ||
42 | __be16 digest_size; | ||
43 | u8 digest[TPM_DIGEST_SIZE]; | ||
44 | } __packed; | ||
45 | |||
46 | struct tpm2_null_auth_area { | ||
47 | __be32 handle; | ||
48 | __be16 nonce_size; | ||
49 | u8 attributes; | ||
50 | __be16 auth_size; | ||
51 | } __packed; | ||
52 | |||
53 | struct tpm2_pcr_extend_in { | ||
54 | __be32 pcr_idx; | ||
55 | __be32 auth_area_size; | ||
56 | struct tpm2_null_auth_area auth_area; | ||
57 | __be32 digest_cnt; | ||
58 | __be16 hash_alg; | ||
59 | u8 digest[TPM_DIGEST_SIZE]; | ||
60 | } __packed; | ||
61 | |||
62 | struct tpm2_get_tpm_pt_in { | ||
63 | __be32 cap_id; | ||
64 | __be32 property_id; | ||
65 | __be32 property_cnt; | ||
66 | } __packed; | ||
67 | |||
68 | struct tpm2_get_tpm_pt_out { | ||
69 | u8 more_data; | ||
70 | __be32 subcap_id; | ||
71 | __be32 property_cnt; | ||
72 | __be32 property_id; | ||
73 | __be32 value; | ||
74 | } __packed; | ||
75 | |||
76 | struct tpm2_get_random_in { | ||
77 | __be16 size; | ||
78 | } __packed; | ||
79 | |||
80 | struct tpm2_get_random_out { | ||
81 | __be16 size; | ||
82 | u8 buffer[TPM_MAX_RNG_DATA]; | ||
83 | } __packed; | ||
84 | |||
85 | union tpm2_cmd_params { | ||
86 | struct tpm2_startup_in startup_in; | ||
87 | struct tpm2_self_test_in selftest_in; | ||
88 | struct tpm2_pcr_read_in pcrread_in; | ||
89 | struct tpm2_pcr_read_out pcrread_out; | ||
90 | struct tpm2_pcr_extend_in pcrextend_in; | ||
91 | struct tpm2_get_tpm_pt_in get_tpm_pt_in; | ||
92 | struct tpm2_get_tpm_pt_out get_tpm_pt_out; | ||
93 | struct tpm2_get_random_in getrandom_in; | ||
94 | struct tpm2_get_random_out getrandom_out; | ||
95 | }; | ||
96 | |||
97 | struct tpm2_cmd { | ||
98 | tpm_cmd_header header; | ||
99 | union tpm2_cmd_params params; | ||
100 | } __packed; | ||
101 | |||
102 | /* | ||
103 | * Array with one entry per ordinal defining the maximum amount | ||
104 | * of time the chip could take to return the result. The values | ||
105 | * of the SHORT, MEDIUM, and LONG durations are taken from the | ||
106 | * PC Client Profile (PTP) specification. | ||
107 | */ | ||
108 | static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { | ||
109 | TPM_UNDEFINED, /* 11F */ | ||
110 | TPM_UNDEFINED, /* 120 */ | ||
111 | TPM_LONG, /* 121 */ | ||
112 | TPM_UNDEFINED, /* 122 */ | ||
113 | TPM_UNDEFINED, /* 123 */ | ||
114 | TPM_UNDEFINED, /* 124 */ | ||
115 | TPM_UNDEFINED, /* 125 */ | ||
116 | TPM_UNDEFINED, /* 126 */ | ||
117 | TPM_UNDEFINED, /* 127 */ | ||
118 | TPM_UNDEFINED, /* 128 */ | ||
119 | TPM_LONG, /* 129 */ | ||
120 | TPM_UNDEFINED, /* 12a */ | ||
121 | TPM_UNDEFINED, /* 12b */ | ||
122 | TPM_UNDEFINED, /* 12c */ | ||
123 | TPM_UNDEFINED, /* 12d */ | ||
124 | TPM_UNDEFINED, /* 12e */ | ||
125 | TPM_UNDEFINED, /* 12f */ | ||
126 | TPM_UNDEFINED, /* 130 */ | ||
127 | TPM_UNDEFINED, /* 131 */ | ||
128 | TPM_UNDEFINED, /* 132 */ | ||
129 | TPM_UNDEFINED, /* 133 */ | ||
130 | TPM_UNDEFINED, /* 134 */ | ||
131 | TPM_UNDEFINED, /* 135 */ | ||
132 | TPM_UNDEFINED, /* 136 */ | ||
133 | TPM_UNDEFINED, /* 137 */ | ||
134 | TPM_UNDEFINED, /* 138 */ | ||
135 | TPM_UNDEFINED, /* 139 */ | ||
136 | TPM_UNDEFINED, /* 13a */ | ||
137 | TPM_UNDEFINED, /* 13b */ | ||
138 | TPM_UNDEFINED, /* 13c */ | ||
139 | TPM_UNDEFINED, /* 13d */ | ||
140 | TPM_MEDIUM, /* 13e */ | ||
141 | TPM_UNDEFINED, /* 13f */ | ||
142 | TPM_UNDEFINED, /* 140 */ | ||
143 | TPM_UNDEFINED, /* 141 */ | ||
144 | TPM_UNDEFINED, /* 142 */ | ||
145 | TPM_LONG, /* 143 */ | ||
146 | TPM_MEDIUM, /* 144 */ | ||
147 | TPM_UNDEFINED, /* 145 */ | ||
148 | TPM_UNDEFINED, /* 146 */ | ||
149 | TPM_UNDEFINED, /* 147 */ | ||
150 | TPM_UNDEFINED, /* 148 */ | ||
151 | TPM_UNDEFINED, /* 149 */ | ||
152 | TPM_UNDEFINED, /* 14a */ | ||
153 | TPM_UNDEFINED, /* 14b */ | ||
154 | TPM_UNDEFINED, /* 14c */ | ||
155 | TPM_UNDEFINED, /* 14d */ | ||
156 | TPM_LONG, /* 14e */ | ||
157 | TPM_UNDEFINED, /* 14f */ | ||
158 | TPM_UNDEFINED, /* 150 */ | ||
159 | TPM_UNDEFINED, /* 151 */ | ||
160 | TPM_UNDEFINED, /* 152 */ | ||
161 | TPM_UNDEFINED, /* 153 */ | ||
162 | TPM_UNDEFINED, /* 154 */ | ||
163 | TPM_UNDEFINED, /* 155 */ | ||
164 | TPM_UNDEFINED, /* 156 */ | ||
165 | TPM_UNDEFINED, /* 157 */ | ||
166 | TPM_UNDEFINED, /* 158 */ | ||
167 | TPM_UNDEFINED, /* 159 */ | ||
168 | TPM_UNDEFINED, /* 15a */ | ||
169 | TPM_UNDEFINED, /* 15b */ | ||
170 | TPM_MEDIUM, /* 15c */ | ||
171 | TPM_UNDEFINED, /* 15d */ | ||
172 | TPM_UNDEFINED, /* 15e */ | ||
173 | TPM_UNDEFINED, /* 15f */ | ||
174 | TPM_UNDEFINED, /* 160 */ | ||
175 | TPM_UNDEFINED, /* 161 */ | ||
176 | TPM_UNDEFINED, /* 162 */ | ||
177 | TPM_UNDEFINED, /* 163 */ | ||
178 | TPM_UNDEFINED, /* 164 */ | ||
179 | TPM_UNDEFINED, /* 165 */ | ||
180 | TPM_UNDEFINED, /* 166 */ | ||
181 | TPM_UNDEFINED, /* 167 */ | ||
182 | TPM_UNDEFINED, /* 168 */ | ||
183 | TPM_UNDEFINED, /* 169 */ | ||
184 | TPM_UNDEFINED, /* 16a */ | ||
185 | TPM_UNDEFINED, /* 16b */ | ||
186 | TPM_UNDEFINED, /* 16c */ | ||
187 | TPM_UNDEFINED, /* 16d */ | ||
188 | TPM_UNDEFINED, /* 16e */ | ||
189 | TPM_UNDEFINED, /* 16f */ | ||
190 | TPM_UNDEFINED, /* 170 */ | ||
191 | TPM_UNDEFINED, /* 171 */ | ||
192 | TPM_UNDEFINED, /* 172 */ | ||
193 | TPM_UNDEFINED, /* 173 */ | ||
194 | TPM_UNDEFINED, /* 174 */ | ||
195 | TPM_UNDEFINED, /* 175 */ | ||
196 | TPM_UNDEFINED, /* 176 */ | ||
197 | TPM_LONG, /* 177 */ | ||
198 | TPM_UNDEFINED, /* 178 */ | ||
199 | TPM_UNDEFINED, /* 179 */ | ||
200 | TPM_MEDIUM, /* 17a */ | ||
201 | TPM_LONG, /* 17b */ | ||
202 | TPM_UNDEFINED, /* 17c */ | ||
203 | TPM_UNDEFINED, /* 17d */ | ||
204 | TPM_UNDEFINED, /* 17e */ | ||
205 | TPM_UNDEFINED, /* 17f */ | ||
206 | TPM_UNDEFINED, /* 180 */ | ||
207 | TPM_UNDEFINED, /* 181 */ | ||
208 | TPM_MEDIUM, /* 182 */ | ||
209 | TPM_UNDEFINED, /* 183 */ | ||
210 | TPM_UNDEFINED, /* 184 */ | ||
211 | TPM_MEDIUM, /* 185 */ | ||
212 | TPM_MEDIUM, /* 186 */ | ||
213 | TPM_UNDEFINED, /* 187 */ | ||
214 | TPM_UNDEFINED, /* 188 */ | ||
215 | TPM_UNDEFINED, /* 189 */ | ||
216 | TPM_UNDEFINED, /* 18a */ | ||
217 | TPM_UNDEFINED, /* 18b */ | ||
218 | TPM_UNDEFINED, /* 18c */ | ||
219 | TPM_UNDEFINED, /* 18d */ | ||
220 | TPM_UNDEFINED, /* 18e */ | ||
221 | TPM_UNDEFINED /* 18f */ | ||
222 | }; | ||
223 | |||
224 | #define TPM2_PCR_READ_IN_SIZE \ | ||
225 | (sizeof(struct tpm_input_header) + \ | ||
226 | sizeof(struct tpm2_pcr_read_in)) | ||
227 | |||
228 | static const struct tpm_input_header tpm2_pcrread_header = { | ||
229 | .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), | ||
230 | .length = cpu_to_be32(TPM2_PCR_READ_IN_SIZE), | ||
231 | .ordinal = cpu_to_be32(TPM2_CC_PCR_READ) | ||
232 | }; | ||
233 | |||
234 | /** | ||
235 | * tpm2_pcr_read() - read a PCR value | ||
236 | * @chip: TPM chip to use. | ||
237 | * @pcr_idx: index of the PCR to read. | ||
238 | * @ref_buf: buffer to store the resulting hash, | ||
239 | * | ||
240 | * 0 is returned when the operation is successful. If a negative number is | ||
241 | * returned it remarks a POSIX error code. If a positive number is returned | ||
242 | * it remarks a TPM error. | ||
243 | */ | ||
244 | int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | ||
245 | { | ||
246 | int rc; | ||
247 | struct tpm2_cmd cmd; | ||
248 | u8 *buf; | ||
249 | |||
250 | if (pcr_idx >= TPM2_PLATFORM_PCR) | ||
251 | return -EINVAL; | ||
252 | |||
253 | cmd.header.in = tpm2_pcrread_header; | ||
254 | cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1); | ||
255 | cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1); | ||
256 | cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN; | ||
257 | |||
258 | memset(cmd.params.pcrread_in.pcr_select, 0, | ||
259 | sizeof(cmd.params.pcrread_in.pcr_select)); | ||
260 | cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); | ||
261 | |||
262 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | ||
263 | "attempting to read a pcr value"); | ||
264 | if (rc == 0) { | ||
265 | buf = cmd.params.pcrread_out.digest; | ||
266 | memcpy(res_buf, buf, TPM_DIGEST_SIZE); | ||
267 | } | ||
268 | |||
269 | return rc; | ||
270 | } | ||
271 | |||
272 | #define TPM2_GET_PCREXTEND_IN_SIZE \ | ||
273 | (sizeof(struct tpm_input_header) + \ | ||
274 | sizeof(struct tpm2_pcr_extend_in)) | ||
275 | |||
276 | static const struct tpm_input_header tpm2_pcrextend_header = { | ||
277 | .tag = cpu_to_be16(TPM2_ST_SESSIONS), | ||
278 | .length = cpu_to_be32(TPM2_GET_PCREXTEND_IN_SIZE), | ||
279 | .ordinal = cpu_to_be32(TPM2_CC_PCR_EXTEND) | ||
280 | }; | ||
281 | |||
282 | /** | ||
283 | * tpm2_pcr_extend() - extend a PCR value | ||
284 | * @chip: TPM chip to use. | ||
285 | * @pcr_idx: index of the PCR. | ||
286 | * @hash: hash value to use for the extend operation. | ||
287 | * | ||
288 | * 0 is returned when the operation is successful. If a negative number is | ||
289 | * returned it remarks a POSIX error code. If a positive number is returned | ||
290 | * it remarks a TPM error. | ||
291 | */ | ||
292 | int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) | ||
293 | { | ||
294 | struct tpm2_cmd cmd; | ||
295 | int rc; | ||
296 | |||
297 | cmd.header.in = tpm2_pcrextend_header; | ||
298 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); | ||
299 | cmd.params.pcrextend_in.auth_area_size = | ||
300 | cpu_to_be32(sizeof(struct tpm2_null_auth_area)); | ||
301 | cmd.params.pcrextend_in.auth_area.handle = | ||
302 | cpu_to_be32(TPM2_RS_PW); | ||
303 | cmd.params.pcrextend_in.auth_area.nonce_size = 0; | ||
304 | cmd.params.pcrextend_in.auth_area.attributes = 0; | ||
305 | cmd.params.pcrextend_in.auth_area.auth_size = 0; | ||
306 | cmd.params.pcrextend_in.digest_cnt = cpu_to_be32(1); | ||
307 | cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1); | ||
308 | memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE); | ||
309 | |||
310 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | ||
311 | "attempting extend a PCR value"); | ||
312 | |||
313 | return rc; | ||
314 | } | ||
315 | |||
316 | #define TPM2_GETRANDOM_IN_SIZE \ | ||
317 | (sizeof(struct tpm_input_header) + \ | ||
318 | sizeof(struct tpm2_get_random_in)) | ||
319 | |||
320 | static const struct tpm_input_header tpm2_getrandom_header = { | ||
321 | .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), | ||
322 | .length = cpu_to_be32(TPM2_GETRANDOM_IN_SIZE), | ||
323 | .ordinal = cpu_to_be32(TPM2_CC_GET_RANDOM) | ||
324 | }; | ||
325 | |||
326 | /** | ||
327 | * tpm2_get_random() - get random bytes from the TPM RNG | ||
328 | * @chip: TPM chip to use | ||
329 | * @out: destination buffer for the random bytes | ||
330 | * @max: the max number of bytes to write to @out | ||
331 | * | ||
332 | * 0 is returned when the operation is successful. If a negative number is | ||
333 | * returned it remarks a POSIX error code. If a positive number is returned | ||
334 | * it remarks a TPM error. | ||
335 | */ | ||
336 | int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max) | ||
337 | { | ||
338 | struct tpm2_cmd cmd; | ||
339 | u32 recd; | ||
340 | u32 num_bytes; | ||
341 | int err; | ||
342 | int total = 0; | ||
343 | int retries = 5; | ||
344 | u8 *dest = out; | ||
345 | |||
346 | num_bytes = min_t(u32, max, sizeof(cmd.params.getrandom_out.buffer)); | ||
347 | |||
348 | if (!out || !num_bytes || | ||
349 | max > sizeof(cmd.params.getrandom_out.buffer)) | ||
350 | return -EINVAL; | ||
351 | |||
352 | do { | ||
353 | cmd.header.in = tpm2_getrandom_header; | ||
354 | cmd.params.getrandom_in.size = cpu_to_be16(num_bytes); | ||
355 | |||
356 | err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | ||
357 | "attempting get random"); | ||
358 | if (err) | ||
359 | break; | ||
360 | |||
361 | recd = min_t(u32, be16_to_cpu(cmd.params.getrandom_out.size), | ||
362 | num_bytes); | ||
363 | memcpy(dest, cmd.params.getrandom_out.buffer, recd); | ||
364 | |||
365 | dest += recd; | ||
366 | total += recd; | ||
367 | num_bytes -= recd; | ||
368 | } while (retries-- && total < max); | ||
369 | |||
370 | return total ? total : -EIO; | ||
371 | } | ||
372 | |||
373 | #define TPM2_GET_TPM_PT_IN_SIZE \ | ||
374 | (sizeof(struct tpm_input_header) + \ | ||
375 | sizeof(struct tpm2_get_tpm_pt_in)) | ||
376 | |||
377 | static const struct tpm_input_header tpm2_get_tpm_pt_header = { | ||
378 | .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), | ||
379 | .length = cpu_to_be32(TPM2_GET_TPM_PT_IN_SIZE), | ||
380 | .ordinal = cpu_to_be32(TPM2_CC_GET_CAPABILITY) | ||
381 | }; | ||
382 | |||
383 | /** | ||
384 | * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property | ||
385 | * @chip: TPM chip to use. | ||
386 | * @property_id: property ID. | ||
387 | * @value: output variable. | ||
388 | * @desc: passed to tpm_transmit_cmd() | ||
389 | * | ||
390 | * 0 is returned when the operation is successful. If a negative number is | ||
391 | * returned it remarks a POSIX error code. If a positive number is returned | ||
392 | * it remarks a TPM error. | ||
393 | */ | ||
394 | ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, | ||
395 | const char *desc) | ||
396 | { | ||
397 | struct tpm2_cmd cmd; | ||
398 | int rc; | ||
399 | |||
400 | cmd.header.in = tpm2_get_tpm_pt_header; | ||
401 | cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES); | ||
402 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id); | ||
403 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); | ||
404 | |||
405 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc); | ||
406 | if (!rc) | ||
407 | *value = cmd.params.get_tpm_pt_out.value; | ||
408 | |||
409 | return rc; | ||
410 | } | ||
411 | |||
412 | #define TPM2_STARTUP_IN_SIZE \ | ||
413 | (sizeof(struct tpm_input_header) + \ | ||
414 | sizeof(struct tpm2_startup_in)) | ||
415 | |||
416 | static const struct tpm_input_header tpm2_startup_header = { | ||
417 | .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), | ||
418 | .length = cpu_to_be32(TPM2_STARTUP_IN_SIZE), | ||
419 | .ordinal = cpu_to_be32(TPM2_CC_STARTUP) | ||
420 | }; | ||
421 | |||
422 | /** | ||
423 | * tpm2_startup() - send startup command to the TPM chip | ||
424 | * @chip: TPM chip to use. | ||
425 | * @startup_type startup type. The value is either | ||
426 | * TPM_SU_CLEAR or TPM_SU_STATE. | ||
427 | * | ||
428 | * 0 is returned when the operation is successful. If a negative number is | ||
429 | * returned it remarks a POSIX error code. If a positive number is returned | ||
430 | * it remarks a TPM error. | ||
431 | */ | ||
432 | int tpm2_startup(struct tpm_chip *chip, u16 startup_type) | ||
433 | { | ||
434 | struct tpm2_cmd cmd; | ||
435 | |||
436 | cmd.header.in = tpm2_startup_header; | ||
437 | |||
438 | cmd.params.startup_in.startup_type = cpu_to_be16(startup_type); | ||
439 | return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | ||
440 | "attempting to start the TPM"); | ||
441 | } | ||
442 | EXPORT_SYMBOL_GPL(tpm2_startup); | ||
443 | |||
444 | #define TPM2_SHUTDOWN_IN_SIZE \ | ||
445 | (sizeof(struct tpm_input_header) + \ | ||
446 | sizeof(struct tpm2_startup_in)) | ||
447 | |||
448 | static const struct tpm_input_header tpm2_shutdown_header = { | ||
449 | .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), | ||
450 | .length = cpu_to_be32(TPM2_SHUTDOWN_IN_SIZE), | ||
451 | .ordinal = cpu_to_be32(TPM2_CC_SHUTDOWN) | ||
452 | }; | ||
453 | |||
454 | /** | ||
455 | * tpm2_shutdown() - send shutdown command to the TPM chip | ||
456 | * @chip: TPM chip to use. | ||
457 | * @shutdown_type shutdown type. The value is either | ||
458 | * TPM_SU_CLEAR or TPM_SU_STATE. | ||
459 | * | ||
460 | * 0 is returned when the operation is successful. If a negative number is | ||
461 | * returned it remarks a POSIX error code. If a positive number is returned | ||
462 | * it remarks a TPM error. | ||
463 | */ | ||
464 | int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) | ||
465 | { | ||
466 | struct tpm2_cmd cmd; | ||
467 | |||
468 | cmd.header.in = tpm2_shutdown_header; | ||
469 | |||
470 | cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); | ||
471 | return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | ||
472 | "stopping the TPM"); | ||
473 | } | ||
474 | EXPORT_SYMBOL_GPL(tpm2_shutdown); | ||
475 | |||
476 | /* | ||
477 | * tpm2_calc_ordinal_duration() - maximum duration for a command | ||
478 | * @chip: TPM chip to use. | ||
479 | * @ordinal: command code number. | ||
480 | * | ||
481 | * 0 is returned when the operation is successful. If a negative number is | ||
482 | * returned it remarks a POSIX error code. If a positive number is returned | ||
483 | * it remarks a TPM error. | ||
484 | */ | ||
485 | unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) | ||
486 | { | ||
487 | int index = TPM_UNDEFINED; | ||
488 | int duration = 0; | ||
489 | |||
490 | if (ordinal >= TPM2_CC_FIRST && ordinal <= TPM2_CC_LAST) | ||
491 | index = tpm2_ordinal_duration[ordinal - TPM2_CC_FIRST]; | ||
492 | |||
493 | if (index != TPM_UNDEFINED) | ||
494 | duration = chip->vendor.duration[index]; | ||
495 | |||
496 | if (duration <= 0) | ||
497 | duration = 2 * 60 * HZ; | ||
498 | |||
499 | return duration; | ||
500 | } | ||
501 | EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration); | ||
502 | |||
503 | #define TPM2_SELF_TEST_IN_SIZE \ | ||
504 | (sizeof(struct tpm_input_header) + \ | ||
505 | sizeof(struct tpm2_self_test_in)) | ||
506 | |||
507 | static const struct tpm_input_header tpm2_selftest_header = { | ||
508 | .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), | ||
509 | .length = cpu_to_be32(TPM2_SELF_TEST_IN_SIZE), | ||
510 | .ordinal = cpu_to_be32(TPM2_CC_SELF_TEST) | ||
511 | }; | ||
512 | |||
513 | /** | ||
514 | * tpm2_continue_selftest() - start a self test | ||
515 | * @chip: TPM chip to use | ||
516 | * @full: test all commands instead of testing only those that were not | ||
517 | * previously tested. | ||
518 | * | ||
519 | * 0 is returned when the operation is successful. If a negative number is | ||
520 | * returned it remarks a POSIX error code. If a positive number is returned | ||
521 | * it remarks a TPM error. | ||
522 | */ | ||
523 | static int tpm2_start_selftest(struct tpm_chip *chip, bool full) | ||
524 | { | ||
525 | int rc; | ||
526 | struct tpm2_cmd cmd; | ||
527 | |||
528 | cmd.header.in = tpm2_selftest_header; | ||
529 | cmd.params.selftest_in.full_test = full; | ||
530 | |||
531 | rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, | ||
532 | "continue selftest"); | ||
533 | |||
534 | /* At least some prototype chips seem to give RC_TESTING error | ||
535 | * immediately. This is a workaround for that. | ||
536 | */ | ||
537 | if (rc == TPM2_RC_TESTING) { | ||
538 | dev_warn(chip->pdev, "Got RC_TESTING, ignoring\n"); | ||
539 | rc = 0; | ||
540 | } | ||
541 | |||
542 | return rc; | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * tpm2_do_selftest() - run a full self test | ||
547 | * @chip: TPM chip to use | ||
548 | * | ||
549 | * During the self test TPM2 commands return with the error code RC_TESTING. | ||
550 | * Waiting is done by issuing PCR read until it executes successfully. | ||
551 | * | ||
552 | * 0 is returned when the operation is successful. If a negative number is | ||
553 | * returned it remarks a POSIX error code. If a positive number is returned | ||
554 | * it remarks a TPM error. | ||
555 | */ | ||
556 | int tpm2_do_selftest(struct tpm_chip *chip) | ||
557 | { | ||
558 | int rc; | ||
559 | unsigned int loops; | ||
560 | unsigned int delay_msec = 100; | ||
561 | unsigned long duration; | ||
562 | struct tpm2_cmd cmd; | ||
563 | int i; | ||
564 | |||
565 | duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST); | ||
566 | |||
567 | loops = jiffies_to_msecs(duration) / delay_msec; | ||
568 | |||
569 | rc = tpm2_start_selftest(chip, true); | ||
570 | if (rc) | ||
571 | return rc; | ||
572 | |||
573 | for (i = 0; i < loops; i++) { | ||
574 | /* Attempt to read a PCR value */ | ||
575 | cmd.header.in = tpm2_pcrread_header; | ||
576 | cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1); | ||
577 | cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1); | ||
578 | cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN; | ||
579 | cmd.params.pcrread_in.pcr_select[0] = 0x01; | ||
580 | cmd.params.pcrread_in.pcr_select[1] = 0x00; | ||
581 | cmd.params.pcrread_in.pcr_select[2] = 0x00; | ||
582 | |||
583 | rc = tpm_transmit_cmd(chip, (u8 *) &cmd, sizeof(cmd), NULL); | ||
584 | if (rc < 0) | ||
585 | break; | ||
586 | |||
587 | rc = be32_to_cpu(cmd.header.out.return_code); | ||
588 | if (rc != TPM2_RC_TESTING) | ||
589 | break; | ||
590 | |||
591 | msleep(delay_msec); | ||
592 | } | ||
593 | |||
594 | return rc; | ||
595 | } | ||
596 | EXPORT_SYMBOL_GPL(tpm2_do_selftest); | ||
597 | |||
598 | /** | ||
599 | * tpm2_gen_interrupt() - generate an interrupt | ||
600 | * @chip: TPM chip to use | ||
601 | * @quiet: surpress the error message | ||
602 | * | ||
603 | * 0 is returned when the operation is successful. If a negative number is | ||
604 | * returned it remarks a POSIX error code. If a positive number is returned | ||
605 | * it remarks a TPM error. | ||
606 | */ | ||
607 | int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet) | ||
608 | { | ||
609 | const char *desc = NULL; | ||
610 | u32 dummy; | ||
611 | |||
612 | if (!quiet) | ||
613 | desc = "attempting to generate an interrupt"; | ||
614 | |||
615 | return tpm2_get_tpm_pt(chip, TPM2_CAP_TPM_PROPERTIES, &dummy, desc); | ||
616 | } | ||
617 | EXPORT_SYMBOL_GPL(tpm2_gen_interrupt); | ||
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 435c8b9dd2f8..dfadad0916a1 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -49,7 +49,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
49 | for (i = 0; i < 6; i++) { | 49 | for (i = 0; i < 6; i++) { |
50 | status = ioread8(chip->vendor.iobase + 1); | 50 | status = ioread8(chip->vendor.iobase + 1); |
51 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 51 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
52 | dev_err(chip->dev, "error reading header\n"); | 52 | dev_err(chip->pdev, "error reading header\n"); |
53 | return -EIO; | 53 | return -EIO; |
54 | } | 54 | } |
55 | *buf++ = ioread8(chip->vendor.iobase); | 55 | *buf++ = ioread8(chip->vendor.iobase); |
@@ -60,12 +60,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
60 | size = be32_to_cpu(*native_size); | 60 | size = be32_to_cpu(*native_size); |
61 | 61 | ||
62 | if (count < size) { | 62 | if (count < size) { |
63 | dev_err(chip->dev, | 63 | dev_err(chip->pdev, |
64 | "Recv size(%d) less than available space\n", size); | 64 | "Recv size(%d) less than available space\n", size); |
65 | for (; i < size; i++) { /* clear the waiting data anyway */ | 65 | for (; i < size; i++) { /* clear the waiting data anyway */ |
66 | status = ioread8(chip->vendor.iobase + 1); | 66 | status = ioread8(chip->vendor.iobase + 1); |
67 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 67 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
68 | dev_err(chip->dev, "error reading data\n"); | 68 | dev_err(chip->pdev, "error reading data\n"); |
69 | return -EIO; | 69 | return -EIO; |
70 | } | 70 | } |
71 | } | 71 | } |
@@ -76,7 +76,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
76 | for (; i < size; i++) { | 76 | for (; i < size; i++) { |
77 | status = ioread8(chip->vendor.iobase + 1); | 77 | status = ioread8(chip->vendor.iobase + 1); |
78 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 78 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
79 | dev_err(chip->dev, "error reading data\n"); | 79 | dev_err(chip->pdev, "error reading data\n"); |
80 | return -EIO; | 80 | return -EIO; |
81 | } | 81 | } |
82 | *buf++ = ioread8(chip->vendor.iobase); | 82 | *buf++ = ioread8(chip->vendor.iobase); |
@@ -86,7 +86,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
86 | status = ioread8(chip->vendor.iobase + 1); | 86 | status = ioread8(chip->vendor.iobase + 1); |
87 | 87 | ||
88 | if (status & ATML_STATUS_DATA_AVAIL) { | 88 | if (status & ATML_STATUS_DATA_AVAIL) { |
89 | dev_err(chip->dev, "data available is stuck\n"); | 89 | dev_err(chip->pdev, "data available is stuck\n"); |
90 | return -EIO; | 90 | return -EIO; |
91 | } | 91 | } |
92 | 92 | ||
@@ -97,9 +97,9 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
97 | { | 97 | { |
98 | int i; | 98 | int i; |
99 | 99 | ||
100 | dev_dbg(chip->dev, "tpm_atml_send:\n"); | 100 | dev_dbg(chip->pdev, "tpm_atml_send:\n"); |
101 | for (i = 0; i < count; i++) { | 101 | for (i = 0; i < count; i++) { |
102 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); | 102 | dev_dbg(chip->pdev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); |
103 | iowrite8(buf[i], chip->vendor.iobase); | 103 | iowrite8(buf[i], chip->vendor.iobase); |
104 | } | 104 | } |
105 | 105 | ||
@@ -138,11 +138,11 @@ static void atml_plat_remove(void) | |||
138 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); | 138 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); |
139 | 139 | ||
140 | if (chip) { | 140 | if (chip) { |
141 | tpm_chip_unregister(chip); | ||
141 | if (chip->vendor.have_region) | 142 | if (chip->vendor.have_region) |
142 | atmel_release_region(chip->vendor.base, | 143 | atmel_release_region(chip->vendor.base, |
143 | chip->vendor.region_size); | 144 | chip->vendor.region_size); |
144 | atmel_put_base_addr(chip->vendor.iobase); | 145 | atmel_put_base_addr(chip->vendor.iobase); |
145 | tpm_remove_hardware(chip->dev); | ||
146 | platform_device_unregister(pdev); | 146 | platform_device_unregister(pdev); |
147 | } | 147 | } |
148 | } | 148 | } |
@@ -183,8 +183,9 @@ static int __init init_atmel(void) | |||
183 | goto err_rel_reg; | 183 | goto err_rel_reg; |
184 | } | 184 | } |
185 | 185 | ||
186 | if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) { | 186 | chip = tpmm_chip_alloc(&pdev->dev, &tpm_atmel); |
187 | rc = -ENODEV; | 187 | if (IS_ERR(chip)) { |
188 | rc = PTR_ERR(chip); | ||
188 | goto err_unreg_dev; | 189 | goto err_unreg_dev; |
189 | } | 190 | } |
190 | 191 | ||
@@ -193,6 +194,10 @@ static int __init init_atmel(void) | |||
193 | chip->vendor.have_region = have_region; | 194 | chip->vendor.have_region = have_region; |
194 | chip->vendor.region_size = region_size; | 195 | chip->vendor.region_size = region_size; |
195 | 196 | ||
197 | rc = tpm_chip_register(chip); | ||
198 | if (rc) | ||
199 | goto err_unreg_dev; | ||
200 | |||
196 | return 0; | 201 | return 0; |
197 | 202 | ||
198 | err_unreg_dev: | 203 | err_unreg_dev: |
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c new file mode 100644 index 000000000000..3dd23cfae4fe --- /dev/null +++ b/drivers/char/tpm/tpm_crb.c | |||
@@ -0,0 +1,354 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Intel Corporation | ||
3 | * | ||
4 | * Authors: | ||
5 | * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | ||
6 | * | ||
7 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
8 | * | ||
9 | * This device driver implements the TPM interface as defined in | ||
10 | * the TCG CRB 2.0 TPM specification. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; version 2 | ||
15 | * of the License. | ||
16 | */ | ||
17 | |||
18 | #include <linux/acpi.h> | ||
19 | #include <linux/highmem.h> | ||
20 | #include <linux/rculist.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include "tpm.h" | ||
24 | |||
25 | #define ACPI_SIG_TPM2 "TPM2" | ||
26 | |||
27 | static const u8 CRB_ACPI_START_UUID[] = { | ||
28 | /* 0000 */ 0xAB, 0x6C, 0xBF, 0x6B, 0x63, 0x54, 0x14, 0x47, | ||
29 | /* 0008 */ 0xB7, 0xCD, 0xF0, 0x20, 0x3C, 0x03, 0x68, 0xD4 | ||
30 | }; | ||
31 | |||
32 | enum crb_defaults { | ||
33 | CRB_ACPI_START_REVISION_ID = 1, | ||
34 | CRB_ACPI_START_INDEX = 1, | ||
35 | }; | ||
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 { | ||
44 | struct acpi_table_header hdr; | ||
45 | u16 platform_class; | ||
46 | u16 reserved; | ||
47 | u64 control_area_pa; | ||
48 | u32 start_method; | ||
49 | } __packed; | ||
50 | |||
51 | enum crb_ca_request { | ||
52 | CRB_CA_REQ_GO_IDLE = BIT(0), | ||
53 | CRB_CA_REQ_CMD_READY = BIT(1), | ||
54 | }; | ||
55 | |||
56 | enum crb_ca_status { | ||
57 | CRB_CA_STS_ERROR = BIT(0), | ||
58 | CRB_CA_STS_TPM_IDLE = BIT(1), | ||
59 | }; | ||
60 | |||
61 | enum crb_start { | ||
62 | CRB_START_INVOKE = BIT(0), | ||
63 | }; | ||
64 | |||
65 | enum crb_cancel { | ||
66 | CRB_CANCEL_INVOKE = BIT(0), | ||
67 | }; | ||
68 | |||
69 | struct crb_control_area { | ||
70 | u32 req; | ||
71 | u32 sts; | ||
72 | u32 cancel; | ||
73 | u32 start; | ||
74 | u32 int_enable; | ||
75 | u32 int_sts; | ||
76 | u32 cmd_size; | ||
77 | u64 cmd_pa; | ||
78 | u32 rsp_size; | ||
79 | u64 rsp_pa; | ||
80 | } __packed; | ||
81 | |||
82 | enum crb_status { | ||
83 | CRB_STS_COMPLETE = BIT(0), | ||
84 | }; | ||
85 | |||
86 | enum crb_flags { | ||
87 | CRB_FL_ACPI_START = BIT(0), | ||
88 | CRB_FL_CRB_START = BIT(1), | ||
89 | }; | ||
90 | |||
91 | struct crb_priv { | ||
92 | unsigned int flags; | ||
93 | struct crb_control_area __iomem *cca; | ||
94 | u8 __iomem *cmd; | ||
95 | u8 __iomem *rsp; | ||
96 | }; | ||
97 | |||
98 | #ifdef CONFIG_PM_SLEEP | ||
99 | static int crb_resume(struct device *dev) | ||
100 | { | ||
101 | int rc; | ||
102 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
103 | |||
104 | rc = tpm2_shutdown(chip, TPM2_SU_STATE); | ||
105 | if (!rc) | ||
106 | rc = tpm2_do_selftest(chip); | ||
107 | |||
108 | return rc; | ||
109 | } | ||
110 | #endif | ||
111 | |||
112 | static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, crb_resume); | ||
113 | |||
114 | static u8 crb_status(struct tpm_chip *chip) | ||
115 | { | ||
116 | struct crb_priv *priv = chip->vendor.priv; | ||
117 | u8 sts = 0; | ||
118 | |||
119 | if ((le32_to_cpu(ioread32(&priv->cca->start)) & CRB_START_INVOKE) != | ||
120 | CRB_START_INVOKE) | ||
121 | sts |= CRB_STS_COMPLETE; | ||
122 | |||
123 | return sts; | ||
124 | } | ||
125 | |||
126 | static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count) | ||
127 | { | ||
128 | struct crb_priv *priv = chip->vendor.priv; | ||
129 | unsigned int expected; | ||
130 | |||
131 | /* sanity check */ | ||
132 | if (count < 6) | ||
133 | return -EIO; | ||
134 | |||
135 | if (le32_to_cpu(ioread32(&priv->cca->sts)) & CRB_CA_STS_ERROR) | ||
136 | return -EIO; | ||
137 | |||
138 | memcpy_fromio(buf, priv->rsp, 6); | ||
139 | expected = be32_to_cpup((__be32 *) &buf[2]); | ||
140 | |||
141 | if (expected > count) | ||
142 | return -EIO; | ||
143 | |||
144 | memcpy_fromio(&buf[6], &priv->rsp[6], expected - 6); | ||
145 | |||
146 | return expected; | ||
147 | } | ||
148 | |||
149 | static int crb_do_acpi_start(struct tpm_chip *chip) | ||
150 | { | ||
151 | union acpi_object *obj; | ||
152 | int rc; | ||
153 | |||
154 | obj = acpi_evaluate_dsm(chip->acpi_dev_handle, | ||
155 | CRB_ACPI_START_UUID, | ||
156 | CRB_ACPI_START_REVISION_ID, | ||
157 | CRB_ACPI_START_INDEX, | ||
158 | NULL); | ||
159 | if (!obj) | ||
160 | return -ENXIO; | ||
161 | rc = obj->integer.value == 0 ? 0 : -ENXIO; | ||
162 | ACPI_FREE(obj); | ||
163 | return rc; | ||
164 | } | ||
165 | |||
166 | static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) | ||
167 | { | ||
168 | struct crb_priv *priv = chip->vendor.priv; | ||
169 | int rc = 0; | ||
170 | |||
171 | if (len > le32_to_cpu(ioread32(&priv->cca->cmd_size))) { | ||
172 | dev_err(&chip->dev, | ||
173 | "invalid command count value %x %zx\n", | ||
174 | (unsigned int) len, | ||
175 | (size_t) le32_to_cpu(ioread32(&priv->cca->cmd_size))); | ||
176 | return -E2BIG; | ||
177 | } | ||
178 | |||
179 | memcpy_toio(priv->cmd, buf, len); | ||
180 | |||
181 | /* Make sure that cmd is populated before issuing start. */ | ||
182 | wmb(); | ||
183 | |||
184 | if (priv->flags & CRB_FL_CRB_START) | ||
185 | iowrite32(cpu_to_le32(CRB_START_INVOKE), &priv->cca->start); | ||
186 | |||
187 | if (priv->flags & CRB_FL_ACPI_START) | ||
188 | rc = crb_do_acpi_start(chip); | ||
189 | |||
190 | return rc; | ||
191 | } | ||
192 | |||
193 | static void crb_cancel(struct tpm_chip *chip) | ||
194 | { | ||
195 | struct crb_priv *priv = chip->vendor.priv; | ||
196 | |||
197 | iowrite32(cpu_to_le32(CRB_CANCEL_INVOKE), &priv->cca->cancel); | ||
198 | |||
199 | /* Make sure that cmd is populated before issuing cancel. */ | ||
200 | wmb(); | ||
201 | |||
202 | if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip)) | ||
203 | dev_err(&chip->dev, "ACPI Start failed\n"); | ||
204 | |||
205 | iowrite32(0, &priv->cca->cancel); | ||
206 | } | ||
207 | |||
208 | static bool crb_req_canceled(struct tpm_chip *chip, u8 status) | ||
209 | { | ||
210 | struct crb_priv *priv = chip->vendor.priv; | ||
211 | u32 cancel = le32_to_cpu(ioread32(&priv->cca->cancel)); | ||
212 | |||
213 | return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; | ||
214 | } | ||
215 | |||
216 | static const struct tpm_class_ops tpm_crb = { | ||
217 | .status = crb_status, | ||
218 | .recv = crb_recv, | ||
219 | .send = crb_send, | ||
220 | .cancel = crb_cancel, | ||
221 | .req_canceled = crb_req_canceled, | ||
222 | .req_complete_mask = CRB_STS_COMPLETE, | ||
223 | .req_complete_val = CRB_STS_COMPLETE, | ||
224 | }; | ||
225 | |||
226 | static int crb_acpi_add(struct acpi_device *device) | ||
227 | { | ||
228 | struct tpm_chip *chip; | ||
229 | struct acpi_tpm2 *buf; | ||
230 | struct crb_priv *priv; | ||
231 | struct device *dev = &device->dev; | ||
232 | acpi_status status; | ||
233 | u32 sm; | ||
234 | u64 pa; | ||
235 | int rc; | ||
236 | |||
237 | chip = tpmm_chip_alloc(dev, &tpm_crb); | ||
238 | if (IS_ERR(chip)) | ||
239 | return PTR_ERR(chip); | ||
240 | |||
241 | chip->flags = TPM_CHIP_FLAG_TPM2; | ||
242 | |||
243 | status = acpi_get_table(ACPI_SIG_TPM2, 1, | ||
244 | (struct acpi_table_header **) &buf); | ||
245 | if (ACPI_FAILURE(status)) { | ||
246 | dev_err(dev, "failed to get TPM2 ACPI table\n"); | ||
247 | return -ENODEV; | ||
248 | } | ||
249 | |||
250 | if (buf->hdr.length < sizeof(struct acpi_tpm2)) { | ||
251 | dev_err(dev, "TPM2 ACPI table has wrong size"); | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | |||
255 | priv = (struct crb_priv *) devm_kzalloc(dev, sizeof(struct crb_priv), | ||
256 | GFP_KERNEL); | ||
257 | if (!priv) { | ||
258 | dev_err(dev, "failed to devm_kzalloc for private data\n"); | ||
259 | return -ENOMEM; | ||
260 | } | ||
261 | |||
262 | sm = le32_to_cpu(buf->start_method); | ||
263 | |||
264 | /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs | ||
265 | * report only ACPI start but in practice seems to require both | ||
266 | * ACPI start and CRB start. | ||
267 | */ | ||
268 | if (sm == CRB_SM_CRB || sm == CRB_SM_CRB_WITH_ACPI_START || | ||
269 | !strcmp(acpi_device_hid(device), "MSFT0101")) | ||
270 | priv->flags |= CRB_FL_CRB_START; | ||
271 | |||
272 | if (sm == CRB_SM_ACPI_START || sm == CRB_SM_CRB_WITH_ACPI_START) | ||
273 | priv->flags |= CRB_FL_ACPI_START; | ||
274 | |||
275 | priv->cca = (struct crb_control_area __iomem *) | ||
276 | devm_ioremap_nocache(dev, buf->control_area_pa, 0x1000); | ||
277 | if (!priv->cca) { | ||
278 | dev_err(dev, "ioremap of the control area failed\n"); | ||
279 | return -ENOMEM; | ||
280 | } | ||
281 | |||
282 | memcpy_fromio(&pa, &priv->cca->cmd_pa, 8); | ||
283 | pa = le64_to_cpu(pa); | ||
284 | priv->cmd = devm_ioremap_nocache(dev, le64_to_cpu(pa), | ||
285 | ioread32(&priv->cca->cmd_size)); | ||
286 | if (!priv->cmd) { | ||
287 | dev_err(dev, "ioremap of the command buffer failed\n"); | ||
288 | return -ENOMEM; | ||
289 | } | ||
290 | |||
291 | memcpy_fromio(&pa, &priv->cca->rsp_pa, 8); | ||
292 | pa = le64_to_cpu(pa); | ||
293 | priv->rsp = devm_ioremap_nocache(dev, le64_to_cpu(pa), | ||
294 | ioread32(&priv->cca->rsp_size)); | ||
295 | if (!priv->rsp) { | ||
296 | dev_err(dev, "ioremap of the response buffer failed\n"); | ||
297 | return -ENOMEM; | ||
298 | } | ||
299 | |||
300 | chip->vendor.priv = priv; | ||
301 | |||
302 | /* Default timeouts and durations */ | ||
303 | chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); | ||
304 | chip->vendor.timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); | ||
305 | chip->vendor.timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); | ||
306 | chip->vendor.timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); | ||
307 | chip->vendor.duration[TPM_SHORT] = | ||
308 | msecs_to_jiffies(TPM2_DURATION_SHORT); | ||
309 | chip->vendor.duration[TPM_MEDIUM] = | ||
310 | msecs_to_jiffies(TPM2_DURATION_MEDIUM); | ||
311 | chip->vendor.duration[TPM_LONG] = | ||
312 | msecs_to_jiffies(TPM2_DURATION_LONG); | ||
313 | |||
314 | chip->acpi_dev_handle = device->handle; | ||
315 | |||
316 | rc = tpm2_do_selftest(chip); | ||
317 | if (rc) | ||
318 | return rc; | ||
319 | |||
320 | return tpm_chip_register(chip); | ||
321 | } | ||
322 | |||
323 | static int crb_acpi_remove(struct acpi_device *device) | ||
324 | { | ||
325 | struct device *dev = &device->dev; | ||
326 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
327 | |||
328 | tpm_chip_unregister(chip); | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static struct acpi_device_id crb_device_ids[] = { | ||
333 | {"MSFT0101", 0}, | ||
334 | {"", 0}, | ||
335 | }; | ||
336 | MODULE_DEVICE_TABLE(acpi, crb_device_ids); | ||
337 | |||
338 | static struct acpi_driver crb_acpi_driver = { | ||
339 | .name = "tpm_crb", | ||
340 | .ids = crb_device_ids, | ||
341 | .ops = { | ||
342 | .add = crb_acpi_add, | ||
343 | .remove = crb_acpi_remove, | ||
344 | }, | ||
345 | .drv = { | ||
346 | .pm = &crb_pm, | ||
347 | }, | ||
348 | }; | ||
349 | |||
350 | module_acpi_driver(crb_acpi_driver); | ||
351 | MODULE_AUTHOR("Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>"); | ||
352 | MODULE_DESCRIPTION("TPM2 Driver"); | ||
353 | MODULE_VERSION("0.1"); | ||
354 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c index 77272925dee6..7a0ca78ad3c6 100644 --- a/drivers/char/tpm/tpm_i2c_atmel.c +++ b/drivers/char/tpm/tpm_i2c_atmel.c | |||
@@ -52,7 +52,7 @@ struct priv_data { | |||
52 | static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) | 52 | static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) |
53 | { | 53 | { |
54 | struct priv_data *priv = chip->vendor.priv; | 54 | struct priv_data *priv = chip->vendor.priv; |
55 | struct i2c_client *client = to_i2c_client(chip->dev); | 55 | struct i2c_client *client = to_i2c_client(chip->pdev); |
56 | s32 status; | 56 | s32 status; |
57 | 57 | ||
58 | priv->len = 0; | 58 | priv->len = 0; |
@@ -62,7 +62,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
62 | 62 | ||
63 | status = i2c_master_send(client, buf, len); | 63 | status = i2c_master_send(client, buf, len); |
64 | 64 | ||
65 | dev_dbg(chip->dev, | 65 | dev_dbg(chip->pdev, |
66 | "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__, | 66 | "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__, |
67 | (int)min_t(size_t, 64, len), buf, len, status); | 67 | (int)min_t(size_t, 64, len), buf, len, status); |
68 | return status; | 68 | return status; |
@@ -71,7 +71,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
71 | static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) | 71 | static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) |
72 | { | 72 | { |
73 | struct priv_data *priv = chip->vendor.priv; | 73 | struct priv_data *priv = chip->vendor.priv; |
74 | struct i2c_client *client = to_i2c_client(chip->dev); | 74 | struct i2c_client *client = to_i2c_client(chip->pdev); |
75 | struct tpm_output_header *hdr = | 75 | struct tpm_output_header *hdr = |
76 | (struct tpm_output_header *)priv->buffer; | 76 | (struct tpm_output_header *)priv->buffer; |
77 | u32 expected_len; | 77 | u32 expected_len; |
@@ -88,7 +88,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
88 | return -ENOMEM; | 88 | return -ENOMEM; |
89 | 89 | ||
90 | if (priv->len >= expected_len) { | 90 | if (priv->len >= expected_len) { |
91 | dev_dbg(chip->dev, | 91 | dev_dbg(chip->pdev, |
92 | "%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__, | 92 | "%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__, |
93 | (int)min_t(size_t, 64, expected_len), buf, count, | 93 | (int)min_t(size_t, 64, expected_len), buf, count, |
94 | expected_len); | 94 | expected_len); |
@@ -97,7 +97,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | rc = i2c_master_recv(client, buf, expected_len); | 99 | rc = i2c_master_recv(client, buf, expected_len); |
100 | dev_dbg(chip->dev, | 100 | dev_dbg(chip->pdev, |
101 | "%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__, | 101 | "%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__, |
102 | (int)min_t(size_t, 64, expected_len), buf, count, | 102 | (int)min_t(size_t, 64, expected_len), buf, count, |
103 | expected_len); | 103 | expected_len); |
@@ -106,13 +106,13 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
106 | 106 | ||
107 | static void i2c_atmel_cancel(struct tpm_chip *chip) | 107 | static void i2c_atmel_cancel(struct tpm_chip *chip) |
108 | { | 108 | { |
109 | dev_err(chip->dev, "TPM operation cancellation was requested, but is not supported"); | 109 | dev_err(chip->pdev, "TPM operation cancellation was requested, but is not supported"); |
110 | } | 110 | } |
111 | 111 | ||
112 | static u8 i2c_atmel_read_status(struct tpm_chip *chip) | 112 | static u8 i2c_atmel_read_status(struct tpm_chip *chip) |
113 | { | 113 | { |
114 | struct priv_data *priv = chip->vendor.priv; | 114 | struct priv_data *priv = chip->vendor.priv; |
115 | struct i2c_client *client = to_i2c_client(chip->dev); | 115 | struct i2c_client *client = to_i2c_client(chip->pdev); |
116 | int rc; | 116 | int rc; |
117 | 117 | ||
118 | /* The TPM fails the I2C read until it is ready, so we do the entire | 118 | /* The TPM fails the I2C read until it is ready, so we do the entire |
@@ -125,7 +125,7 @@ static u8 i2c_atmel_read_status(struct tpm_chip *chip) | |||
125 | /* Once the TPM has completed the command the command remains readable | 125 | /* Once the TPM has completed the command the command remains readable |
126 | * until another command is issued. */ | 126 | * until another command is issued. */ |
127 | rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer)); | 127 | rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer)); |
128 | dev_dbg(chip->dev, | 128 | dev_dbg(chip->pdev, |
129 | "%s: sts=%d", __func__, rc); | 129 | "%s: sts=%d", __func__, rc); |
130 | if (rc <= 0) | 130 | if (rc <= 0) |
131 | return 0; | 131 | return 0; |
@@ -153,21 +153,20 @@ static const struct tpm_class_ops i2c_atmel = { | |||
153 | static int i2c_atmel_probe(struct i2c_client *client, | 153 | static int i2c_atmel_probe(struct i2c_client *client, |
154 | const struct i2c_device_id *id) | 154 | const struct i2c_device_id *id) |
155 | { | 155 | { |
156 | int rc; | ||
157 | struct tpm_chip *chip; | 156 | struct tpm_chip *chip; |
158 | struct device *dev = &client->dev; | 157 | struct device *dev = &client->dev; |
159 | 158 | ||
160 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | 159 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
161 | return -ENODEV; | 160 | return -ENODEV; |
162 | 161 | ||
163 | chip = tpm_register_hardware(dev, &i2c_atmel); | 162 | chip = tpmm_chip_alloc(dev, &i2c_atmel); |
164 | if (!chip) { | 163 | if (IS_ERR(chip)) |
165 | dev_err(dev, "%s() error in tpm_register_hardware\n", __func__); | 164 | return PTR_ERR(chip); |
166 | return -ENODEV; | ||
167 | } | ||
168 | 165 | ||
169 | chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), | 166 | chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), |
170 | GFP_KERNEL); | 167 | GFP_KERNEL); |
168 | if (!chip->vendor.priv) | ||
169 | return -ENOMEM; | ||
171 | 170 | ||
172 | /* Default timeouts */ | 171 | /* Default timeouts */ |
173 | chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); | 172 | chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); |
@@ -179,33 +178,20 @@ static int i2c_atmel_probe(struct i2c_client *client, | |||
179 | /* There is no known way to probe for this device, and all version | 178 | /* There is no known way to probe for this device, and all version |
180 | * information seems to be read via TPM commands. Thus we rely on the | 179 | * information seems to be read via TPM commands. Thus we rely on the |
181 | * TPM startup process in the common code to detect the device. */ | 180 | * TPM startup process in the common code to detect the device. */ |
182 | if (tpm_get_timeouts(chip)) { | 181 | if (tpm_get_timeouts(chip)) |
183 | rc = -ENODEV; | 182 | return -ENODEV; |
184 | goto out_err; | ||
185 | } | ||
186 | |||
187 | if (tpm_do_selftest(chip)) { | ||
188 | rc = -ENODEV; | ||
189 | goto out_err; | ||
190 | } | ||
191 | 183 | ||
192 | return 0; | 184 | if (tpm_do_selftest(chip)) |
185 | return -ENODEV; | ||
193 | 186 | ||
194 | out_err: | 187 | return tpm_chip_register(chip); |
195 | tpm_dev_vendor_release(chip); | ||
196 | tpm_remove_hardware(chip->dev); | ||
197 | return rc; | ||
198 | } | 188 | } |
199 | 189 | ||
200 | static int i2c_atmel_remove(struct i2c_client *client) | 190 | static int i2c_atmel_remove(struct i2c_client *client) |
201 | { | 191 | { |
202 | struct device *dev = &(client->dev); | 192 | struct device *dev = &(client->dev); |
203 | struct tpm_chip *chip = dev_get_drvdata(dev); | 193 | struct tpm_chip *chip = dev_get_drvdata(dev); |
204 | 194 | tpm_chip_unregister(chip); | |
205 | if (chip) | ||
206 | tpm_dev_vendor_release(chip); | ||
207 | tpm_remove_hardware(dev); | ||
208 | kfree(chip); | ||
209 | return 0; | 195 | return 0; |
210 | } | 196 | } |
211 | 197 | ||
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 472af4bb1b61..33c5f360ab01 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c | |||
@@ -446,7 +446,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
446 | /* read first 10 bytes, including tag, paramsize, and result */ | 446 | /* read first 10 bytes, including tag, paramsize, and result */ |
447 | size = recv_data(chip, buf, TPM_HEADER_SIZE); | 447 | size = recv_data(chip, buf, TPM_HEADER_SIZE); |
448 | if (size < TPM_HEADER_SIZE) { | 448 | if (size < TPM_HEADER_SIZE) { |
449 | dev_err(chip->dev, "Unable to read header\n"); | 449 | dev_err(chip->pdev, "Unable to read header\n"); |
450 | goto out; | 450 | goto out; |
451 | } | 451 | } |
452 | 452 | ||
@@ -459,14 +459,14 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
459 | size += recv_data(chip, &buf[TPM_HEADER_SIZE], | 459 | size += recv_data(chip, &buf[TPM_HEADER_SIZE], |
460 | expected - TPM_HEADER_SIZE); | 460 | expected - TPM_HEADER_SIZE); |
461 | if (size < expected) { | 461 | if (size < expected) { |
462 | dev_err(chip->dev, "Unable to read remainder of result\n"); | 462 | dev_err(chip->pdev, "Unable to read remainder of result\n"); |
463 | size = -ETIME; | 463 | size = -ETIME; |
464 | goto out; | 464 | goto out; |
465 | } | 465 | } |
466 | 466 | ||
467 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); | 467 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); |
468 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ | 468 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ |
469 | dev_err(chip->dev, "Error left over data\n"); | 469 | dev_err(chip->pdev, "Error left over data\n"); |
470 | size = -EIO; | 470 | size = -EIO; |
471 | goto out; | 471 | goto out; |
472 | } | 472 | } |
@@ -581,12 +581,9 @@ static int tpm_tis_i2c_init(struct device *dev) | |||
581 | int rc = 0; | 581 | int rc = 0; |
582 | struct tpm_chip *chip; | 582 | struct tpm_chip *chip; |
583 | 583 | ||
584 | chip = tpm_register_hardware(dev, &tpm_tis_i2c); | 584 | chip = tpmm_chip_alloc(dev, &tpm_tis_i2c); |
585 | if (!chip) { | 585 | if (IS_ERR(chip)) |
586 | dev_err(dev, "could not register hardware\n"); | 586 | return PTR_ERR(chip); |
587 | rc = -ENODEV; | ||
588 | goto out_err; | ||
589 | } | ||
590 | 587 | ||
591 | /* Disable interrupts */ | 588 | /* Disable interrupts */ |
592 | chip->vendor.irq = 0; | 589 | chip->vendor.irq = 0; |
@@ -600,7 +597,7 @@ static int tpm_tis_i2c_init(struct device *dev) | |||
600 | if (request_locality(chip, 0) != 0) { | 597 | if (request_locality(chip, 0) != 0) { |
601 | dev_err(dev, "could not request locality\n"); | 598 | dev_err(dev, "could not request locality\n"); |
602 | rc = -ENODEV; | 599 | rc = -ENODEV; |
603 | goto out_vendor; | 600 | goto out_err; |
604 | } | 601 | } |
605 | 602 | ||
606 | /* read four bytes from DID_VID register */ | 603 | /* read four bytes from DID_VID register */ |
@@ -628,21 +625,9 @@ static int tpm_tis_i2c_init(struct device *dev) | |||
628 | tpm_get_timeouts(chip); | 625 | tpm_get_timeouts(chip); |
629 | tpm_do_selftest(chip); | 626 | tpm_do_selftest(chip); |
630 | 627 | ||
631 | return 0; | 628 | return tpm_chip_register(chip); |
632 | |||
633 | out_release: | 629 | out_release: |
634 | release_locality(chip, chip->vendor.locality, 1); | 630 | release_locality(chip, chip->vendor.locality, 1); |
635 | |||
636 | out_vendor: | ||
637 | /* close file handles */ | ||
638 | tpm_dev_vendor_release(chip); | ||
639 | |||
640 | /* remove hardware */ | ||
641 | tpm_remove_hardware(chip->dev); | ||
642 | |||
643 | /* reset these pointers, otherwise we oops */ | ||
644 | chip->dev->release = NULL; | ||
645 | chip->release = NULL; | ||
646 | tpm_dev.client = NULL; | 631 | tpm_dev.client = NULL; |
647 | out_err: | 632 | out_err: |
648 | return rc; | 633 | return rc; |
@@ -712,17 +697,9 @@ static int tpm_tis_i2c_probe(struct i2c_client *client, | |||
712 | static int tpm_tis_i2c_remove(struct i2c_client *client) | 697 | static int tpm_tis_i2c_remove(struct i2c_client *client) |
713 | { | 698 | { |
714 | struct tpm_chip *chip = tpm_dev.chip; | 699 | struct tpm_chip *chip = tpm_dev.chip; |
715 | release_locality(chip, chip->vendor.locality, 1); | ||
716 | 700 | ||
717 | /* close file handles */ | 701 | tpm_chip_unregister(chip); |
718 | tpm_dev_vendor_release(chip); | 702 | release_locality(chip, chip->vendor.locality, 1); |
719 | |||
720 | /* remove hardware */ | ||
721 | tpm_remove_hardware(chip->dev); | ||
722 | |||
723 | /* reset these pointers, otherwise we oops */ | ||
724 | chip->dev->release = NULL; | ||
725 | chip->release = NULL; | ||
726 | tpm_dev.client = NULL; | 703 | tpm_dev.client = NULL; |
727 | 704 | ||
728 | return 0; | 705 | return 0; |
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index 7b158efd49f7..9d42b7d78e50 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c | |||
@@ -96,13 +96,13 @@ static s32 i2c_nuvoton_write_buf(struct i2c_client *client, u8 offset, u8 size, | |||
96 | /* read TPM_STS register */ | 96 | /* read TPM_STS register */ |
97 | static u8 i2c_nuvoton_read_status(struct tpm_chip *chip) | 97 | static u8 i2c_nuvoton_read_status(struct tpm_chip *chip) |
98 | { | 98 | { |
99 | struct i2c_client *client = to_i2c_client(chip->dev); | 99 | struct i2c_client *client = to_i2c_client(chip->pdev); |
100 | s32 status; | 100 | s32 status; |
101 | u8 data; | 101 | u8 data; |
102 | 102 | ||
103 | status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data); | 103 | status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data); |
104 | if (status <= 0) { | 104 | if (status <= 0) { |
105 | dev_err(chip->dev, "%s() error return %d\n", __func__, | 105 | dev_err(chip->pdev, "%s() error return %d\n", __func__, |
106 | status); | 106 | status); |
107 | data = TPM_STS_ERR_VAL; | 107 | data = TPM_STS_ERR_VAL; |
108 | } | 108 | } |
@@ -127,13 +127,13 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data) | |||
127 | /* write commandReady to TPM_STS register */ | 127 | /* write commandReady to TPM_STS register */ |
128 | static void i2c_nuvoton_ready(struct tpm_chip *chip) | 128 | static void i2c_nuvoton_ready(struct tpm_chip *chip) |
129 | { | 129 | { |
130 | struct i2c_client *client = to_i2c_client(chip->dev); | 130 | struct i2c_client *client = to_i2c_client(chip->pdev); |
131 | s32 status; | 131 | s32 status; |
132 | 132 | ||
133 | /* this causes the current command to be aborted */ | 133 | /* this causes the current command to be aborted */ |
134 | status = i2c_nuvoton_write_status(client, TPM_STS_COMMAND_READY); | 134 | status = i2c_nuvoton_write_status(client, TPM_STS_COMMAND_READY); |
135 | if (status < 0) | 135 | if (status < 0) |
136 | dev_err(chip->dev, | 136 | dev_err(chip->pdev, |
137 | "%s() fail to write TPM_STS.commandReady\n", __func__); | 137 | "%s() fail to write TPM_STS.commandReady\n", __func__); |
138 | } | 138 | } |
139 | 139 | ||
@@ -212,7 +212,7 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value, | |||
212 | return 0; | 212 | return 0; |
213 | } while (time_before(jiffies, stop)); | 213 | } while (time_before(jiffies, stop)); |
214 | } | 214 | } |
215 | dev_err(chip->dev, "%s(%02x, %02x) -> timeout\n", __func__, mask, | 215 | dev_err(chip->pdev, "%s(%02x, %02x) -> timeout\n", __func__, mask, |
216 | value); | 216 | value); |
217 | return -ETIMEDOUT; | 217 | return -ETIMEDOUT; |
218 | } | 218 | } |
@@ -240,7 +240,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, | |||
240 | &chip->vendor.read_queue) == 0) { | 240 | &chip->vendor.read_queue) == 0) { |
241 | burst_count = i2c_nuvoton_get_burstcount(client, chip); | 241 | burst_count = i2c_nuvoton_get_burstcount(client, chip); |
242 | if (burst_count < 0) { | 242 | if (burst_count < 0) { |
243 | dev_err(chip->dev, | 243 | dev_err(chip->pdev, |
244 | "%s() fail to read burstCount=%d\n", __func__, | 244 | "%s() fail to read burstCount=%d\n", __func__, |
245 | burst_count); | 245 | burst_count); |
246 | return -EIO; | 246 | return -EIO; |
@@ -249,12 +249,12 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, | |||
249 | rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_R, | 249 | rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_R, |
250 | bytes2read, &buf[size]); | 250 | bytes2read, &buf[size]); |
251 | if (rc < 0) { | 251 | if (rc < 0) { |
252 | dev_err(chip->dev, | 252 | dev_err(chip->pdev, |
253 | "%s() fail on i2c_nuvoton_read_buf()=%d\n", | 253 | "%s() fail on i2c_nuvoton_read_buf()=%d\n", |
254 | __func__, rc); | 254 | __func__, rc); |
255 | return -EIO; | 255 | return -EIO; |
256 | } | 256 | } |
257 | dev_dbg(chip->dev, "%s(%d):", __func__, bytes2read); | 257 | dev_dbg(chip->pdev, "%s(%d):", __func__, bytes2read); |
258 | size += bytes2read; | 258 | size += bytes2read; |
259 | } | 259 | } |
260 | 260 | ||
@@ -264,7 +264,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, | |||
264 | /* Read TPM command results */ | 264 | /* Read TPM command results */ |
265 | static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) | 265 | static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) |
266 | { | 266 | { |
267 | struct device *dev = chip->dev; | 267 | struct device *dev = chip->pdev; |
268 | struct i2c_client *client = to_i2c_client(dev); | 268 | struct i2c_client *client = to_i2c_client(dev); |
269 | s32 rc; | 269 | s32 rc; |
270 | int expected, status, burst_count, retries, size = 0; | 270 | int expected, status, burst_count, retries, size = 0; |
@@ -334,7 +334,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
334 | break; | 334 | break; |
335 | } | 335 | } |
336 | i2c_nuvoton_ready(chip); | 336 | i2c_nuvoton_ready(chip); |
337 | dev_dbg(chip->dev, "%s() -> %d\n", __func__, size); | 337 | dev_dbg(chip->pdev, "%s() -> %d\n", __func__, size); |
338 | return size; | 338 | return size; |
339 | } | 339 | } |
340 | 340 | ||
@@ -347,7 +347,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
347 | */ | 347 | */ |
348 | static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) | 348 | static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) |
349 | { | 349 | { |
350 | struct device *dev = chip->dev; | 350 | struct device *dev = chip->pdev; |
351 | struct i2c_client *client = to_i2c_client(dev); | 351 | struct i2c_client *client = to_i2c_client(dev); |
352 | u32 ordinal; | 352 | u32 ordinal; |
353 | size_t count = 0; | 353 | size_t count = 0; |
@@ -530,14 +530,15 @@ static int i2c_nuvoton_probe(struct i2c_client *client, | |||
530 | dev_info(dev, "VID: %04X DID: %02X RID: %02X\n", (u16) vid, | 530 | dev_info(dev, "VID: %04X DID: %02X RID: %02X\n", (u16) vid, |
531 | (u8) (vid >> 16), (u8) (vid >> 24)); | 531 | (u8) (vid >> 16), (u8) (vid >> 24)); |
532 | 532 | ||
533 | chip = tpm_register_hardware(dev, &tpm_i2c); | 533 | chip = tpmm_chip_alloc(dev, &tpm_i2c); |
534 | if (!chip) { | 534 | if (IS_ERR(chip)) |
535 | dev_err(dev, "%s() error in tpm_register_hardware\n", __func__); | 535 | return PTR_ERR(chip); |
536 | return -ENODEV; | ||
537 | } | ||
538 | 536 | ||
539 | chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), | 537 | chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), |
540 | GFP_KERNEL); | 538 | GFP_KERNEL); |
539 | if (!chip->vendor.priv) | ||
540 | return -ENOMEM; | ||
541 | |||
541 | init_waitqueue_head(&chip->vendor.read_queue); | 542 | init_waitqueue_head(&chip->vendor.read_queue); |
542 | init_waitqueue_head(&chip->vendor.int_queue); | 543 | init_waitqueue_head(&chip->vendor.int_queue); |
543 | 544 | ||
@@ -559,7 +560,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client, | |||
559 | rc = devm_request_irq(dev, chip->vendor.irq, | 560 | rc = devm_request_irq(dev, chip->vendor.irq, |
560 | i2c_nuvoton_int_handler, | 561 | i2c_nuvoton_int_handler, |
561 | IRQF_TRIGGER_LOW, | 562 | IRQF_TRIGGER_LOW, |
562 | chip->vendor.miscdev.name, | 563 | chip->devname, |
563 | chip); | 564 | chip); |
564 | if (rc) { | 565 | if (rc) { |
565 | dev_err(dev, "%s() Unable to request irq: %d for use\n", | 566 | dev_err(dev, "%s() Unable to request irq: %d for use\n", |
@@ -584,7 +585,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client, | |||
584 | TPM_DATA_FIFO_W, | 585 | TPM_DATA_FIFO_W, |
585 | 1, (u8 *) (&rc)); | 586 | 1, (u8 *) (&rc)); |
586 | if (rc < 0) | 587 | if (rc < 0) |
587 | goto out_err; | 588 | return rc; |
588 | /* TPM_STS <- 0x40 (commandReady) */ | 589 | /* TPM_STS <- 0x40 (commandReady) */ |
589 | i2c_nuvoton_ready(chip); | 590 | i2c_nuvoton_ready(chip); |
590 | } else { | 591 | } else { |
@@ -594,45 +595,29 @@ static int i2c_nuvoton_probe(struct i2c_client *client, | |||
594 | * only TPM_STS_VALID should be set | 595 | * only TPM_STS_VALID should be set |
595 | */ | 596 | */ |
596 | if (i2c_nuvoton_read_status(chip) != | 597 | if (i2c_nuvoton_read_status(chip) != |
597 | TPM_STS_VALID) { | 598 | TPM_STS_VALID) |
598 | rc = -EIO; | 599 | return -EIO; |
599 | goto out_err; | ||
600 | } | ||
601 | } | 600 | } |
602 | } | 601 | } |
603 | } | 602 | } |
604 | 603 | ||
605 | if (tpm_get_timeouts(chip)) { | 604 | if (tpm_get_timeouts(chip)) |
606 | rc = -ENODEV; | 605 | return -ENODEV; |
607 | goto out_err; | ||
608 | } | ||
609 | |||
610 | if (tpm_do_selftest(chip)) { | ||
611 | rc = -ENODEV; | ||
612 | goto out_err; | ||
613 | } | ||
614 | 606 | ||
615 | return 0; | 607 | if (tpm_do_selftest(chip)) |
608 | return -ENODEV; | ||
616 | 609 | ||
617 | out_err: | 610 | return tpm_chip_register(chip); |
618 | tpm_dev_vendor_release(chip); | ||
619 | tpm_remove_hardware(chip->dev); | ||
620 | return rc; | ||
621 | } | 611 | } |
622 | 612 | ||
623 | static int i2c_nuvoton_remove(struct i2c_client *client) | 613 | static int i2c_nuvoton_remove(struct i2c_client *client) |
624 | { | 614 | { |
625 | struct device *dev = &(client->dev); | 615 | struct device *dev = &(client->dev); |
626 | struct tpm_chip *chip = dev_get_drvdata(dev); | 616 | struct tpm_chip *chip = dev_get_drvdata(dev); |
627 | 617 | tpm_chip_unregister(chip); | |
628 | if (chip) | ||
629 | tpm_dev_vendor_release(chip); | ||
630 | tpm_remove_hardware(dev); | ||
631 | kfree(chip); | ||
632 | return 0; | 618 | return 0; |
633 | } | 619 | } |
634 | 620 | ||
635 | |||
636 | static const struct i2c_device_id i2c_nuvoton_id[] = { | 621 | static const struct i2c_device_id i2c_nuvoton_id[] = { |
637 | {I2C_DRIVER_NAME, 0}, | 622 | {I2C_DRIVER_NAME, 0}, |
638 | {} | 623 | {} |
diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c index 4669e3713428..612845b36c29 100644 --- a/drivers/char/tpm/tpm_i2c_stm_st33.c +++ b/drivers/char/tpm/tpm_i2c_stm_st33.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24 | 2 | * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24 |
3 | * Copyright (C) 2009, 2010 STMicroelectronics | 3 | * Copyright (C) 2009, 2010, 2014 STMicroelectronics |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -12,11 +12,10 @@ | |||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License along | 15 | * You should have received a copy of the GNU General Public License |
16 | * with this program; if not, write to the Free Software Foundation, Inc., | 16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * | 17 | * |
19 | * STMicroelectronics version 1.2.0, Copyright (C) 2010 | 18 | * STMicroelectronics version 1.2.1, Copyright (C) 2014 |
20 | * STMicroelectronics comes with ABSOLUTELY NO WARRANTY. | 19 | * STMicroelectronics comes with ABSOLUTELY NO WARRANTY. |
21 | * This is free software, and you are welcome to redistribute it | 20 | * This is free software, and you are welcome to redistribute it |
22 | * under certain conditions. | 21 | * under certain conditions. |
@@ -27,7 +26,7 @@ | |||
27 | * | 26 | * |
28 | * @Synopsis: | 27 | * @Synopsis: |
29 | * 09/15/2010: First shot driver tpm_tis driver for | 28 | * 09/15/2010: First shot driver tpm_tis driver for |
30 | lpc is used as model. | 29 | * lpc is used as model. |
31 | */ | 30 | */ |
32 | 31 | ||
33 | #include <linux/pci.h> | 32 | #include <linux/pci.h> |
@@ -39,18 +38,38 @@ | |||
39 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
40 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
41 | #include <linux/wait.h> | 40 | #include <linux/wait.h> |
41 | #include <linux/freezer.h> | ||
42 | #include <linux/string.h> | 42 | #include <linux/string.h> |
43 | #include <linux/interrupt.h> | 43 | #include <linux/interrupt.h> |
44 | #include <linux/spinlock.h> | ||
45 | #include <linux/sysfs.h> | 44 | #include <linux/sysfs.h> |
46 | #include <linux/gpio.h> | 45 | #include <linux/gpio.h> |
47 | #include <linux/sched.h> | 46 | #include <linux/sched.h> |
48 | #include <linux/uaccess.h> | 47 | #include <linux/uaccess.h> |
49 | #include <linux/io.h> | 48 | #include <linux/io.h> |
50 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
50 | #include <linux/of_irq.h> | ||
51 | #include <linux/of_gpio.h> | ||
51 | 52 | ||
53 | #include <linux/platform_data/tpm_stm_st33.h> | ||
52 | #include "tpm.h" | 54 | #include "tpm.h" |
53 | #include "tpm_i2c_stm_st33.h" | 55 | |
56 | #define TPM_ACCESS 0x0 | ||
57 | #define TPM_STS 0x18 | ||
58 | #define TPM_HASH_END 0x20 | ||
59 | #define TPM_DATA_FIFO 0x24 | ||
60 | #define TPM_HASH_DATA 0x24 | ||
61 | #define TPM_HASH_START 0x28 | ||
62 | #define TPM_INTF_CAPABILITY 0x14 | ||
63 | #define TPM_INT_STATUS 0x10 | ||
64 | #define TPM_INT_ENABLE 0x08 | ||
65 | |||
66 | #define TPM_DUMMY_BYTE 0xAA | ||
67 | #define TPM_WRITE_DIRECTION 0x80 | ||
68 | #define TPM_HEADER_SIZE 10 | ||
69 | #define TPM_BUFSIZE 2048 | ||
70 | |||
71 | #define LOCALITY0 0 | ||
72 | |||
54 | 73 | ||
55 | enum stm33zp24_access { | 74 | enum stm33zp24_access { |
56 | TPM_ACCESS_VALID = 0x80, | 75 | TPM_ACCESS_VALID = 0x80, |
@@ -82,6 +101,14 @@ enum tis_defaults { | |||
82 | TIS_LONG_TIMEOUT = 2000, | 101 | TIS_LONG_TIMEOUT = 2000, |
83 | }; | 102 | }; |
84 | 103 | ||
104 | struct tpm_stm_dev { | ||
105 | struct i2c_client *client; | ||
106 | struct tpm_chip *chip; | ||
107 | u8 buf[TPM_BUFSIZE + 1]; | ||
108 | u32 intrs; | ||
109 | int io_lpcpd; | ||
110 | }; | ||
111 | |||
85 | /* | 112 | /* |
86 | * write8_reg | 113 | * write8_reg |
87 | * Send byte to the TIS register according to the ST33ZP24 I2C protocol. | 114 | * Send byte to the TIS register according to the ST33ZP24 I2C protocol. |
@@ -90,17 +117,12 @@ enum tis_defaults { | |||
90 | * @param: tpm_size, The length of the data | 117 | * @param: tpm_size, The length of the data |
91 | * @return: Returns negative errno, or else the number of bytes written. | 118 | * @return: Returns negative errno, or else the number of bytes written. |
92 | */ | 119 | */ |
93 | static int write8_reg(struct i2c_client *client, u8 tpm_register, | 120 | static int write8_reg(struct tpm_stm_dev *tpm_dev, u8 tpm_register, |
94 | u8 *tpm_data, u16 tpm_size) | 121 | u8 *tpm_data, u16 tpm_size) |
95 | { | 122 | { |
96 | struct st33zp24_platform_data *pin_infos; | 123 | tpm_dev->buf[0] = tpm_register; |
97 | 124 | memcpy(tpm_dev->buf + 1, tpm_data, tpm_size); | |
98 | pin_infos = client->dev.platform_data; | 125 | return i2c_master_send(tpm_dev->client, tpm_dev->buf, tpm_size + 1); |
99 | |||
100 | pin_infos->tpm_i2c_buffer[0][0] = tpm_register; | ||
101 | memcpy(&pin_infos->tpm_i2c_buffer[0][1], tpm_data, tpm_size); | ||
102 | return i2c_master_send(client, pin_infos->tpm_i2c_buffer[0], | ||
103 | tpm_size + 1); | ||
104 | } /* write8_reg() */ | 126 | } /* write8_reg() */ |
105 | 127 | ||
106 | /* | 128 | /* |
@@ -111,101 +133,58 @@ static int write8_reg(struct i2c_client *client, u8 tpm_register, | |||
111 | * @param: tpm_size, tpm TPM response size to read. | 133 | * @param: tpm_size, tpm TPM response size to read. |
112 | * @return: number of byte read successfully: should be one if success. | 134 | * @return: number of byte read successfully: should be one if success. |
113 | */ | 135 | */ |
114 | static int read8_reg(struct i2c_client *client, u8 tpm_register, | 136 | static int read8_reg(struct tpm_stm_dev *tpm_dev, u8 tpm_register, |
115 | u8 *tpm_data, int tpm_size) | 137 | u8 *tpm_data, int tpm_size) |
116 | { | 138 | { |
117 | u8 status = 0; | 139 | u8 status = 0; |
118 | u8 data; | 140 | u8 data; |
119 | 141 | ||
120 | data = TPM_DUMMY_BYTE; | 142 | data = TPM_DUMMY_BYTE; |
121 | status = write8_reg(client, tpm_register, &data, 1); | 143 | status = write8_reg(tpm_dev, tpm_register, &data, 1); |
122 | if (status == 2) | 144 | if (status == 2) |
123 | status = i2c_master_recv(client, tpm_data, tpm_size); | 145 | status = i2c_master_recv(tpm_dev->client, tpm_data, tpm_size); |
124 | return status; | 146 | return status; |
125 | } /* read8_reg() */ | 147 | } /* read8_reg() */ |
126 | 148 | ||
127 | /* | 149 | /* |
128 | * I2C_WRITE_DATA | 150 | * I2C_WRITE_DATA |
129 | * Send byte to the TIS register according to the ST33ZP24 I2C protocol. | 151 | * Send byte to the TIS register according to the ST33ZP24 I2C protocol. |
130 | * @param: client, the chip description | 152 | * @param: tpm_dev, the chip description |
131 | * @param: tpm_register, the tpm tis register where the data should be written | 153 | * @param: tpm_register, the tpm tis register where the data should be written |
132 | * @param: tpm_data, the tpm_data to write inside the tpm_register | 154 | * @param: tpm_data, the tpm_data to write inside the tpm_register |
133 | * @param: tpm_size, The length of the data | 155 | * @param: tpm_size, The length of the data |
134 | * @return: number of byte written successfully: should be one if success. | 156 | * @return: number of byte written successfully: should be one if success. |
135 | */ | 157 | */ |
136 | #define I2C_WRITE_DATA(client, tpm_register, tpm_data, tpm_size) \ | 158 | #define I2C_WRITE_DATA(tpm_dev, tpm_register, tpm_data, tpm_size) \ |
137 | (write8_reg(client, tpm_register | \ | 159 | (write8_reg(tpm_dev, tpm_register | \ |
138 | TPM_WRITE_DIRECTION, tpm_data, tpm_size)) | 160 | TPM_WRITE_DIRECTION, tpm_data, tpm_size)) |
139 | 161 | ||
140 | /* | 162 | /* |
141 | * I2C_READ_DATA | 163 | * I2C_READ_DATA |
142 | * Recv byte from the TIS register according to the ST33ZP24 I2C protocol. | 164 | * Recv byte from the TIS register according to the ST33ZP24 I2C protocol. |
143 | * @param: tpm, the chip description | 165 | * @param: tpm_dev, the chip description |
144 | * @param: tpm_register, the tpm tis register where the data should be read | 166 | * @param: tpm_register, the tpm tis register where the data should be read |
145 | * @param: tpm_data, the TPM response | 167 | * @param: tpm_data, the TPM response |
146 | * @param: tpm_size, tpm TPM response size to read. | 168 | * @param: tpm_size, tpm TPM response size to read. |
147 | * @return: number of byte read successfully: should be one if success. | 169 | * @return: number of byte read successfully: should be one if success. |
148 | */ | 170 | */ |
149 | #define I2C_READ_DATA(client, tpm_register, tpm_data, tpm_size) \ | 171 | #define I2C_READ_DATA(tpm_dev, tpm_register, tpm_data, tpm_size) \ |
150 | (read8_reg(client, tpm_register, tpm_data, tpm_size)) | 172 | (read8_reg(tpm_dev, tpm_register, tpm_data, tpm_size)) |
151 | 173 | ||
152 | /* | 174 | /* |
153 | * clear_interruption | 175 | * clear_interruption |
154 | * clear the TPM interrupt register. | 176 | * clear the TPM interrupt register. |
155 | * @param: tpm, the chip description | 177 | * @param: tpm, the chip description |
178 | * @return: the TPM_INT_STATUS value | ||
156 | */ | 179 | */ |
157 | static void clear_interruption(struct i2c_client *client) | 180 | static u8 clear_interruption(struct tpm_stm_dev *tpm_dev) |
158 | { | 181 | { |
159 | u8 interrupt; | 182 | u8 interrupt; |
160 | I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1); | ||
161 | I2C_WRITE_DATA(client, TPM_INT_STATUS, &interrupt, 1); | ||
162 | I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1); | ||
163 | } /* clear_interruption() */ | ||
164 | |||
165 | /* | ||
166 | * _wait_for_interrupt_serirq_timeout | ||
167 | * @param: tpm, the chip description | ||
168 | * @param: timeout, the timeout of the interrupt | ||
169 | * @return: the status of the interruption. | ||
170 | */ | ||
171 | static long _wait_for_interrupt_serirq_timeout(struct tpm_chip *chip, | ||
172 | unsigned long timeout) | ||
173 | { | ||
174 | long status; | ||
175 | struct i2c_client *client; | ||
176 | struct st33zp24_platform_data *pin_infos; | ||
177 | |||
178 | client = (struct i2c_client *)TPM_VPRIV(chip); | ||
179 | pin_infos = client->dev.platform_data; | ||
180 | |||
181 | status = wait_for_completion_interruptible_timeout( | ||
182 | &pin_infos->irq_detection, | ||
183 | timeout); | ||
184 | if (status > 0) | ||
185 | enable_irq(gpio_to_irq(pin_infos->io_serirq)); | ||
186 | gpio_direction_input(pin_infos->io_serirq); | ||
187 | |||
188 | return status; | ||
189 | } /* wait_for_interrupt_serirq_timeout() */ | ||
190 | |||
191 | static int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition, | ||
192 | unsigned long timeout) | ||
193 | { | ||
194 | int status = 2; | ||
195 | struct i2c_client *client; | ||
196 | |||
197 | client = (struct i2c_client *)TPM_VPRIV(chip); | ||
198 | 183 | ||
199 | status = _wait_for_interrupt_serirq_timeout(chip, timeout); | 184 | I2C_READ_DATA(tpm_dev, TPM_INT_STATUS, &interrupt, 1); |
200 | if (!status) { | 185 | I2C_WRITE_DATA(tpm_dev, TPM_INT_STATUS, &interrupt, 1); |
201 | status = -EBUSY; | 186 | return interrupt; |
202 | } else { | 187 | } /* clear_interruption() */ |
203 | clear_interruption(client); | ||
204 | if (condition) | ||
205 | status = 1; | ||
206 | } | ||
207 | return status; | ||
208 | } | ||
209 | 188 | ||
210 | /* | 189 | /* |
211 | * tpm_stm_i2c_cancel, cancel is not implemented. | 190 | * tpm_stm_i2c_cancel, cancel is not implemented. |
@@ -213,16 +192,14 @@ static int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition, | |||
213 | */ | 192 | */ |
214 | static void tpm_stm_i2c_cancel(struct tpm_chip *chip) | 193 | static void tpm_stm_i2c_cancel(struct tpm_chip *chip) |
215 | { | 194 | { |
216 | struct i2c_client *client; | 195 | struct tpm_stm_dev *tpm_dev; |
217 | u8 data; | 196 | u8 data; |
218 | 197 | ||
219 | client = (struct i2c_client *)TPM_VPRIV(chip); | 198 | tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); |
220 | 199 | ||
221 | data = TPM_STS_COMMAND_READY; | 200 | data = TPM_STS_COMMAND_READY; |
222 | I2C_WRITE_DATA(client, TPM_STS, &data, 1); | 201 | I2C_WRITE_DATA(tpm_dev, TPM_STS, &data, 1); |
223 | if (chip->vendor.irq) | 202 | } /* tpm_stm_i2c_cancel() */ |
224 | wait_for_serirq_timeout(chip, 1, chip->vendor.timeout_a); | ||
225 | } /* tpm_stm_i2c_cancel() */ | ||
226 | 203 | ||
227 | /* | 204 | /* |
228 | * tpm_stm_spi_status return the TPM_STS register | 205 | * tpm_stm_spi_status return the TPM_STS register |
@@ -231,13 +208,14 @@ static void tpm_stm_i2c_cancel(struct tpm_chip *chip) | |||
231 | */ | 208 | */ |
232 | static u8 tpm_stm_i2c_status(struct tpm_chip *chip) | 209 | static u8 tpm_stm_i2c_status(struct tpm_chip *chip) |
233 | { | 210 | { |
234 | struct i2c_client *client; | 211 | struct tpm_stm_dev *tpm_dev; |
235 | u8 data; | 212 | u8 data; |
236 | client = (struct i2c_client *)TPM_VPRIV(chip); | ||
237 | 213 | ||
238 | I2C_READ_DATA(client, TPM_STS, &data, 1); | 214 | tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); |
215 | |||
216 | I2C_READ_DATA(tpm_dev, TPM_STS, &data, 1); | ||
239 | return data; | 217 | return data; |
240 | } /* tpm_stm_i2c_status() */ | 218 | } /* tpm_stm_i2c_status() */ |
241 | 219 | ||
242 | 220 | ||
243 | /* | 221 | /* |
@@ -247,20 +225,19 @@ static u8 tpm_stm_i2c_status(struct tpm_chip *chip) | |||
247 | */ | 225 | */ |
248 | static int check_locality(struct tpm_chip *chip) | 226 | static int check_locality(struct tpm_chip *chip) |
249 | { | 227 | { |
250 | struct i2c_client *client; | 228 | struct tpm_stm_dev *tpm_dev; |
251 | u8 data; | 229 | u8 data; |
252 | u8 status; | 230 | u8 status; |
253 | 231 | ||
254 | client = (struct i2c_client *)TPM_VPRIV(chip); | 232 | tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); |
255 | 233 | ||
256 | status = I2C_READ_DATA(client, TPM_ACCESS, &data, 1); | 234 | status = I2C_READ_DATA(tpm_dev, TPM_ACCESS, &data, 1); |
257 | if (status && (data & | 235 | if (status && (data & |
258 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == | 236 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == |
259 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) | 237 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) |
260 | return chip->vendor.locality; | 238 | return chip->vendor.locality; |
261 | 239 | ||
262 | return -EACCES; | 240 | return -EACCES; |
263 | |||
264 | } /* check_locality() */ | 241 | } /* check_locality() */ |
265 | 242 | ||
266 | /* | 243 | /* |
@@ -271,37 +248,31 @@ static int check_locality(struct tpm_chip *chip) | |||
271 | static int request_locality(struct tpm_chip *chip) | 248 | static int request_locality(struct tpm_chip *chip) |
272 | { | 249 | { |
273 | unsigned long stop; | 250 | unsigned long stop; |
274 | long rc; | 251 | long ret; |
275 | struct i2c_client *client; | 252 | struct tpm_stm_dev *tpm_dev; |
276 | u8 data; | 253 | u8 data; |
277 | 254 | ||
278 | client = (struct i2c_client *)TPM_VPRIV(chip); | ||
279 | |||
280 | if (check_locality(chip) == chip->vendor.locality) | 255 | if (check_locality(chip) == chip->vendor.locality) |
281 | return chip->vendor.locality; | 256 | return chip->vendor.locality; |
282 | 257 | ||
258 | tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); | ||
259 | |||
283 | data = TPM_ACCESS_REQUEST_USE; | 260 | data = TPM_ACCESS_REQUEST_USE; |
284 | rc = I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1); | 261 | ret = I2C_WRITE_DATA(tpm_dev, TPM_ACCESS, &data, 1); |
285 | if (rc < 0) | 262 | if (ret < 0) |
286 | goto end; | 263 | goto end; |
287 | 264 | ||
288 | if (chip->vendor.irq) { | 265 | stop = jiffies + chip->vendor.timeout_a; |
289 | rc = wait_for_serirq_timeout(chip, (check_locality | 266 | |
290 | (chip) >= 0), | 267 | /* Request locality is usually effective after the request */ |
291 | chip->vendor.timeout_a); | 268 | do { |
292 | if (rc > 0) | 269 | if (check_locality(chip) >= 0) |
293 | return chip->vendor.locality; | 270 | return chip->vendor.locality; |
294 | } else { | 271 | msleep(TPM_TIMEOUT); |
295 | stop = jiffies + chip->vendor.timeout_a; | 272 | } while (time_before(jiffies, stop)); |
296 | do { | 273 | ret = -EACCES; |
297 | if (check_locality(chip) >= 0) | ||
298 | return chip->vendor.locality; | ||
299 | msleep(TPM_TIMEOUT); | ||
300 | } while (time_before(jiffies, stop)); | ||
301 | } | ||
302 | rc = -EACCES; | ||
303 | end: | 274 | end: |
304 | return rc; | 275 | return ret; |
305 | } /* request_locality() */ | 276 | } /* request_locality() */ |
306 | 277 | ||
307 | /* | 278 | /* |
@@ -310,13 +281,13 @@ end: | |||
310 | */ | 281 | */ |
311 | static void release_locality(struct tpm_chip *chip) | 282 | static void release_locality(struct tpm_chip *chip) |
312 | { | 283 | { |
313 | struct i2c_client *client; | 284 | struct tpm_stm_dev *tpm_dev; |
314 | u8 data; | 285 | u8 data; |
315 | 286 | ||
316 | client = (struct i2c_client *)TPM_VPRIV(chip); | 287 | tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); |
317 | data = TPM_ACCESS_ACTIVE_LOCALITY; | 288 | data = TPM_ACCESS_ACTIVE_LOCALITY; |
318 | 289 | ||
319 | I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1); | 290 | I2C_WRITE_DATA(tpm_dev, TPM_ACCESS, &data, 1); |
320 | } | 291 | } |
321 | 292 | ||
322 | /* | 293 | /* |
@@ -329,19 +300,20 @@ static int get_burstcount(struct tpm_chip *chip) | |||
329 | unsigned long stop; | 300 | unsigned long stop; |
330 | int burstcnt, status; | 301 | int burstcnt, status; |
331 | u8 tpm_reg, temp; | 302 | u8 tpm_reg, temp; |
303 | struct tpm_stm_dev *tpm_dev; | ||
332 | 304 | ||
333 | struct i2c_client *client = (struct i2c_client *)TPM_VPRIV(chip); | 305 | tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); |
334 | 306 | ||
335 | stop = jiffies + chip->vendor.timeout_d; | 307 | stop = jiffies + chip->vendor.timeout_d; |
336 | do { | 308 | do { |
337 | tpm_reg = TPM_STS + 1; | 309 | tpm_reg = TPM_STS + 1; |
338 | status = I2C_READ_DATA(client, tpm_reg, &temp, 1); | 310 | status = I2C_READ_DATA(tpm_dev, tpm_reg, &temp, 1); |
339 | if (status < 0) | 311 | if (status < 0) |
340 | goto end; | 312 | goto end; |
341 | 313 | ||
342 | tpm_reg = tpm_reg + 1; | 314 | tpm_reg = tpm_reg + 1; |
343 | burstcnt = temp; | 315 | burstcnt = temp; |
344 | status = I2C_READ_DATA(client, tpm_reg, &temp, 1); | 316 | status = I2C_READ_DATA(tpm_dev, tpm_reg, &temp, 1); |
345 | if (status < 0) | 317 | if (status < 0) |
346 | goto end; | 318 | goto end; |
347 | 319 | ||
@@ -355,36 +327,107 @@ end: | |||
355 | return -EBUSY; | 327 | return -EBUSY; |
356 | } /* get_burstcount() */ | 328 | } /* get_burstcount() */ |
357 | 329 | ||
330 | static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, | ||
331 | bool check_cancel, bool *canceled) | ||
332 | { | ||
333 | u8 status = chip->ops->status(chip); | ||
334 | |||
335 | *canceled = false; | ||
336 | if ((status & mask) == mask) | ||
337 | return true; | ||
338 | if (check_cancel && chip->ops->req_canceled(chip, status)) { | ||
339 | *canceled = true; | ||
340 | return true; | ||
341 | } | ||
342 | return false; | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * interrupt_to_status | ||
347 | * @param: irq_mask, the irq mask value to wait | ||
348 | * @return: the corresponding tpm_sts value | ||
349 | */ | ||
350 | static u8 interrupt_to_status(u8 irq_mask) | ||
351 | { | ||
352 | u8 status = 0; | ||
353 | |||
354 | if ((irq_mask & TPM_INTF_STS_VALID_INT) == TPM_INTF_STS_VALID_INT) | ||
355 | status |= TPM_STS_VALID; | ||
356 | if ((irq_mask & TPM_INTF_DATA_AVAIL_INT) == TPM_INTF_DATA_AVAIL_INT) | ||
357 | status |= TPM_STS_DATA_AVAIL; | ||
358 | if ((irq_mask & TPM_INTF_CMD_READY_INT) == TPM_INTF_CMD_READY_INT) | ||
359 | status |= TPM_STS_COMMAND_READY; | ||
360 | |||
361 | return status; | ||
362 | } /* status_to_interrupt() */ | ||
363 | |||
358 | /* | 364 | /* |
359 | * wait_for_stat wait for a TPM_STS value | 365 | * wait_for_stat wait for a TPM_STS value |
360 | * @param: chip, the tpm chip description | 366 | * @param: chip, the tpm chip description |
361 | * @param: mask, the value mask to wait | 367 | * @param: mask, the value mask to wait |
362 | * @param: timeout, the timeout | 368 | * @param: timeout, the timeout |
363 | * @param: queue, the wait queue. | 369 | * @param: queue, the wait queue. |
370 | * @param: check_cancel, does the command can be cancelled ? | ||
364 | * @return: the tpm status, 0 if success, -ETIME if timeout is reached. | 371 | * @return: the tpm status, 0 if success, -ETIME if timeout is reached. |
365 | */ | 372 | */ |
366 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | 373 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, |
367 | wait_queue_head_t *queue) | 374 | wait_queue_head_t *queue, bool check_cancel) |
368 | { | 375 | { |
369 | unsigned long stop; | 376 | unsigned long stop; |
370 | long rc; | 377 | int ret; |
371 | u8 status; | 378 | bool canceled = false; |
379 | bool condition; | ||
380 | u32 cur_intrs; | ||
381 | u8 interrupt, status; | ||
382 | struct tpm_stm_dev *tpm_dev; | ||
372 | 383 | ||
373 | if (chip->vendor.irq) { | 384 | tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); |
374 | rc = wait_for_serirq_timeout(chip, ((tpm_stm_i2c_status | 385 | |
375 | (chip) & mask) == | 386 | /* check current status */ |
376 | mask), timeout); | 387 | status = tpm_stm_i2c_status(chip); |
377 | if (rc > 0) | 388 | if ((status & mask) == mask) |
389 | return 0; | ||
390 | |||
391 | stop = jiffies + timeout; | ||
392 | |||
393 | if (chip->vendor.irq) { | ||
394 | cur_intrs = tpm_dev->intrs; | ||
395 | interrupt = clear_interruption(tpm_dev); | ||
396 | enable_irq(chip->vendor.irq); | ||
397 | |||
398 | again: | ||
399 | timeout = stop - jiffies; | ||
400 | if ((long) timeout <= 0) | ||
401 | return -1; | ||
402 | |||
403 | ret = wait_event_interruptible_timeout(*queue, | ||
404 | cur_intrs != tpm_dev->intrs, timeout); | ||
405 | |||
406 | interrupt |= clear_interruption(tpm_dev); | ||
407 | status = interrupt_to_status(interrupt); | ||
408 | condition = wait_for_tpm_stat_cond(chip, mask, | ||
409 | check_cancel, &canceled); | ||
410 | |||
411 | if (ret >= 0 && condition) { | ||
412 | if (canceled) | ||
413 | return -ECANCELED; | ||
378 | return 0; | 414 | return 0; |
415 | } | ||
416 | if (ret == -ERESTARTSYS && freezing(current)) { | ||
417 | clear_thread_flag(TIF_SIGPENDING); | ||
418 | goto again; | ||
419 | } | ||
420 | disable_irq_nosync(chip->vendor.irq); | ||
421 | |||
379 | } else { | 422 | } else { |
380 | stop = jiffies + timeout; | ||
381 | do { | 423 | do { |
382 | msleep(TPM_TIMEOUT); | 424 | msleep(TPM_TIMEOUT); |
383 | status = tpm_stm_i2c_status(chip); | 425 | status = chip->ops->status(chip); |
384 | if ((status & mask) == mask) | 426 | if ((status & mask) == mask) |
385 | return 0; | 427 | return 0; |
386 | } while (time_before(jiffies, stop)); | 428 | } while (time_before(jiffies, stop)); |
387 | } | 429 | } |
430 | |||
388 | return -ETIME; | 431 | return -ETIME; |
389 | } /* wait_for_stat() */ | 432 | } /* wait_for_stat() */ |
390 | 433 | ||
@@ -397,22 +440,24 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | |||
397 | */ | 440 | */ |
398 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | 441 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) |
399 | { | 442 | { |
400 | int size = 0, burstcnt, len; | 443 | int size = 0, burstcnt, len, ret; |
401 | struct i2c_client *client; | 444 | struct tpm_stm_dev *tpm_dev; |
402 | 445 | ||
403 | client = (struct i2c_client *)TPM_VPRIV(chip); | 446 | tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); |
404 | 447 | ||
405 | while (size < count && | 448 | while (size < count && |
406 | wait_for_stat(chip, | 449 | wait_for_stat(chip, |
407 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 450 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
408 | chip->vendor.timeout_c, | 451 | chip->vendor.timeout_c, |
409 | &chip->vendor.read_queue) | 452 | &chip->vendor.read_queue, true) == 0) { |
410 | == 0) { | ||
411 | burstcnt = get_burstcount(chip); | 453 | burstcnt = get_burstcount(chip); |
412 | if (burstcnt < 0) | 454 | if (burstcnt < 0) |
413 | return burstcnt; | 455 | return burstcnt; |
414 | len = min_t(int, burstcnt, count - size); | 456 | len = min_t(int, burstcnt, count - size); |
415 | I2C_READ_DATA(client, TPM_DATA_FIFO, buf + size, len); | 457 | ret = I2C_READ_DATA(tpm_dev, TPM_DATA_FIFO, buf + size, len); |
458 | if (ret < 0) | ||
459 | return ret; | ||
460 | |||
416 | size += len; | 461 | size += len; |
417 | } | 462 | } |
418 | return size; | 463 | return size; |
@@ -427,15 +472,14 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | |||
427 | static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) | 472 | static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) |
428 | { | 473 | { |
429 | struct tpm_chip *chip = dev_id; | 474 | struct tpm_chip *chip = dev_id; |
430 | struct i2c_client *client; | 475 | struct tpm_stm_dev *tpm_dev; |
431 | struct st33zp24_platform_data *pin_infos; | ||
432 | 476 | ||
433 | disable_irq_nosync(irq); | 477 | tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); |
434 | 478 | ||
435 | client = (struct i2c_client *)TPM_VPRIV(chip); | 479 | tpm_dev->intrs++; |
436 | pin_infos = client->dev.platform_data; | 480 | wake_up_interruptible(&chip->vendor.read_queue); |
481 | disable_irq_nosync(chip->vendor.irq); | ||
437 | 482 | ||
438 | complete(&pin_infos->irq_detection); | ||
439 | return IRQ_HANDLED; | 483 | return IRQ_HANDLED; |
440 | } /* tpm_ioserirq_handler() */ | 484 | } /* tpm_ioserirq_handler() */ |
441 | 485 | ||
@@ -457,13 +501,15 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, | |||
457 | int ret; | 501 | int ret; |
458 | u8 data; | 502 | u8 data; |
459 | struct i2c_client *client; | 503 | struct i2c_client *client; |
504 | struct tpm_stm_dev *tpm_dev; | ||
460 | 505 | ||
461 | if (chip == NULL) | 506 | if (!chip) |
462 | return -EBUSY; | 507 | return -EBUSY; |
463 | if (len < TPM_HEADER_SIZE) | 508 | if (len < TPM_HEADER_SIZE) |
464 | return -EBUSY; | 509 | return -EBUSY; |
465 | 510 | ||
466 | client = (struct i2c_client *)TPM_VPRIV(chip); | 511 | tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); |
512 | client = tpm_dev->client; | ||
467 | 513 | ||
468 | client->flags = 0; | 514 | client->flags = 0; |
469 | 515 | ||
@@ -476,7 +522,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, | |||
476 | tpm_stm_i2c_cancel(chip); | 522 | tpm_stm_i2c_cancel(chip); |
477 | if (wait_for_stat | 523 | if (wait_for_stat |
478 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, | 524 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, |
479 | &chip->vendor.int_queue) < 0) { | 525 | &chip->vendor.read_queue, false) < 0) { |
480 | ret = -ETIME; | 526 | ret = -ETIME; |
481 | goto out_err; | 527 | goto out_err; |
482 | } | 528 | } |
@@ -487,7 +533,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, | |||
487 | if (burstcnt < 0) | 533 | if (burstcnt < 0) |
488 | return burstcnt; | 534 | return burstcnt; |
489 | size = min_t(int, len - i - 1, burstcnt); | 535 | size = min_t(int, len - i - 1, burstcnt); |
490 | ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size); | 536 | ret = I2C_WRITE_DATA(tpm_dev, TPM_DATA_FIFO, buf + i, size); |
491 | if (ret < 0) | 537 | if (ret < 0) |
492 | goto out_err; | 538 | goto out_err; |
493 | 539 | ||
@@ -500,7 +546,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, | |||
500 | goto out_err; | 546 | goto out_err; |
501 | } | 547 | } |
502 | 548 | ||
503 | ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + len - 1, 1); | 549 | ret = I2C_WRITE_DATA(tpm_dev, TPM_DATA_FIFO, buf + len - 1, 1); |
504 | if (ret < 0) | 550 | if (ret < 0) |
505 | goto out_err; | 551 | goto out_err; |
506 | 552 | ||
@@ -511,7 +557,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, | |||
511 | } | 557 | } |
512 | 558 | ||
513 | data = TPM_STS_GO; | 559 | data = TPM_STS_GO; |
514 | I2C_WRITE_DATA(client, TPM_STS, &data, 1); | 560 | I2C_WRITE_DATA(tpm_dev, TPM_STS, &data, 1); |
515 | 561 | ||
516 | return len; | 562 | return len; |
517 | out_err: | 563 | out_err: |
@@ -526,7 +572,7 @@ out_err: | |||
526 | * @param: buf, the buffer to store datas. | 572 | * @param: buf, the buffer to store datas. |
527 | * @param: count, the number of bytes to send. | 573 | * @param: count, the number of bytes to send. |
528 | * @return: In case of success the number of bytes received. | 574 | * @return: In case of success the number of bytes received. |
529 | * In other case, a < 0 value describing the issue. | 575 | * In other case, a < 0 value describing the issue. |
530 | */ | 576 | */ |
531 | static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf, | 577 | static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf, |
532 | size_t count) | 578 | size_t count) |
@@ -534,7 +580,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf, | |||
534 | int size = 0; | 580 | int size = 0; |
535 | int expected; | 581 | int expected; |
536 | 582 | ||
537 | if (chip == NULL) | 583 | if (!chip) |
538 | return -EBUSY; | 584 | return -EBUSY; |
539 | 585 | ||
540 | if (count < TPM_HEADER_SIZE) { | 586 | if (count < TPM_HEADER_SIZE) { |
@@ -544,7 +590,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf, | |||
544 | 590 | ||
545 | size = recv_data(chip, buf, TPM_HEADER_SIZE); | 591 | size = recv_data(chip, buf, TPM_HEADER_SIZE); |
546 | if (size < TPM_HEADER_SIZE) { | 592 | if (size < TPM_HEADER_SIZE) { |
547 | dev_err(chip->dev, "Unable to read header\n"); | 593 | dev_err(chip->pdev, "Unable to read header\n"); |
548 | goto out; | 594 | goto out; |
549 | } | 595 | } |
550 | 596 | ||
@@ -555,9 +601,9 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf, | |||
555 | } | 601 | } |
556 | 602 | ||
557 | size += recv_data(chip, &buf[TPM_HEADER_SIZE], | 603 | size += recv_data(chip, &buf[TPM_HEADER_SIZE], |
558 | expected - TPM_HEADER_SIZE); | 604 | expected - TPM_HEADER_SIZE); |
559 | if (size < expected) { | 605 | if (size < expected) { |
560 | dev_err(chip->dev, "Unable to read remainder of result\n"); | 606 | dev_err(chip->pdev, "Unable to read remainder of result\n"); |
561 | size = -ETIME; | 607 | size = -ETIME; |
562 | goto out; | 608 | goto out; |
563 | } | 609 | } |
@@ -568,7 +614,7 @@ out: | |||
568 | return size; | 614 | return size; |
569 | } | 615 | } |
570 | 616 | ||
571 | static bool tpm_st33_i2c_req_canceled(struct tpm_chip *chip, u8 status) | 617 | static bool tpm_stm_i2c_req_canceled(struct tpm_chip *chip, u8 status) |
572 | { | 618 | { |
573 | return (status == TPM_STS_COMMAND_READY); | 619 | return (status == TPM_STS_COMMAND_READY); |
574 | } | 620 | } |
@@ -580,75 +626,134 @@ static const struct tpm_class_ops st_i2c_tpm = { | |||
580 | .status = tpm_stm_i2c_status, | 626 | .status = tpm_stm_i2c_status, |
581 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 627 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
582 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 628 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
583 | .req_canceled = tpm_st33_i2c_req_canceled, | 629 | .req_canceled = tpm_stm_i2c_req_canceled, |
584 | }; | 630 | }; |
585 | 631 | ||
586 | static int interrupts; | 632 | #ifdef CONFIG_OF |
587 | module_param(interrupts, int, 0444); | 633 | static int tpm_stm_i2c_of_request_resources(struct tpm_chip *chip) |
588 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); | 634 | { |
635 | struct device_node *pp; | ||
636 | struct tpm_stm_dev *tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); | ||
637 | struct i2c_client *client = tpm_dev->client; | ||
638 | int gpio; | ||
639 | int ret; | ||
640 | |||
641 | pp = client->dev.of_node; | ||
642 | if (!pp) { | ||
643 | dev_err(chip->pdev, "No platform data\n"); | ||
644 | return -ENODEV; | ||
645 | } | ||
646 | |||
647 | /* Get GPIO from device tree */ | ||
648 | gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0); | ||
649 | if (gpio < 0) { | ||
650 | dev_err(chip->pdev, "Failed to retrieve lpcpd-gpios from dts.\n"); | ||
651 | tpm_dev->io_lpcpd = -1; | ||
652 | /* | ||
653 | * lpcpd pin is not specified. This is not an issue as | ||
654 | * power management can be also managed by TPM specific | ||
655 | * commands. So leave with a success status code. | ||
656 | */ | ||
657 | return 0; | ||
658 | } | ||
659 | /* GPIO request and configuration */ | ||
660 | ret = devm_gpio_request_one(&client->dev, gpio, | ||
661 | GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD"); | ||
662 | if (ret) { | ||
663 | dev_err(chip->pdev, "Failed to request lpcpd pin\n"); | ||
664 | return -ENODEV; | ||
665 | } | ||
666 | tpm_dev->io_lpcpd = gpio; | ||
667 | |||
668 | return 0; | ||
669 | } | ||
670 | #else | ||
671 | static int tpm_stm_i2c_of_request_resources(struct tpm_chip *chip) | ||
672 | { | ||
673 | return -ENODEV; | ||
674 | } | ||
675 | #endif | ||
589 | 676 | ||
590 | static int power_mgt = 1; | 677 | static int tpm_stm_i2c_request_resources(struct i2c_client *client, |
591 | module_param(power_mgt, int, 0444); | 678 | struct tpm_chip *chip) |
592 | MODULE_PARM_DESC(power_mgt, "Power Management"); | 679 | { |
680 | struct st33zp24_platform_data *pdata; | ||
681 | struct tpm_stm_dev *tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); | ||
682 | int ret; | ||
683 | |||
684 | pdata = client->dev.platform_data; | ||
685 | if (!pdata) { | ||
686 | dev_err(chip->pdev, "No platform data\n"); | ||
687 | return -ENODEV; | ||
688 | } | ||
689 | |||
690 | /* store for late use */ | ||
691 | tpm_dev->io_lpcpd = pdata->io_lpcpd; | ||
692 | |||
693 | if (gpio_is_valid(pdata->io_lpcpd)) { | ||
694 | ret = devm_gpio_request_one(&client->dev, | ||
695 | pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH, | ||
696 | "TPM IO_LPCPD"); | ||
697 | if (ret) { | ||
698 | dev_err(chip->pdev, "%s : reset gpio_request failed\n", | ||
699 | __FILE__); | ||
700 | return ret; | ||
701 | } | ||
702 | } | ||
703 | |||
704 | return 0; | ||
705 | } | ||
593 | 706 | ||
594 | /* | 707 | /* |
595 | * tpm_st33_i2c_probe initialize the TPM device | 708 | * tpm_stm_i2c_probe initialize the TPM device |
596 | * @param: client, the i2c_client drescription (TPM I2C description). | 709 | * @param: client, the i2c_client drescription (TPM I2C description). |
597 | * @param: id, the i2c_device_id struct. | 710 | * @param: id, the i2c_device_id struct. |
598 | * @return: 0 in case of success. | 711 | * @return: 0 in case of success. |
599 | * -1 in other case. | 712 | * -1 in other case. |
600 | */ | 713 | */ |
601 | static int | 714 | static int |
602 | tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) | 715 | tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) |
603 | { | 716 | { |
604 | int err; | 717 | int ret; |
605 | u8 intmask; | 718 | u8 intmask = 0; |
606 | struct tpm_chip *chip; | 719 | struct tpm_chip *chip; |
607 | struct st33zp24_platform_data *platform_data; | 720 | struct st33zp24_platform_data *platform_data; |
721 | struct tpm_stm_dev *tpm_dev; | ||
608 | 722 | ||
609 | if (client == NULL) { | 723 | if (!client) { |
610 | pr_info("%s: i2c client is NULL. Device not accessible.\n", | 724 | pr_info("%s: i2c client is NULL. Device not accessible.\n", |
611 | __func__); | 725 | __func__); |
612 | err = -ENODEV; | 726 | return -ENODEV; |
613 | goto end; | ||
614 | } | 727 | } |
615 | 728 | ||
616 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | 729 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
617 | dev_info(&client->dev, "client not i2c capable\n"); | 730 | dev_info(&client->dev, "client not i2c capable\n"); |
618 | err = -ENODEV; | 731 | return -ENODEV; |
619 | goto end; | ||
620 | } | 732 | } |
621 | 733 | ||
622 | chip = tpm_register_hardware(&client->dev, &st_i2c_tpm); | 734 | tpm_dev = devm_kzalloc(&client->dev, sizeof(struct tpm_stm_dev), |
623 | if (!chip) { | 735 | GFP_KERNEL); |
624 | dev_info(&client->dev, "fail chip\n"); | 736 | if (!tpm_dev) |
625 | err = -ENODEV; | 737 | return -ENOMEM; |
626 | goto end; | ||
627 | } | ||
628 | 738 | ||
629 | platform_data = client->dev.platform_data; | 739 | chip = tpmm_chip_alloc(&client->dev, &st_i2c_tpm); |
740 | if (IS_ERR(chip)) | ||
741 | return PTR_ERR(chip); | ||
630 | 742 | ||
631 | if (!platform_data) { | 743 | TPM_VPRIV(chip) = tpm_dev; |
632 | dev_info(&client->dev, "chip not available\n"); | 744 | tpm_dev->client = client; |
633 | err = -ENODEV; | ||
634 | goto _tpm_clean_answer; | ||
635 | } | ||
636 | 745 | ||
637 | platform_data->tpm_i2c_buffer[0] = | 746 | platform_data = client->dev.platform_data; |
638 | kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); | 747 | if (!platform_data && client->dev.of_node) { |
639 | if (platform_data->tpm_i2c_buffer[0] == NULL) { | 748 | ret = tpm_stm_i2c_of_request_resources(chip); |
640 | err = -ENOMEM; | 749 | if (ret) |
641 | goto _tpm_clean_answer; | 750 | goto _tpm_clean_answer; |
642 | } | 751 | } else if (platform_data) { |
643 | platform_data->tpm_i2c_buffer[1] = | 752 | ret = tpm_stm_i2c_request_resources(client, chip); |
644 | kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); | 753 | if (ret) |
645 | if (platform_data->tpm_i2c_buffer[1] == NULL) { | 754 | goto _tpm_clean_answer; |
646 | err = -ENOMEM; | ||
647 | goto _tpm_clean_response1; | ||
648 | } | 755 | } |
649 | 756 | ||
650 | TPM_VPRIV(chip) = client; | ||
651 | |||
652 | chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 757 | chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); |
653 | chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); | 758 | chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); |
654 | chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 759 | chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); |
@@ -656,59 +761,44 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
656 | 761 | ||
657 | chip->vendor.locality = LOCALITY0; | 762 | chip->vendor.locality = LOCALITY0; |
658 | 763 | ||
659 | if (power_mgt) { | 764 | if (client->irq) { |
660 | err = gpio_request(platform_data->io_lpcpd, "TPM IO_LPCPD"); | 765 | /* INTERRUPT Setup */ |
661 | if (err) | 766 | init_waitqueue_head(&chip->vendor.read_queue); |
662 | goto _gpio_init1; | 767 | tpm_dev->intrs = 0; |
663 | gpio_set_value(platform_data->io_lpcpd, 1); | ||
664 | } | ||
665 | 768 | ||
666 | if (interrupts) { | ||
667 | init_completion(&platform_data->irq_detection); | ||
668 | if (request_locality(chip) != LOCALITY0) { | 769 | if (request_locality(chip) != LOCALITY0) { |
669 | err = -ENODEV; | 770 | ret = -ENODEV; |
670 | goto _tpm_clean_response2; | 771 | goto _tpm_clean_answer; |
671 | } | 772 | } |
672 | err = gpio_request(platform_data->io_serirq, "TPM IO_SERIRQ"); | ||
673 | if (err) | ||
674 | goto _gpio_init2; | ||
675 | 773 | ||
676 | clear_interruption(client); | 774 | clear_interruption(tpm_dev); |
677 | err = request_irq(gpio_to_irq(platform_data->io_serirq), | 775 | ret = devm_request_irq(&client->dev, client->irq, |
678 | &tpm_ioserirq_handler, | 776 | tpm_ioserirq_handler, |
679 | IRQF_TRIGGER_HIGH, | 777 | IRQF_TRIGGER_HIGH, |
680 | "TPM SERIRQ management", chip); | 778 | "TPM SERIRQ management", chip); |
681 | if (err < 0) { | 779 | if (ret < 0) { |
682 | dev_err(chip->dev , "TPM SERIRQ signals %d not available\n", | 780 | dev_err(chip->pdev, "TPM SERIRQ signals %d not available\n", |
683 | gpio_to_irq(platform_data->io_serirq)); | 781 | client->irq); |
684 | goto _irq_set; | 782 | goto _tpm_clean_answer; |
685 | } | 783 | } |
686 | 784 | ||
687 | err = I2C_READ_DATA(client, TPM_INT_ENABLE, &intmask, 1); | ||
688 | if (err < 0) | ||
689 | goto _irq_set; | ||
690 | |||
691 | intmask |= TPM_INTF_CMD_READY_INT | 785 | intmask |= TPM_INTF_CMD_READY_INT |
692 | | TPM_INTF_FIFO_AVALAIBLE_INT | ||
693 | | TPM_INTF_WAKE_UP_READY_INT | ||
694 | | TPM_INTF_LOCALITY_CHANGE_INT | ||
695 | | TPM_INTF_STS_VALID_INT | 786 | | TPM_INTF_STS_VALID_INT |
696 | | TPM_INTF_DATA_AVAIL_INT; | 787 | | TPM_INTF_DATA_AVAIL_INT; |
697 | 788 | ||
698 | err = I2C_WRITE_DATA(client, TPM_INT_ENABLE, &intmask, 1); | 789 | ret = I2C_WRITE_DATA(tpm_dev, TPM_INT_ENABLE, &intmask, 1); |
699 | if (err < 0) | 790 | if (ret < 0) |
700 | goto _irq_set; | 791 | goto _tpm_clean_answer; |
701 | 792 | ||
702 | intmask = TPM_GLOBAL_INT_ENABLE; | 793 | intmask = TPM_GLOBAL_INT_ENABLE; |
703 | err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1); | 794 | ret = I2C_WRITE_DATA(tpm_dev, (TPM_INT_ENABLE + 3), |
704 | if (err < 0) | 795 | &intmask, 1); |
705 | goto _irq_set; | 796 | if (ret < 0) |
797 | goto _tpm_clean_answer; | ||
706 | 798 | ||
707 | err = I2C_READ_DATA(client, TPM_INT_STATUS, &intmask, 1); | 799 | chip->vendor.irq = client->irq; |
708 | if (err < 0) | ||
709 | goto _irq_set; | ||
710 | 800 | ||
711 | chip->vendor.irq = interrupts; | 801 | disable_irq_nosync(chip->vendor.irq); |
712 | 802 | ||
713 | tpm_gen_interrupt(chip); | 803 | tpm_gen_interrupt(chip); |
714 | } | 804 | } |
@@ -716,130 +806,106 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
716 | tpm_get_timeouts(chip); | 806 | tpm_get_timeouts(chip); |
717 | tpm_do_selftest(chip); | 807 | tpm_do_selftest(chip); |
718 | 808 | ||
719 | dev_info(chip->dev, "TPM I2C Initialized\n"); | 809 | return tpm_chip_register(chip); |
720 | return 0; | ||
721 | _irq_set: | ||
722 | free_irq(gpio_to_irq(platform_data->io_serirq), (void *)chip); | ||
723 | _gpio_init2: | ||
724 | if (interrupts) | ||
725 | gpio_free(platform_data->io_serirq); | ||
726 | _gpio_init1: | ||
727 | if (power_mgt) | ||
728 | gpio_free(platform_data->io_lpcpd); | ||
729 | _tpm_clean_response2: | ||
730 | kzfree(platform_data->tpm_i2c_buffer[1]); | ||
731 | platform_data->tpm_i2c_buffer[1] = NULL; | ||
732 | _tpm_clean_response1: | ||
733 | kzfree(platform_data->tpm_i2c_buffer[0]); | ||
734 | platform_data->tpm_i2c_buffer[0] = NULL; | ||
735 | _tpm_clean_answer: | 810 | _tpm_clean_answer: |
736 | tpm_remove_hardware(chip->dev); | 811 | dev_info(chip->pdev, "TPM I2C initialisation fail\n"); |
737 | end: | 812 | return ret; |
738 | pr_info("TPM I2C initialisation fail\n"); | ||
739 | return err; | ||
740 | } | 813 | } |
741 | 814 | ||
742 | /* | 815 | /* |
743 | * tpm_st33_i2c_remove remove the TPM device | 816 | * tpm_stm_i2c_remove remove the TPM device |
744 | * @param: client, the i2c_client drescription (TPM I2C description). | 817 | * @param: client, the i2c_client description (TPM I2C description). |
745 | clear_bit(0, &chip->is_open); | ||
746 | * @return: 0 in case of success. | 818 | * @return: 0 in case of success. |
747 | */ | 819 | */ |
748 | static int tpm_st33_i2c_remove(struct i2c_client *client) | 820 | static int tpm_stm_i2c_remove(struct i2c_client *client) |
749 | { | 821 | { |
750 | struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client); | 822 | struct tpm_chip *chip = |
751 | struct st33zp24_platform_data *pin_infos = | 823 | (struct tpm_chip *) i2c_get_clientdata(client); |
752 | ((struct i2c_client *)TPM_VPRIV(chip))->dev.platform_data; | ||
753 | |||
754 | if (pin_infos != NULL) { | ||
755 | free_irq(pin_infos->io_serirq, chip); | ||
756 | |||
757 | gpio_free(pin_infos->io_serirq); | ||
758 | gpio_free(pin_infos->io_lpcpd); | ||
759 | |||
760 | tpm_remove_hardware(chip->dev); | ||
761 | 824 | ||
762 | if (pin_infos->tpm_i2c_buffer[1] != NULL) { | 825 | if (chip) |
763 | kzfree(pin_infos->tpm_i2c_buffer[1]); | 826 | tpm_chip_unregister(chip); |
764 | pin_infos->tpm_i2c_buffer[1] = NULL; | ||
765 | } | ||
766 | if (pin_infos->tpm_i2c_buffer[0] != NULL) { | ||
767 | kzfree(pin_infos->tpm_i2c_buffer[0]); | ||
768 | pin_infos->tpm_i2c_buffer[0] = NULL; | ||
769 | } | ||
770 | } | ||
771 | 827 | ||
772 | return 0; | 828 | return 0; |
773 | } | 829 | } |
774 | 830 | ||
775 | #ifdef CONFIG_PM_SLEEP | 831 | #ifdef CONFIG_PM_SLEEP |
776 | /* | 832 | /* |
777 | * tpm_st33_i2c_pm_suspend suspend the TPM device | 833 | * tpm_stm_i2c_pm_suspend suspend the TPM device |
778 | * @param: client, the i2c_client drescription (TPM I2C description). | 834 | * @param: client, the i2c_client drescription (TPM I2C description). |
779 | * @param: mesg, the power management message. | 835 | * @param: mesg, the power management message. |
780 | * @return: 0 in case of success. | 836 | * @return: 0 in case of success. |
781 | */ | 837 | */ |
782 | static int tpm_st33_i2c_pm_suspend(struct device *dev) | 838 | static int tpm_stm_i2c_pm_suspend(struct device *dev) |
783 | { | 839 | { |
784 | struct st33zp24_platform_data *pin_infos = dev->platform_data; | 840 | struct st33zp24_platform_data *pin_infos = dev->platform_data; |
785 | int ret = 0; | 841 | int ret = 0; |
786 | 842 | ||
787 | if (power_mgt) { | 843 | if (gpio_is_valid(pin_infos->io_lpcpd)) |
788 | gpio_set_value(pin_infos->io_lpcpd, 0); | 844 | gpio_set_value(pin_infos->io_lpcpd, 0); |
789 | } else { | 845 | else |
790 | ret = tpm_pm_suspend(dev); | 846 | ret = tpm_pm_suspend(dev); |
791 | } | 847 | |
792 | return ret; | 848 | return ret; |
793 | } /* tpm_st33_i2c_suspend() */ | 849 | } /* tpm_stm_i2c_suspend() */ |
794 | 850 | ||
795 | /* | 851 | /* |
796 | * tpm_st33_i2c_pm_resume resume the TPM device | 852 | * tpm_stm_i2c_pm_resume resume the TPM device |
797 | * @param: client, the i2c_client drescription (TPM I2C description). | 853 | * @param: client, the i2c_client drescription (TPM I2C description). |
798 | * @return: 0 in case of success. | 854 | * @return: 0 in case of success. |
799 | */ | 855 | */ |
800 | static int tpm_st33_i2c_pm_resume(struct device *dev) | 856 | static int tpm_stm_i2c_pm_resume(struct device *dev) |
801 | { | 857 | { |
802 | struct tpm_chip *chip = dev_get_drvdata(dev); | 858 | struct tpm_chip *chip = dev_get_drvdata(dev); |
803 | struct st33zp24_platform_data *pin_infos = dev->platform_data; | 859 | struct st33zp24_platform_data *pin_infos = dev->platform_data; |
804 | 860 | ||
805 | int ret = 0; | 861 | int ret = 0; |
806 | 862 | ||
807 | if (power_mgt) { | 863 | if (gpio_is_valid(pin_infos->io_lpcpd)) { |
808 | gpio_set_value(pin_infos->io_lpcpd, 1); | 864 | gpio_set_value(pin_infos->io_lpcpd, 1); |
809 | ret = wait_for_serirq_timeout(chip, | 865 | ret = wait_for_stat(chip, |
810 | (chip->ops->status(chip) & | 866 | TPM_STS_VALID, chip->vendor.timeout_b, |
811 | TPM_STS_VALID) == TPM_STS_VALID, | 867 | &chip->vendor.read_queue, false); |
812 | chip->vendor.timeout_b); | ||
813 | } else { | 868 | } else { |
814 | ret = tpm_pm_resume(dev); | 869 | ret = tpm_pm_resume(dev); |
815 | if (!ret) | 870 | if (!ret) |
816 | tpm_do_selftest(chip); | 871 | tpm_do_selftest(chip); |
817 | } | 872 | } |
818 | return ret; | 873 | return ret; |
819 | } /* tpm_st33_i2c_pm_resume() */ | 874 | } /* tpm_stm_i2c_pm_resume() */ |
820 | #endif | 875 | #endif |
821 | 876 | ||
822 | static const struct i2c_device_id tpm_st33_i2c_id[] = { | 877 | static const struct i2c_device_id tpm_stm_i2c_id[] = { |
823 | {TPM_ST33_I2C, 0}, | 878 | {TPM_ST33_I2C, 0}, |
824 | {} | 879 | {} |
825 | }; | 880 | }; |
826 | MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id); | 881 | MODULE_DEVICE_TABLE(i2c, tpm_stm_i2c_id); |
827 | static SIMPLE_DEV_PM_OPS(tpm_st33_i2c_ops, tpm_st33_i2c_pm_suspend, | 882 | |
828 | tpm_st33_i2c_pm_resume); | 883 | #ifdef CONFIG_OF |
829 | static struct i2c_driver tpm_st33_i2c_driver = { | 884 | static const struct of_device_id of_st33zp24_i2c_match[] = { |
885 | { .compatible = "st,st33zp24-i2c", }, | ||
886 | {} | ||
887 | }; | ||
888 | MODULE_DEVICE_TABLE(of, of_st33zp24_i2c_match); | ||
889 | #endif | ||
890 | |||
891 | static SIMPLE_DEV_PM_OPS(tpm_stm_i2c_ops, tpm_stm_i2c_pm_suspend, | ||
892 | tpm_stm_i2c_pm_resume); | ||
893 | |||
894 | static struct i2c_driver tpm_stm_i2c_driver = { | ||
830 | .driver = { | 895 | .driver = { |
831 | .owner = THIS_MODULE, | 896 | .owner = THIS_MODULE, |
832 | .name = TPM_ST33_I2C, | 897 | .name = TPM_ST33_I2C, |
833 | .pm = &tpm_st33_i2c_ops, | 898 | .pm = &tpm_stm_i2c_ops, |
834 | }, | 899 | .of_match_table = of_match_ptr(of_st33zp24_i2c_match), |
835 | .probe = tpm_st33_i2c_probe, | 900 | }, |
836 | .remove = tpm_st33_i2c_remove, | 901 | .probe = tpm_stm_i2c_probe, |
837 | .id_table = tpm_st33_i2c_id | 902 | .remove = tpm_stm_i2c_remove, |
903 | .id_table = tpm_stm_i2c_id | ||
838 | }; | 904 | }; |
839 | 905 | ||
840 | module_i2c_driver(tpm_st33_i2c_driver); | 906 | module_i2c_driver(tpm_stm_i2c_driver); |
841 | 907 | ||
842 | MODULE_AUTHOR("Christophe Ricard (tpmsupport@st.com)"); | 908 | MODULE_AUTHOR("Christophe Ricard (tpmsupport@st.com)"); |
843 | MODULE_DESCRIPTION("STM TPM I2C ST33 Driver"); | 909 | MODULE_DESCRIPTION("STM TPM I2C ST33 Driver"); |
844 | MODULE_VERSION("1.2.0"); | 910 | MODULE_VERSION("1.2.1"); |
845 | MODULE_LICENSE("GPL"); | 911 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index af74c57e5090..0840347e251c 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2012 IBM Corporation | 2 | * Copyright (C) 2012 IBM Corporation |
3 | * | 3 | * |
4 | * Author: Ashley Lai <adlai@us.ibm.com> | 4 | * Author: Ashley Lai <ashleydlai@gmail.com> |
5 | * | 5 | * |
6 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | 6 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> |
7 | * | 7 | * |
@@ -270,8 +270,11 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm) | |||
270 | static int tpm_ibmvtpm_remove(struct vio_dev *vdev) | 270 | static int tpm_ibmvtpm_remove(struct vio_dev *vdev) |
271 | { | 271 | { |
272 | struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); | 272 | struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); |
273 | struct tpm_chip *chip = dev_get_drvdata(ibmvtpm->dev); | ||
273 | int rc = 0; | 274 | int rc = 0; |
274 | 275 | ||
276 | tpm_chip_unregister(chip); | ||
277 | |||
275 | free_irq(vdev->irq, ibmvtpm); | 278 | free_irq(vdev->irq, ibmvtpm); |
276 | 279 | ||
277 | do { | 280 | do { |
@@ -290,8 +293,6 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) | |||
290 | kfree(ibmvtpm->rtce_buf); | 293 | kfree(ibmvtpm->rtce_buf); |
291 | } | 294 | } |
292 | 295 | ||
293 | tpm_remove_hardware(ibmvtpm->dev); | ||
294 | |||
295 | kfree(ibmvtpm); | 296 | kfree(ibmvtpm); |
296 | 297 | ||
297 | return 0; | 298 | return 0; |
@@ -307,6 +308,14 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) | |||
307 | static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev) | 308 | static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev) |
308 | { | 309 | { |
309 | struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); | 310 | struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); |
311 | |||
312 | /* ibmvtpm initializes at probe time, so the data we are | ||
313 | * asking for may not be set yet. Estimate that 4K required | ||
314 | * for TCE-mapped buffer in addition to CRQ. | ||
315 | */ | ||
316 | if (!ibmvtpm) | ||
317 | return CRQ_RES_BUF_SIZE + PAGE_SIZE; | ||
318 | |||
310 | return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size; | 319 | return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size; |
311 | } | 320 | } |
312 | 321 | ||
@@ -555,11 +564,9 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, | |||
555 | struct tpm_chip *chip; | 564 | struct tpm_chip *chip; |
556 | int rc = -ENOMEM, rc1; | 565 | int rc = -ENOMEM, rc1; |
557 | 566 | ||
558 | chip = tpm_register_hardware(dev, &tpm_ibmvtpm); | 567 | chip = tpmm_chip_alloc(dev, &tpm_ibmvtpm); |
559 | if (!chip) { | 568 | if (IS_ERR(chip)) |
560 | dev_err(dev, "tpm_register_hardware failed\n"); | 569 | return PTR_ERR(chip); |
561 | return -ENODEV; | ||
562 | } | ||
563 | 570 | ||
564 | ibmvtpm = kzalloc(sizeof(struct ibmvtpm_dev), GFP_KERNEL); | 571 | ibmvtpm = kzalloc(sizeof(struct ibmvtpm_dev), GFP_KERNEL); |
565 | if (!ibmvtpm) { | 572 | if (!ibmvtpm) { |
@@ -629,7 +636,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, | |||
629 | if (rc) | 636 | if (rc) |
630 | goto init_irq_cleanup; | 637 | goto init_irq_cleanup; |
631 | 638 | ||
632 | return rc; | 639 | return tpm_chip_register(chip); |
633 | init_irq_cleanup: | 640 | init_irq_cleanup: |
634 | do { | 641 | do { |
635 | rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address); | 642 | rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address); |
@@ -644,8 +651,6 @@ cleanup: | |||
644 | kfree(ibmvtpm); | 651 | kfree(ibmvtpm); |
645 | } | 652 | } |
646 | 653 | ||
647 | tpm_remove_hardware(dev); | ||
648 | |||
649 | return rc; | 654 | return rc; |
650 | } | 655 | } |
651 | 656 | ||
diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h index bd82a791f995..f595f14426bf 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.h +++ b/drivers/char/tpm/tpm_ibmvtpm.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2012 IBM Corporation | 2 | * Copyright (C) 2012 IBM Corporation |
3 | * | 3 | * |
4 | * Author: Ashley Lai <adlai@us.ibm.com> | 4 | * Author: Ashley Lai <ashleydlai@gmail.com> |
5 | * | 5 | * |
6 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | 6 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> |
7 | * | 7 | * |
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index dc0a2554034e..6d492132ad2b 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
@@ -195,9 +195,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) | |||
195 | } | 195 | } |
196 | if (i == TPM_MAX_TRIES) { /* timeout occurs */ | 196 | if (i == TPM_MAX_TRIES) { /* timeout occurs */ |
197 | if (wait_for_bit == STAT_XFE) | 197 | if (wait_for_bit == STAT_XFE) |
198 | dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n"); | 198 | dev_err(chip->pdev, "Timeout in wait(STAT_XFE)\n"); |
199 | if (wait_for_bit == STAT_RDA) | 199 | if (wait_for_bit == STAT_RDA) |
200 | dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n"); | 200 | dev_err(chip->pdev, "Timeout in wait(STAT_RDA)\n"); |
201 | return -EIO; | 201 | return -EIO; |
202 | } | 202 | } |
203 | return 0; | 203 | return 0; |
@@ -220,7 +220,7 @@ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) | |||
220 | static void tpm_wtx(struct tpm_chip *chip) | 220 | static void tpm_wtx(struct tpm_chip *chip) |
221 | { | 221 | { |
222 | number_of_wtx++; | 222 | number_of_wtx++; |
223 | dev_info(chip->dev, "Granting WTX (%02d / %02d)\n", | 223 | dev_info(chip->pdev, "Granting WTX (%02d / %02d)\n", |
224 | number_of_wtx, TPM_MAX_WTX_PACKAGES); | 224 | number_of_wtx, TPM_MAX_WTX_PACKAGES); |
225 | wait_and_send(chip, TPM_VL_VER); | 225 | wait_and_send(chip, TPM_VL_VER); |
226 | wait_and_send(chip, TPM_CTRL_WTX); | 226 | wait_and_send(chip, TPM_CTRL_WTX); |
@@ -231,7 +231,7 @@ static void tpm_wtx(struct tpm_chip *chip) | |||
231 | 231 | ||
232 | static void tpm_wtx_abort(struct tpm_chip *chip) | 232 | static void tpm_wtx_abort(struct tpm_chip *chip) |
233 | { | 233 | { |
234 | dev_info(chip->dev, "Aborting WTX\n"); | 234 | dev_info(chip->pdev, "Aborting WTX\n"); |
235 | wait_and_send(chip, TPM_VL_VER); | 235 | wait_and_send(chip, TPM_VL_VER); |
236 | wait_and_send(chip, TPM_CTRL_WTX_ABORT); | 236 | wait_and_send(chip, TPM_CTRL_WTX_ABORT); |
237 | wait_and_send(chip, 0x00); | 237 | wait_and_send(chip, 0x00); |
@@ -257,7 +257,7 @@ recv_begin: | |||
257 | } | 257 | } |
258 | 258 | ||
259 | if (buf[0] != TPM_VL_VER) { | 259 | if (buf[0] != TPM_VL_VER) { |
260 | dev_err(chip->dev, | 260 | dev_err(chip->pdev, |
261 | "Wrong transport protocol implementation!\n"); | 261 | "Wrong transport protocol implementation!\n"); |
262 | return -EIO; | 262 | return -EIO; |
263 | } | 263 | } |
@@ -272,7 +272,7 @@ recv_begin: | |||
272 | } | 272 | } |
273 | 273 | ||
274 | if ((size == 0x6D00) && (buf[1] == 0x80)) { | 274 | if ((size == 0x6D00) && (buf[1] == 0x80)) { |
275 | dev_err(chip->dev, "Error handling on vendor layer!\n"); | 275 | dev_err(chip->pdev, "Error handling on vendor layer!\n"); |
276 | return -EIO; | 276 | return -EIO; |
277 | } | 277 | } |
278 | 278 | ||
@@ -284,7 +284,7 @@ recv_begin: | |||
284 | } | 284 | } |
285 | 285 | ||
286 | if (buf[1] == TPM_CTRL_WTX) { | 286 | if (buf[1] == TPM_CTRL_WTX) { |
287 | dev_info(chip->dev, "WTX-package received\n"); | 287 | dev_info(chip->pdev, "WTX-package received\n"); |
288 | if (number_of_wtx < TPM_MAX_WTX_PACKAGES) { | 288 | if (number_of_wtx < TPM_MAX_WTX_PACKAGES) { |
289 | tpm_wtx(chip); | 289 | tpm_wtx(chip); |
290 | goto recv_begin; | 290 | goto recv_begin; |
@@ -295,14 +295,14 @@ recv_begin: | |||
295 | } | 295 | } |
296 | 296 | ||
297 | if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) { | 297 | if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) { |
298 | dev_info(chip->dev, "WTX-abort acknowledged\n"); | 298 | dev_info(chip->pdev, "WTX-abort acknowledged\n"); |
299 | return size; | 299 | return size; |
300 | } | 300 | } |
301 | 301 | ||
302 | if (buf[1] == TPM_CTRL_ERROR) { | 302 | if (buf[1] == TPM_CTRL_ERROR) { |
303 | dev_err(chip->dev, "ERROR-package received:\n"); | 303 | dev_err(chip->pdev, "ERROR-package received:\n"); |
304 | if (buf[4] == TPM_INF_NAK) | 304 | if (buf[4] == TPM_INF_NAK) |
305 | dev_err(chip->dev, | 305 | dev_err(chip->pdev, |
306 | "-> Negative acknowledgement" | 306 | "-> Negative acknowledgement" |
307 | " - retransmit command!\n"); | 307 | " - retransmit command!\n"); |
308 | return -EIO; | 308 | return -EIO; |
@@ -321,7 +321,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
321 | 321 | ||
322 | ret = empty_fifo(chip, 1); | 322 | ret = empty_fifo(chip, 1); |
323 | if (ret) { | 323 | if (ret) { |
324 | dev_err(chip->dev, "Timeout while clearing FIFO\n"); | 324 | dev_err(chip->pdev, "Timeout while clearing FIFO\n"); |
325 | return -EIO; | 325 | return -EIO; |
326 | } | 326 | } |
327 | 327 | ||
@@ -546,7 +546,14 @@ static int tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
546 | vendorid[0], vendorid[1], | 546 | vendorid[0], vendorid[1], |
547 | productid[0], productid[1], chipname); | 547 | productid[0], productid[1], chipname); |
548 | 548 | ||
549 | if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) | 549 | chip = tpmm_chip_alloc(&dev->dev, &tpm_inf); |
550 | if (IS_ERR(chip)) { | ||
551 | rc = PTR_ERR(chip); | ||
552 | goto err_release_region; | ||
553 | } | ||
554 | |||
555 | rc = tpm_chip_register(chip); | ||
556 | if (rc) | ||
550 | goto err_release_region; | 557 | goto err_release_region; |
551 | 558 | ||
552 | return 0; | 559 | return 0; |
@@ -572,17 +579,15 @@ static void tpm_inf_pnp_remove(struct pnp_dev *dev) | |||
572 | { | 579 | { |
573 | struct tpm_chip *chip = pnp_get_drvdata(dev); | 580 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
574 | 581 | ||
575 | if (chip) { | 582 | tpm_chip_unregister(chip); |
576 | if (tpm_dev.iotype == TPM_INF_IO_PORT) { | 583 | |
577 | release_region(tpm_dev.data_regs, tpm_dev.data_size); | 584 | if (tpm_dev.iotype == TPM_INF_IO_PORT) { |
578 | release_region(tpm_dev.config_port, | 585 | release_region(tpm_dev.data_regs, tpm_dev.data_size); |
579 | tpm_dev.config_size); | 586 | release_region(tpm_dev.config_port, |
580 | } else { | 587 | tpm_dev.config_size); |
581 | iounmap(tpm_dev.mem_base); | 588 | } else { |
582 | release_mem_region(tpm_dev.map_base, tpm_dev.map_size); | 589 | iounmap(tpm_dev.mem_base); |
583 | } | 590 | release_mem_region(tpm_dev.map_base, tpm_dev.map_size); |
584 | tpm_dev_vendor_release(chip); | ||
585 | tpm_remove_hardware(chip->dev); | ||
586 | } | 591 | } |
587 | } | 592 | } |
588 | 593 | ||
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 4d0a17ea8cde..289389ecef84 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
@@ -113,7 +113,7 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) | |||
113 | } | 113 | } |
114 | while (time_before(jiffies, stop)); | 114 | while (time_before(jiffies, stop)); |
115 | 115 | ||
116 | dev_info(chip->dev, "wait for ready failed\n"); | 116 | dev_info(chip->pdev, "wait for ready failed\n"); |
117 | return -EBUSY; | 117 | return -EBUSY; |
118 | } | 118 | } |
119 | 119 | ||
@@ -129,12 +129,12 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) | |||
129 | return -EIO; | 129 | return -EIO; |
130 | 130 | ||
131 | if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) { | 131 | if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) { |
132 | dev_err(chip->dev, "F0 timeout\n"); | 132 | dev_err(chip->pdev, "F0 timeout\n"); |
133 | return -EIO; | 133 | return -EIO; |
134 | } | 134 | } |
135 | if ((data = | 135 | if ((data = |
136 | inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { | 136 | inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { |
137 | dev_err(chip->dev, "not in normal mode (0x%x)\n", | 137 | dev_err(chip->pdev, "not in normal mode (0x%x)\n", |
138 | data); | 138 | data); |
139 | return -EIO; | 139 | return -EIO; |
140 | } | 140 | } |
@@ -143,7 +143,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) | |||
143 | for (p = buffer; p < &buffer[count]; p++) { | 143 | for (p = buffer; p < &buffer[count]; p++) { |
144 | if (wait_for_stat | 144 | if (wait_for_stat |
145 | (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) { | 145 | (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) { |
146 | dev_err(chip->dev, | 146 | dev_err(chip->pdev, |
147 | "OBF timeout (while reading data)\n"); | 147 | "OBF timeout (while reading data)\n"); |
148 | return -EIO; | 148 | return -EIO; |
149 | } | 149 | } |
@@ -154,11 +154,11 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) | |||
154 | 154 | ||
155 | if ((data & NSC_STATUS_F0) == 0 && | 155 | if ((data & NSC_STATUS_F0) == 0 && |
156 | (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) { | 156 | (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) { |
157 | dev_err(chip->dev, "F0 not set\n"); | 157 | dev_err(chip->pdev, "F0 not set\n"); |
158 | return -EIO; | 158 | return -EIO; |
159 | } | 159 | } |
160 | if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { | 160 | if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { |
161 | dev_err(chip->dev, | 161 | dev_err(chip->pdev, |
162 | "expected end of command(0x%x)\n", data); | 162 | "expected end of command(0x%x)\n", data); |
163 | return -EIO; | 163 | return -EIO; |
164 | } | 164 | } |
@@ -189,19 +189,19 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
189 | return -EIO; | 189 | return -EIO; |
190 | 190 | ||
191 | if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { | 191 | if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { |
192 | dev_err(chip->dev, "IBF timeout\n"); | 192 | dev_err(chip->pdev, "IBF timeout\n"); |
193 | return -EIO; | 193 | return -EIO; |
194 | } | 194 | } |
195 | 195 | ||
196 | outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); | 196 | outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); |
197 | if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { | 197 | if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { |
198 | dev_err(chip->dev, "IBR timeout\n"); | 198 | dev_err(chip->pdev, "IBR timeout\n"); |
199 | return -EIO; | 199 | return -EIO; |
200 | } | 200 | } |
201 | 201 | ||
202 | for (i = 0; i < count; i++) { | 202 | for (i = 0; i < count; i++) { |
203 | if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { | 203 | if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { |
204 | dev_err(chip->dev, | 204 | dev_err(chip->pdev, |
205 | "IBF timeout (while writing data)\n"); | 205 | "IBF timeout (while writing data)\n"); |
206 | return -EIO; | 206 | return -EIO; |
207 | } | 207 | } |
@@ -209,7 +209,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
209 | } | 209 | } |
210 | 210 | ||
211 | if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { | 211 | if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { |
212 | dev_err(chip->dev, "IBF timeout\n"); | 212 | dev_err(chip->pdev, "IBF timeout\n"); |
213 | return -EIO; | 213 | return -EIO; |
214 | } | 214 | } |
215 | outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); | 215 | outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); |
@@ -247,10 +247,9 @@ static struct platform_device *pdev = NULL; | |||
247 | static void tpm_nsc_remove(struct device *dev) | 247 | static void tpm_nsc_remove(struct device *dev) |
248 | { | 248 | { |
249 | struct tpm_chip *chip = dev_get_drvdata(dev); | 249 | struct tpm_chip *chip = dev_get_drvdata(dev); |
250 | if ( chip ) { | 250 | |
251 | release_region(chip->vendor.base, 2); | 251 | tpm_chip_unregister(chip); |
252 | tpm_remove_hardware(chip->dev); | 252 | release_region(chip->vendor.base, 2); |
253 | } | ||
254 | } | 253 | } |
255 | 254 | ||
256 | static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume); | 255 | static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume); |
@@ -307,11 +306,16 @@ static int __init init_nsc(void) | |||
307 | goto err_del_dev; | 306 | goto err_del_dev; |
308 | } | 307 | } |
309 | 308 | ||
310 | if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { | 309 | chip = tpmm_chip_alloc(&pdev->dev, &tpm_nsc); |
310 | if (IS_ERR(chip)) { | ||
311 | rc = -ENODEV; | 311 | rc = -ENODEV; |
312 | goto err_rel_reg; | 312 | goto err_rel_reg; |
313 | } | 313 | } |
314 | 314 | ||
315 | rc = tpm_chip_register(chip); | ||
316 | if (rc) | ||
317 | goto err_rel_reg; | ||
318 | |||
315 | dev_dbg(&pdev->dev, "NSC TPM detected\n"); | 319 | dev_dbg(&pdev->dev, "NSC TPM detected\n"); |
316 | dev_dbg(&pdev->dev, | 320 | dev_dbg(&pdev->dev, |
317 | "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n", | 321 | "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n", |
diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c index 98ba2bd1a355..c002d1bd9caf 100644 --- a/drivers/char/tpm/tpm_of.c +++ b/drivers/char/tpm/tpm_of.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2012 IBM Corporation | 2 | * Copyright 2012 IBM Corporation |
3 | * | 3 | * |
4 | * Author: Ashley Lai <adlai@us.ibm.com> | 4 | * Author: Ashley Lai <ashleydlai@gmail.com> |
5 | * | 5 | * |
6 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | 6 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> |
7 | * | 7 | * |
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index 61dcc8011ec7..6ca9b5d78144 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 | ||
17 | static const u8 tpm_ppi_uuid[] = { | 35 | static 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 | ||
25 | static char tpm_ppi_version[PPI_VERSION_LEN + 1]; | ||
26 | static acpi_handle tpm_ppi_handle; | ||
27 | |||
28 | static 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 | |||
52 | static inline union acpi_object * | 43 | static inline union acpi_object * |
53 | tpm_eval_dsm(int func, acpi_object_type type, union acpi_object *argv4) | 44 | tpm_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 | ||
60 | static ssize_t tpm_show_ppi_version(struct device *dev, | 53 | static 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 | ||
66 | static ssize_t tpm_show_ppi_request(struct device *dev, | 61 | static 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 | ||
251 | static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) | 254 | static 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 | ||
297 | static ssize_t tpm_show_ppi_vs_operations(struct device *dev, | 305 | static 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 | ||
304 | static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL); | 315 | static 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 | ||
326 | int tpm_add_ppi(struct kobject *parent) | 337 | int 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->pdev->kobj, &ppi_attr_grp); | ||
360 | |||
361 | if (!rc) | ||
362 | chip->flags |= TPM_CHIP_FLAG_PPI; | ||
363 | |||
364 | return rc; | ||
332 | } | 365 | } |
333 | 366 | ||
334 | void tpm_remove_ppi(struct kobject *parent) | 367 | void 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->pdev->kobj, &ppi_attr_grp); |
338 | } | 371 | } |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 6f1985496112..6725bef7cb96 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -1,5 +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 | * | 4 | * |
4 | * Authors: | 5 | * Authors: |
5 | * Leendert van Doorn <leendert@watson.ibm.com> | 6 | * Leendert van Doorn <leendert@watson.ibm.com> |
@@ -64,19 +65,30 @@ enum tis_defaults { | |||
64 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ | 65 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ |
65 | }; | 66 | }; |
66 | 67 | ||
68 | |||
69 | /* Some timeout values are needed before it is known whether the chip is | ||
70 | * TPM 1.0 or TPM 2.0. | ||
71 | */ | ||
72 | #define TIS_TIMEOUT_A_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A) | ||
73 | #define TIS_TIMEOUT_B_MAX max(TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B) | ||
74 | #define TIS_TIMEOUT_C_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C) | ||
75 | #define TIS_TIMEOUT_D_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D) | ||
76 | |||
67 | #define TPM_ACCESS(l) (0x0000 | ((l) << 12)) | 77 | #define TPM_ACCESS(l) (0x0000 | ((l) << 12)) |
68 | #define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) | 78 | #define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) |
69 | #define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) | 79 | #define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) |
70 | #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) | 80 | #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) |
71 | #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) | 81 | #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) |
72 | #define TPM_STS(l) (0x0018 | ((l) << 12)) | 82 | #define TPM_STS(l) (0x0018 | ((l) << 12)) |
83 | #define TPM_STS3(l) (0x001b | ((l) << 12)) | ||
73 | #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) | 84 | #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) |
74 | 85 | ||
75 | #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) | 86 | #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) |
76 | #define TPM_RID(l) (0x0F04 | ((l) << 12)) | 87 | #define TPM_RID(l) (0x0F04 | ((l) << 12)) |
77 | 88 | ||
78 | static LIST_HEAD(tis_chips); | 89 | struct priv_data { |
79 | static DEFINE_MUTEX(tis_lock); | 90 | bool irq_tested; |
91 | }; | ||
80 | 92 | ||
81 | #if defined(CONFIG_PNP) && defined(CONFIG_ACPI) | 93 | #if defined(CONFIG_PNP) && defined(CONFIG_ACPI) |
82 | static int is_itpm(struct pnp_dev *dev) | 94 | static int is_itpm(struct pnp_dev *dev) |
@@ -241,7 +253,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
241 | /* read first 10 bytes, including tag, paramsize, and result */ | 253 | /* read first 10 bytes, including tag, paramsize, and result */ |
242 | if ((size = | 254 | if ((size = |
243 | recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) { | 255 | recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) { |
244 | dev_err(chip->dev, "Unable to read header\n"); | 256 | dev_err(chip->pdev, "Unable to read header\n"); |
245 | goto out; | 257 | goto out; |
246 | } | 258 | } |
247 | 259 | ||
@@ -254,7 +266,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
254 | if ((size += | 266 | if ((size += |
255 | recv_data(chip, &buf[TPM_HEADER_SIZE], | 267 | recv_data(chip, &buf[TPM_HEADER_SIZE], |
256 | expected - TPM_HEADER_SIZE)) < expected) { | 268 | expected - TPM_HEADER_SIZE)) < expected) { |
257 | dev_err(chip->dev, "Unable to read remainder of result\n"); | 269 | dev_err(chip->pdev, "Unable to read remainder of result\n"); |
258 | size = -ETIME; | 270 | size = -ETIME; |
259 | goto out; | 271 | goto out; |
260 | } | 272 | } |
@@ -263,7 +275,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
263 | &chip->vendor.int_queue, false); | 275 | &chip->vendor.int_queue, false); |
264 | status = tpm_tis_status(chip); | 276 | status = tpm_tis_status(chip); |
265 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ | 277 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ |
266 | dev_err(chip->dev, "Error left over data\n"); | 278 | dev_err(chip->pdev, "Error left over data\n"); |
267 | size = -EIO; | 279 | size = -EIO; |
268 | goto out; | 280 | goto out; |
269 | } | 281 | } |
@@ -338,15 +350,31 @@ out_err: | |||
338 | return rc; | 350 | return rc; |
339 | } | 351 | } |
340 | 352 | ||
353 | static void disable_interrupts(struct tpm_chip *chip) | ||
354 | { | ||
355 | u32 intmask; | ||
356 | |||
357 | intmask = | ||
358 | ioread32(chip->vendor.iobase + | ||
359 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
360 | intmask &= ~TPM_GLOBAL_INT_ENABLE; | ||
361 | iowrite32(intmask, | ||
362 | chip->vendor.iobase + | ||
363 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
364 | free_irq(chip->vendor.irq, chip); | ||
365 | chip->vendor.irq = 0; | ||
366 | } | ||
367 | |||
341 | /* | 368 | /* |
342 | * If interrupts are used (signaled by an irq set in the vendor structure) | 369 | * If interrupts are used (signaled by an irq set in the vendor structure) |
343 | * tpm.c can skip polling for the data to be available as the interrupt is | 370 | * tpm.c can skip polling for the data to be available as the interrupt is |
344 | * waited for here | 371 | * waited for here |
345 | */ | 372 | */ |
346 | static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | 373 | static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) |
347 | { | 374 | { |
348 | int rc; | 375 | int rc; |
349 | u32 ordinal; | 376 | u32 ordinal; |
377 | unsigned long dur; | ||
350 | 378 | ||
351 | rc = tpm_tis_send_data(chip, buf, len); | 379 | rc = tpm_tis_send_data(chip, buf, len); |
352 | if (rc < 0) | 380 | if (rc < 0) |
@@ -358,9 +386,14 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
358 | 386 | ||
359 | if (chip->vendor.irq) { | 387 | if (chip->vendor.irq) { |
360 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | 388 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); |
389 | |||
390 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | ||
391 | dur = tpm2_calc_ordinal_duration(chip, ordinal); | ||
392 | else | ||
393 | dur = tpm_calc_ordinal_duration(chip, ordinal); | ||
394 | |||
361 | if (wait_for_tpm_stat | 395 | if (wait_for_tpm_stat |
362 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 396 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, |
363 | tpm_calc_ordinal_duration(chip, ordinal), | ||
364 | &chip->vendor.read_queue, false) < 0) { | 397 | &chip->vendor.read_queue, false) < 0) { |
365 | rc = -ETIME; | 398 | rc = -ETIME; |
366 | goto out_err; | 399 | goto out_err; |
@@ -373,6 +406,30 @@ out_err: | |||
373 | return rc; | 406 | return rc; |
374 | } | 407 | } |
375 | 408 | ||
409 | static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | ||
410 | { | ||
411 | int rc, irq; | ||
412 | struct priv_data *priv = chip->vendor.priv; | ||
413 | |||
414 | if (!chip->vendor.irq || priv->irq_tested) | ||
415 | return tpm_tis_send_main(chip, buf, len); | ||
416 | |||
417 | /* Verify receipt of the expected IRQ */ | ||
418 | irq = chip->vendor.irq; | ||
419 | chip->vendor.irq = 0; | ||
420 | rc = tpm_tis_send_main(chip, buf, len); | ||
421 | chip->vendor.irq = irq; | ||
422 | if (!priv->irq_tested) | ||
423 | msleep(1); | ||
424 | if (!priv->irq_tested) { | ||
425 | disable_interrupts(chip); | ||
426 | dev_err(chip->pdev, | ||
427 | FW_BUG "TPM interrupt not working, polling instead\n"); | ||
428 | } | ||
429 | priv->irq_tested = true; | ||
430 | return rc; | ||
431 | } | ||
432 | |||
376 | struct tis_vendor_timeout_override { | 433 | struct tis_vendor_timeout_override { |
377 | u32 did_vid; | 434 | u32 did_vid; |
378 | unsigned long timeout_us[4]; | 435 | unsigned long timeout_us[4]; |
@@ -436,7 +493,7 @@ static int probe_itpm(struct tpm_chip *chip) | |||
436 | 493 | ||
437 | rc = tpm_tis_send_data(chip, cmd_getticks, len); | 494 | rc = tpm_tis_send_data(chip, cmd_getticks, len); |
438 | if (rc == 0) { | 495 | if (rc == 0) { |
439 | dev_info(chip->dev, "Detected an iTPM.\n"); | 496 | dev_info(chip->pdev, "Detected an iTPM.\n"); |
440 | rc = 1; | 497 | rc = 1; |
441 | } else | 498 | } else |
442 | rc = -EFAULT; | 499 | rc = -EFAULT; |
@@ -505,6 +562,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) | |||
505 | if (interrupt == 0) | 562 | if (interrupt == 0) |
506 | return IRQ_NONE; | 563 | return IRQ_NONE; |
507 | 564 | ||
565 | ((struct priv_data *)chip->vendor.priv)->irq_tested = true; | ||
508 | if (interrupt & TPM_INTF_DATA_AVAIL_INT) | 566 | if (interrupt & TPM_INTF_DATA_AVAIL_INT) |
509 | wake_up_interruptible(&chip->vendor.read_queue); | 567 | wake_up_interruptible(&chip->vendor.read_queue); |
510 | if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) | 568 | if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) |
@@ -528,27 +586,48 @@ static bool interrupts = true; | |||
528 | module_param(interrupts, bool, 0444); | 586 | module_param(interrupts, bool, 0444); |
529 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); | 587 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); |
530 | 588 | ||
531 | static int tpm_tis_init(struct device *dev, resource_size_t start, | 589 | static void tpm_tis_remove(struct tpm_chip *chip) |
532 | resource_size_t len, unsigned int irq) | 590 | { |
591 | iowrite32(~TPM_GLOBAL_INT_ENABLE & | ||
592 | ioread32(chip->vendor.iobase + | ||
593 | TPM_INT_ENABLE(chip->vendor. | ||
594 | locality)), | ||
595 | chip->vendor.iobase + | ||
596 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
597 | release_locality(chip, chip->vendor.locality, 1); | ||
598 | } | ||
599 | |||
600 | static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | ||
601 | resource_size_t start, resource_size_t len, | ||
602 | unsigned int irq) | ||
533 | { | 603 | { |
534 | u32 vendor, intfcaps, intmask; | 604 | u32 vendor, intfcaps, intmask; |
535 | int rc, i, irq_s, irq_e, probe; | 605 | int rc, i, irq_s, irq_e, probe; |
536 | struct tpm_chip *chip; | 606 | struct tpm_chip *chip; |
607 | struct priv_data *priv; | ||
537 | 608 | ||
538 | if (!(chip = tpm_register_hardware(dev, &tpm_tis))) | 609 | priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); |
539 | return -ENODEV; | 610 | if (priv == NULL) |
611 | return -ENOMEM; | ||
540 | 612 | ||
541 | chip->vendor.iobase = ioremap(start, len); | 613 | chip = tpmm_chip_alloc(dev, &tpm_tis); |
542 | if (!chip->vendor.iobase) { | 614 | if (IS_ERR(chip)) |
543 | rc = -EIO; | 615 | return PTR_ERR(chip); |
544 | goto out_err; | 616 | |
545 | } | 617 | chip->vendor.priv = priv; |
618 | #ifdef CONFIG_ACPI | ||
619 | chip->acpi_dev_handle = acpi_dev_handle; | ||
620 | #endif | ||
621 | |||
622 | chip->vendor.iobase = devm_ioremap(dev, start, len); | ||
623 | if (!chip->vendor.iobase) | ||
624 | return -EIO; | ||
546 | 625 | ||
547 | /* Default timeouts */ | 626 | /* Maximum timeouts */ |
548 | chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 627 | chip->vendor.timeout_a = TIS_TIMEOUT_A_MAX; |
549 | chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); | 628 | chip->vendor.timeout_b = TIS_TIMEOUT_B_MAX; |
550 | chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 629 | chip->vendor.timeout_c = TIS_TIMEOUT_C_MAX; |
551 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 630 | chip->vendor.timeout_d = TIS_TIMEOUT_D_MAX; |
552 | 631 | ||
553 | if (wait_startup(chip, 0) != 0) { | 632 | if (wait_startup(chip, 0) != 0) { |
554 | rc = -ENODEV; | 633 | rc = -ENODEV; |
@@ -560,11 +639,18 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
560 | goto out_err; | 639 | goto out_err; |
561 | } | 640 | } |
562 | 641 | ||
642 | /* Every TPM 2.x command has a higher ordinal than TPM 1.x commands. | ||
643 | * Therefore, we can use an idempotent TPM 2.x command to probe TPM 2.x. | ||
644 | */ | ||
645 | rc = tpm2_gen_interrupt(chip, true); | ||
646 | if (rc == 0 || rc == TPM2_RC_INITIALIZE) | ||
647 | chip->flags |= TPM_CHIP_FLAG_TPM2; | ||
648 | |||
563 | vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); | 649 | vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); |
564 | chip->vendor.manufacturer_id = vendor; | 650 | chip->vendor.manufacturer_id = vendor; |
565 | 651 | ||
566 | dev_info(dev, | 652 | dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", |
567 | "1.2 TPM (device-id 0x%X, rev-id %d)\n", | 653 | (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", |
568 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); | 654 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); |
569 | 655 | ||
570 | if (!itpm) { | 656 | if (!itpm) { |
@@ -605,19 +691,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
605 | if (intfcaps & TPM_INTF_DATA_AVAIL_INT) | 691 | if (intfcaps & TPM_INTF_DATA_AVAIL_INT) |
606 | dev_dbg(dev, "\tData Avail Int Support\n"); | 692 | dev_dbg(dev, "\tData Avail Int Support\n"); |
607 | 693 | ||
608 | /* get the timeouts before testing for irqs */ | ||
609 | if (tpm_get_timeouts(chip)) { | ||
610 | dev_err(dev, "Could not get TPM timeouts and durations\n"); | ||
611 | rc = -ENODEV; | ||
612 | goto out_err; | ||
613 | } | ||
614 | |||
615 | if (tpm_do_selftest(chip)) { | ||
616 | dev_err(dev, "TPM self test failed\n"); | ||
617 | rc = -ENODEV; | ||
618 | goto out_err; | ||
619 | } | ||
620 | |||
621 | /* INTERRUPT Setup */ | 694 | /* INTERRUPT Setup */ |
622 | init_waitqueue_head(&chip->vendor.read_queue); | 695 | init_waitqueue_head(&chip->vendor.read_queue); |
623 | init_waitqueue_head(&chip->vendor.int_queue); | 696 | init_waitqueue_head(&chip->vendor.int_queue); |
@@ -649,10 +722,10 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
649 | for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) { | 722 | for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) { |
650 | iowrite8(i, chip->vendor.iobase + | 723 | iowrite8(i, chip->vendor.iobase + |
651 | TPM_INT_VECTOR(chip->vendor.locality)); | 724 | TPM_INT_VECTOR(chip->vendor.locality)); |
652 | if (request_irq | 725 | if (devm_request_irq |
653 | (i, tis_int_probe, IRQF_SHARED, | 726 | (dev, i, tis_int_probe, IRQF_SHARED, |
654 | chip->vendor.miscdev.name, chip) != 0) { | 727 | chip->devname, chip) != 0) { |
655 | dev_info(chip->dev, | 728 | dev_info(chip->pdev, |
656 | "Unable to request irq: %d for probe\n", | 729 | "Unable to request irq: %d for probe\n", |
657 | i); | 730 | i); |
658 | continue; | 731 | continue; |
@@ -673,7 +746,10 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
673 | chip->vendor.probed_irq = 0; | 746 | chip->vendor.probed_irq = 0; |
674 | 747 | ||
675 | /* Generate Interrupts */ | 748 | /* Generate Interrupts */ |
676 | tpm_gen_interrupt(chip); | 749 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
750 | tpm2_gen_interrupt(chip, false); | ||
751 | else | ||
752 | tpm_gen_interrupt(chip); | ||
677 | 753 | ||
678 | chip->vendor.irq = chip->vendor.probed_irq; | 754 | chip->vendor.irq = chip->vendor.probed_irq; |
679 | 755 | ||
@@ -690,17 +766,16 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
690 | iowrite32(intmask, | 766 | iowrite32(intmask, |
691 | chip->vendor.iobase + | 767 | chip->vendor.iobase + |
692 | TPM_INT_ENABLE(chip->vendor.locality)); | 768 | TPM_INT_ENABLE(chip->vendor.locality)); |
693 | free_irq(i, chip); | ||
694 | } | 769 | } |
695 | } | 770 | } |
696 | if (chip->vendor.irq) { | 771 | if (chip->vendor.irq) { |
697 | iowrite8(chip->vendor.irq, | 772 | iowrite8(chip->vendor.irq, |
698 | chip->vendor.iobase + | 773 | chip->vendor.iobase + |
699 | TPM_INT_VECTOR(chip->vendor.locality)); | 774 | TPM_INT_VECTOR(chip->vendor.locality)); |
700 | if (request_irq | 775 | if (devm_request_irq |
701 | (chip->vendor.irq, tis_int_handler, IRQF_SHARED, | 776 | (dev, chip->vendor.irq, tis_int_handler, IRQF_SHARED, |
702 | chip->vendor.miscdev.name, chip) != 0) { | 777 | chip->devname, chip) != 0) { |
703 | dev_info(chip->dev, | 778 | dev_info(chip->pdev, |
704 | "Unable to request irq: %d for use\n", | 779 | "Unable to request irq: %d for use\n", |
705 | chip->vendor.irq); | 780 | chip->vendor.irq); |
706 | chip->vendor.irq = 0; | 781 | chip->vendor.irq = 0; |
@@ -719,17 +794,49 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
719 | } | 794 | } |
720 | } | 795 | } |
721 | 796 | ||
722 | INIT_LIST_HEAD(&chip->vendor.list); | 797 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
723 | mutex_lock(&tis_lock); | 798 | chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); |
724 | list_add(&chip->vendor.list, &tis_chips); | 799 | chip->vendor.timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); |
725 | mutex_unlock(&tis_lock); | 800 | chip->vendor.timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); |
801 | chip->vendor.timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); | ||
802 | chip->vendor.duration[TPM_SHORT] = | ||
803 | msecs_to_jiffies(TPM2_DURATION_SHORT); | ||
804 | chip->vendor.duration[TPM_MEDIUM] = | ||
805 | msecs_to_jiffies(TPM2_DURATION_MEDIUM); | ||
806 | chip->vendor.duration[TPM_LONG] = | ||
807 | msecs_to_jiffies(TPM2_DURATION_LONG); | ||
808 | |||
809 | rc = tpm2_do_selftest(chip); | ||
810 | if (rc == TPM2_RC_INITIALIZE) { | ||
811 | dev_warn(dev, "Firmware has not started TPM\n"); | ||
812 | rc = tpm2_startup(chip, TPM2_SU_CLEAR); | ||
813 | if (!rc) | ||
814 | rc = tpm2_do_selftest(chip); | ||
815 | } | ||
726 | 816 | ||
817 | if (rc) { | ||
818 | dev_err(dev, "TPM self test failed\n"); | ||
819 | if (rc > 0) | ||
820 | rc = -ENODEV; | ||
821 | goto out_err; | ||
822 | } | ||
823 | } else { | ||
824 | if (tpm_get_timeouts(chip)) { | ||
825 | dev_err(dev, "Could not get TPM timeouts and durations\n"); | ||
826 | rc = -ENODEV; | ||
827 | goto out_err; | ||
828 | } | ||
727 | 829 | ||
728 | return 0; | 830 | if (tpm_do_selftest(chip)) { |
831 | dev_err(dev, "TPM self test failed\n"); | ||
832 | rc = -ENODEV; | ||
833 | goto out_err; | ||
834 | } | ||
835 | } | ||
836 | |||
837 | return tpm_chip_register(chip); | ||
729 | out_err: | 838 | out_err: |
730 | if (chip->vendor.iobase) | 839 | tpm_tis_remove(chip); |
731 | iounmap(chip->vendor.iobase); | ||
732 | tpm_remove_hardware(chip->dev); | ||
733 | return rc; | 840 | return rc; |
734 | } | 841 | } |
735 | 842 | ||
@@ -758,14 +865,23 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) | |||
758 | static int tpm_tis_resume(struct device *dev) | 865 | static int tpm_tis_resume(struct device *dev) |
759 | { | 866 | { |
760 | struct tpm_chip *chip = dev_get_drvdata(dev); | 867 | struct tpm_chip *chip = dev_get_drvdata(dev); |
761 | int ret; | 868 | int ret = 0; |
762 | 869 | ||
763 | if (chip->vendor.irq) | 870 | if (chip->vendor.irq) |
764 | tpm_tis_reenable_interrupts(chip); | 871 | tpm_tis_reenable_interrupts(chip); |
765 | 872 | ||
766 | ret = tpm_pm_resume(dev); | 873 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
767 | if (!ret) | 874 | /* NOP if firmware properly does this. */ |
768 | tpm_do_selftest(chip); | 875 | tpm2_startup(chip, TPM2_SU_STATE); |
876 | |||
877 | ret = tpm2_shutdown(chip, TPM2_SU_STATE); | ||
878 | if (!ret) | ||
879 | ret = tpm2_do_selftest(chip); | ||
880 | } else { | ||
881 | ret = tpm_pm_resume(dev); | ||
882 | if (!ret) | ||
883 | tpm_do_selftest(chip); | ||
884 | } | ||
769 | 885 | ||
770 | return ret; | 886 | return ret; |
771 | } | 887 | } |
@@ -779,6 +895,7 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | |||
779 | { | 895 | { |
780 | resource_size_t start, len; | 896 | resource_size_t start, len; |
781 | unsigned int irq = 0; | 897 | unsigned int irq = 0; |
898 | acpi_handle acpi_dev_handle = NULL; | ||
782 | 899 | ||
783 | start = pnp_mem_start(pnp_dev, 0); | 900 | start = pnp_mem_start(pnp_dev, 0); |
784 | len = pnp_mem_len(pnp_dev, 0); | 901 | len = pnp_mem_len(pnp_dev, 0); |
@@ -791,7 +908,12 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | |||
791 | if (is_itpm(pnp_dev)) | 908 | if (is_itpm(pnp_dev)) |
792 | itpm = true; | 909 | itpm = true; |
793 | 910 | ||
794 | return tpm_tis_init(&pnp_dev->dev, start, len, irq); | 911 | #ifdef CONFIG_ACPI |
912 | if (pnp_acpi_device(pnp_dev)) | ||
913 | acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle; | ||
914 | #endif | ||
915 | |||
916 | return tpm_tis_init(&pnp_dev->dev, acpi_dev_handle, start, len, irq); | ||
795 | } | 917 | } |
796 | 918 | ||
797 | static struct pnp_device_id tpm_pnp_tbl[] = { | 919 | static struct pnp_device_id tpm_pnp_tbl[] = { |
@@ -811,13 +933,10 @@ MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); | |||
811 | static void tpm_tis_pnp_remove(struct pnp_dev *dev) | 933 | static void tpm_tis_pnp_remove(struct pnp_dev *dev) |
812 | { | 934 | { |
813 | struct tpm_chip *chip = pnp_get_drvdata(dev); | 935 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
814 | 936 | tpm_chip_unregister(chip); | |
815 | tpm_dev_vendor_release(chip); | 937 | tpm_tis_remove(chip); |
816 | |||
817 | kfree(chip); | ||
818 | } | 938 | } |
819 | 939 | ||
820 | |||
821 | static struct pnp_driver tis_pnp_driver = { | 940 | static struct pnp_driver tis_pnp_driver = { |
822 | .name = "tpm_tis", | 941 | .name = "tpm_tis", |
823 | .id_table = tpm_pnp_tbl, | 942 | .id_table = tpm_pnp_tbl, |
@@ -836,7 +955,7 @@ MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | |||
836 | 955 | ||
837 | static struct platform_driver tis_drv = { | 956 | static struct platform_driver tis_drv = { |
838 | .driver = { | 957 | .driver = { |
839 | .name = "tpm_tis", | 958 | .name = "tpm_tis", |
840 | .pm = &tpm_tis_pm, | 959 | .pm = &tpm_tis_pm, |
841 | }, | 960 | }, |
842 | }; | 961 | }; |
@@ -862,7 +981,7 @@ static int __init init_tis(void) | |||
862 | rc = PTR_ERR(pdev); | 981 | rc = PTR_ERR(pdev); |
863 | goto err_dev; | 982 | goto err_dev; |
864 | } | 983 | } |
865 | rc = tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0); | 984 | rc = tpm_tis_init(&pdev->dev, NULL, TIS_MEM_BASE, TIS_MEM_LEN, 0); |
866 | if (rc) | 985 | if (rc) |
867 | goto err_init; | 986 | goto err_init; |
868 | return 0; | 987 | return 0; |
@@ -875,31 +994,16 @@ err_dev: | |||
875 | 994 | ||
876 | static void __exit cleanup_tis(void) | 995 | static void __exit cleanup_tis(void) |
877 | { | 996 | { |
878 | struct tpm_vendor_specific *i, *j; | ||
879 | struct tpm_chip *chip; | 997 | struct tpm_chip *chip; |
880 | mutex_lock(&tis_lock); | ||
881 | list_for_each_entry_safe(i, j, &tis_chips, list) { | ||
882 | chip = to_tpm_chip(i); | ||
883 | tpm_remove_hardware(chip->dev); | ||
884 | iowrite32(~TPM_GLOBAL_INT_ENABLE & | ||
885 | ioread32(chip->vendor.iobase + | ||
886 | TPM_INT_ENABLE(chip->vendor. | ||
887 | locality)), | ||
888 | chip->vendor.iobase + | ||
889 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
890 | release_locality(chip, chip->vendor.locality, 1); | ||
891 | if (chip->vendor.irq) | ||
892 | free_irq(chip->vendor.irq, chip); | ||
893 | iounmap(i->iobase); | ||
894 | list_del(&i->list); | ||
895 | } | ||
896 | mutex_unlock(&tis_lock); | ||
897 | #ifdef CONFIG_PNP | 998 | #ifdef CONFIG_PNP |
898 | if (!force) { | 999 | if (!force) { |
899 | pnp_unregister_driver(&tis_pnp_driver); | 1000 | pnp_unregister_driver(&tis_pnp_driver); |
900 | return; | 1001 | return; |
901 | } | 1002 | } |
902 | #endif | 1003 | #endif |
1004 | chip = dev_get_drvdata(&pdev->dev); | ||
1005 | tpm_chip_unregister(chip); | ||
1006 | tpm_tis_remove(chip); | ||
903 | platform_device_unregister(pdev); | 1007 | platform_device_unregister(pdev); |
904 | platform_driver_unregister(&tis_drv); | 1008 | platform_driver_unregister(&tis_drv); |
905 | } | 1009 | } |
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c index 441b44e54226..c3b4f5a5ac10 100644 --- a/drivers/char/tpm/xen-tpmfront.c +++ b/drivers/char/tpm/xen-tpmfront.c | |||
@@ -175,9 +175,9 @@ static int setup_chip(struct device *dev, struct tpm_private *priv) | |||
175 | { | 175 | { |
176 | struct tpm_chip *chip; | 176 | struct tpm_chip *chip; |
177 | 177 | ||
178 | chip = tpm_register_hardware(dev, &tpm_vtpm); | 178 | chip = tpmm_chip_alloc(dev, &tpm_vtpm); |
179 | if (!chip) | 179 | if (IS_ERR(chip)) |
180 | return -ENODEV; | 180 | return PTR_ERR(chip); |
181 | 181 | ||
182 | init_waitqueue_head(&chip->vendor.read_queue); | 182 | init_waitqueue_head(&chip->vendor.read_queue); |
183 | 183 | ||
@@ -286,6 +286,7 @@ static int tpmfront_probe(struct xenbus_device *dev, | |||
286 | const struct xenbus_device_id *id) | 286 | const struct xenbus_device_id *id) |
287 | { | 287 | { |
288 | struct tpm_private *priv; | 288 | struct tpm_private *priv; |
289 | struct tpm_chip *chip; | ||
289 | int rv; | 290 | int rv; |
290 | 291 | ||
291 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 292 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
@@ -302,21 +303,22 @@ static int tpmfront_probe(struct xenbus_device *dev, | |||
302 | 303 | ||
303 | rv = setup_ring(dev, priv); | 304 | rv = setup_ring(dev, priv); |
304 | if (rv) { | 305 | if (rv) { |
305 | tpm_remove_hardware(&dev->dev); | 306 | chip = dev_get_drvdata(&dev->dev); |
307 | tpm_chip_unregister(chip); | ||
306 | ring_free(priv); | 308 | ring_free(priv); |
307 | return rv; | 309 | return rv; |
308 | } | 310 | } |
309 | 311 | ||
310 | tpm_get_timeouts(priv->chip); | 312 | tpm_get_timeouts(priv->chip); |
311 | 313 | ||
312 | return rv; | 314 | return tpm_chip_register(priv->chip); |
313 | } | 315 | } |
314 | 316 | ||
315 | static int tpmfront_remove(struct xenbus_device *dev) | 317 | static int tpmfront_remove(struct xenbus_device *dev) |
316 | { | 318 | { |
317 | struct tpm_chip *chip = dev_get_drvdata(&dev->dev); | 319 | struct tpm_chip *chip = dev_get_drvdata(&dev->dev); |
318 | struct tpm_private *priv = TPM_VPRIV(chip); | 320 | struct tpm_private *priv = TPM_VPRIV(chip); |
319 | tpm_remove_hardware(&dev->dev); | 321 | tpm_chip_unregister(chip); |
320 | ring_free(priv); | 322 | ring_free(priv); |
321 | TPM_VPRIV(chip) = NULL; | 323 | TPM_VPRIV(chip) = NULL; |
322 | return 0; | 324 | return 0; |
diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.h b/include/linux/platform_data/tpm_stm_st33.h index 439a43249aa6..ff75310c0f47 100644 --- a/drivers/char/tpm/tpm_i2c_stm_st33.h +++ b/include/linux/platform_data/tpm_stm_st33.h | |||
@@ -12,9 +12,8 @@ | |||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License along | 15 | * You should have received a copy of the GNU General Public License |
16 | * with this program; if not, write to the Free Software Foundation, Inc., | 16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * | 17 | * |
19 | * STMicroelectronics version 1.2.0, Copyright (C) 2010 | 18 | * STMicroelectronics version 1.2.0, Copyright (C) 2010 |
20 | * STMicroelectronics comes with ABSOLUTELY NO WARRANTY. | 19 | * STMicroelectronics comes with ABSOLUTELY NO WARRANTY. |
@@ -23,39 +22,18 @@ | |||
23 | * | 22 | * |
24 | * @Author: Christophe RICARD tpmsupport@st.com | 23 | * @Author: Christophe RICARD tpmsupport@st.com |
25 | * | 24 | * |
26 | * @File: stm_st33_tpm_i2c.h | 25 | * @File: stm_st33_tpm.h |
27 | * | 26 | * |
28 | * @Date: 09/15/2010 | 27 | * @Date: 09/15/2010 |
29 | */ | 28 | */ |
30 | #ifndef __STM_ST33_TPM_I2C_MAIN_H__ | 29 | #ifndef __STM_ST33_TPM_H__ |
31 | #define __STM_ST33_TPM_I2C_MAIN_H__ | 30 | #define __STM_ST33_TPM_H__ |
32 | 31 | ||
33 | #define TPM_ACCESS (0x0) | 32 | #define TPM_ST33_I2C "st33zp24-i2c" |
34 | #define TPM_STS (0x18) | 33 | #define TPM_ST33_SPI "st33zp24-spi" |
35 | #define TPM_HASH_END (0x20) | ||
36 | #define TPM_DATA_FIFO (0x24) | ||
37 | #define TPM_HASH_DATA (0x24) | ||
38 | #define TPM_HASH_START (0x28) | ||
39 | #define TPM_INTF_CAPABILITY (0x14) | ||
40 | #define TPM_INT_STATUS (0x10) | ||
41 | #define TPM_INT_ENABLE (0x08) | ||
42 | |||
43 | #define TPM_DUMMY_BYTE 0xAA | ||
44 | #define TPM_WRITE_DIRECTION 0x80 | ||
45 | #define TPM_HEADER_SIZE 10 | ||
46 | #define TPM_BUFSIZE 2048 | ||
47 | |||
48 | #define LOCALITY0 0 | ||
49 | |||
50 | #define TPM_ST33_I2C "st33zp24_i2c" | ||
51 | 34 | ||
52 | struct st33zp24_platform_data { | 35 | struct st33zp24_platform_data { |
53 | int io_serirq; | ||
54 | int io_lpcpd; | 36 | int io_lpcpd; |
55 | struct i2c_client *client; | ||
56 | u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */ | ||
57 | struct completion irq_detection; | ||
58 | struct mutex lock; | ||
59 | }; | 37 | }; |
60 | 38 | ||
61 | #endif /* __STM_ST33_TPM_I2C_MAIN_H__ */ | 39 | #endif /* __STM_ST33_TPM_H__ */ |
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index a6fd939f202d..3ebb168b9afc 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h | |||
@@ -121,13 +121,6 @@ extern int cipso_v4_rbm_strictvalid; | |||
121 | #endif | 121 | #endif |
122 | 122 | ||
123 | /* | 123 | /* |
124 | * Helper Functions | ||
125 | */ | ||
126 | |||
127 | #define CIPSO_V4_OPTEXIST(x) (IPCB(x)->opt.cipso != 0) | ||
128 | #define CIPSO_V4_OPTPTR(x) (skb_network_header(x) + IPCB(x)->opt.cipso) | ||
129 | |||
130 | /* | ||
131 | * DOI List Functions | 124 | * DOI List Functions |
132 | */ | 125 | */ |
133 | 126 | ||
@@ -190,7 +183,7 @@ static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, | |||
190 | 183 | ||
191 | #ifdef CONFIG_NETLABEL | 184 | #ifdef CONFIG_NETLABEL |
192 | void cipso_v4_cache_invalidate(void); | 185 | void cipso_v4_cache_invalidate(void); |
193 | int cipso_v4_cache_add(const struct sk_buff *skb, | 186 | int cipso_v4_cache_add(const unsigned char *cipso_ptr, |
194 | const struct netlbl_lsm_secattr *secattr); | 187 | const struct netlbl_lsm_secattr *secattr); |
195 | #else | 188 | #else |
196 | static inline void cipso_v4_cache_invalidate(void) | 189 | static inline void cipso_v4_cache_invalidate(void) |
@@ -198,7 +191,7 @@ static inline void cipso_v4_cache_invalidate(void) | |||
198 | return; | 191 | return; |
199 | } | 192 | } |
200 | 193 | ||
201 | static inline int cipso_v4_cache_add(const struct sk_buff *skb, | 194 | static inline int cipso_v4_cache_add(const unsigned char *cipso_ptr, |
202 | const struct netlbl_lsm_secattr *secattr) | 195 | const struct netlbl_lsm_secattr *secattr) |
203 | { | 196 | { |
204 | return 0; | 197 | return 0; |
@@ -211,6 +204,8 @@ static inline int cipso_v4_cache_add(const struct sk_buff *skb, | |||
211 | 204 | ||
212 | #ifdef CONFIG_NETLABEL | 205 | #ifdef CONFIG_NETLABEL |
213 | void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway); | 206 | void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway); |
207 | int cipso_v4_getattr(const unsigned char *cipso, | ||
208 | struct netlbl_lsm_secattr *secattr); | ||
214 | int cipso_v4_sock_setattr(struct sock *sk, | 209 | int cipso_v4_sock_setattr(struct sock *sk, |
215 | const struct cipso_v4_doi *doi_def, | 210 | const struct cipso_v4_doi *doi_def, |
216 | const struct netlbl_lsm_secattr *secattr); | 211 | const struct netlbl_lsm_secattr *secattr); |
@@ -226,6 +221,7 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb, | |||
226 | int cipso_v4_skbuff_delattr(struct sk_buff *skb); | 221 | int cipso_v4_skbuff_delattr(struct sk_buff *skb); |
227 | int cipso_v4_skbuff_getattr(const struct sk_buff *skb, | 222 | int cipso_v4_skbuff_getattr(const struct sk_buff *skb, |
228 | struct netlbl_lsm_secattr *secattr); | 223 | struct netlbl_lsm_secattr *secattr); |
224 | unsigned char *cipso_v4_optptr(const struct sk_buff *skb); | ||
229 | int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option); | 225 | int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option); |
230 | #else | 226 | #else |
231 | static inline void cipso_v4_error(struct sk_buff *skb, | 227 | static inline void cipso_v4_error(struct sk_buff *skb, |
@@ -235,6 +231,12 @@ static inline void cipso_v4_error(struct sk_buff *skb, | |||
235 | return; | 231 | return; |
236 | } | 232 | } |
237 | 233 | ||
234 | static inline int cipso_v4_getattr(const unsigned char *cipso, | ||
235 | struct netlbl_lsm_secattr *secattr) | ||
236 | { | ||
237 | return -ENOSYS; | ||
238 | } | ||
239 | |||
238 | static inline int cipso_v4_sock_setattr(struct sock *sk, | 240 | static inline int cipso_v4_sock_setattr(struct sock *sk, |
239 | const struct cipso_v4_doi *doi_def, | 241 | const struct cipso_v4_doi *doi_def, |
240 | const struct netlbl_lsm_secattr *secattr) | 242 | const struct netlbl_lsm_secattr *secattr) |
@@ -282,6 +284,11 @@ static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb, | |||
282 | return -ENOSYS; | 284 | return -ENOSYS; |
283 | } | 285 | } |
284 | 286 | ||
287 | static inline unsigned char *cipso_v4_optptr(const struct sk_buff *skb) | ||
288 | { | ||
289 | return NULL; | ||
290 | } | ||
291 | |||
285 | static inline int cipso_v4_validate(const struct sk_buff *skb, | 292 | static inline int cipso_v4_validate(const struct sk_buff *skb, |
286 | unsigned char **option) | 293 | unsigned char **option) |
287 | { | 294 | { |
diff --git a/kernel/Makefile b/kernel/Makefile index 07737e50fe6e..1408b3353a3c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -143,7 +143,7 @@ endif | |||
143 | kernel/system_certificates.o: $(obj)/x509_certificate_list | 143 | kernel/system_certificates.o: $(obj)/x509_certificate_list |
144 | 144 | ||
145 | quiet_cmd_x509certs = CERTS $@ | 145 | quiet_cmd_x509certs = CERTS $@ |
146 | cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; echo " - Including cert $(X509)") | 146 | cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; $(kecho) " - Including cert $(X509)") |
147 | 147 | ||
148 | targets += $(obj)/x509_certificate_list | 148 | targets += $(obj)/x509_certificate_list |
149 | $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list | 149 | $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list |
diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c index 1871e7b61ca0..d25e9e96c310 100644 --- a/lib/mpi/mpi-cmp.c +++ b/lib/mpi/mpi-cmp.c | |||
@@ -57,14 +57,12 @@ int mpi_cmp(MPI u, MPI v) | |||
57 | if (usize != vsize && !u->sign && !v->sign) | 57 | if (usize != vsize && !u->sign && !v->sign) |
58 | return usize - vsize; | 58 | return usize - vsize; |
59 | if (usize != vsize && u->sign && v->sign) | 59 | if (usize != vsize && u->sign && v->sign) |
60 | return vsize + usize; | 60 | return vsize - usize; |
61 | if (!usize) | 61 | if (!usize) |
62 | return 0; | 62 | return 0; |
63 | cmp = mpihelp_cmp(u->d, v->d, usize); | 63 | cmp = mpihelp_cmp(u->d, v->d, usize); |
64 | if (!cmp) | 64 | if (u->sign) |
65 | return 0; | 65 | return -cmp; |
66 | if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) | 66 | return cmp; |
67 | return 1; | ||
68 | return -1; | ||
69 | } | 67 | } |
70 | EXPORT_SYMBOL_GPL(mpi_cmp); | 68 | EXPORT_SYMBOL_GPL(mpi_cmp); |
diff --git a/lib/mpi/mpi-internal.h b/lib/mpi/mpi-internal.h index 60cf765628e9..c65dd1bff45a 100644 --- a/lib/mpi/mpi-internal.h +++ b/lib/mpi/mpi-internal.h | |||
@@ -84,7 +84,7 @@ static inline int RESIZE_IF_NEEDED(MPI a, unsigned b) | |||
84 | do { \ | 84 | do { \ |
85 | mpi_size_t _i; \ | 85 | mpi_size_t _i; \ |
86 | for (_i = 0; _i < (n); _i++) \ | 86 | for (_i = 0; _i < (n); _i++) \ |
87 | (d)[_i] = (d)[_i]; \ | 87 | (d)[_i] = (s)[_i]; \ |
88 | } while (0) | 88 | } while (0) |
89 | 89 | ||
90 | #define MPN_COPY_DECR(d, s, n) \ | 90 | #define MPN_COPY_DECR(d, s, n) \ |
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 5160c710f2eb..e361ea6f3fc8 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -378,20 +378,18 @@ static int cipso_v4_cache_check(const unsigned char *key, | |||
378 | * negative values on failure. | 378 | * negative values on failure. |
379 | * | 379 | * |
380 | */ | 380 | */ |
381 | int cipso_v4_cache_add(const struct sk_buff *skb, | 381 | int cipso_v4_cache_add(const unsigned char *cipso_ptr, |
382 | const struct netlbl_lsm_secattr *secattr) | 382 | const struct netlbl_lsm_secattr *secattr) |
383 | { | 383 | { |
384 | int ret_val = -EPERM; | 384 | int ret_val = -EPERM; |
385 | u32 bkt; | 385 | u32 bkt; |
386 | struct cipso_v4_map_cache_entry *entry = NULL; | 386 | struct cipso_v4_map_cache_entry *entry = NULL; |
387 | struct cipso_v4_map_cache_entry *old_entry = NULL; | 387 | struct cipso_v4_map_cache_entry *old_entry = NULL; |
388 | unsigned char *cipso_ptr; | ||
389 | u32 cipso_ptr_len; | 388 | u32 cipso_ptr_len; |
390 | 389 | ||
391 | if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0) | 390 | if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0) |
392 | return 0; | 391 | return 0; |
393 | 392 | ||
394 | cipso_ptr = CIPSO_V4_OPTPTR(skb); | ||
395 | cipso_ptr_len = cipso_ptr[1]; | 393 | cipso_ptr_len = cipso_ptr[1]; |
396 | 394 | ||
397 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); | 395 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); |
@@ -1579,6 +1577,33 @@ static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def, | |||
1579 | } | 1577 | } |
1580 | 1578 | ||
1581 | /** | 1579 | /** |
1580 | * cipso_v4_optptr - Find the CIPSO option in the packet | ||
1581 | * @skb: the packet | ||
1582 | * | ||
1583 | * Description: | ||
1584 | * Parse the packet's IP header looking for a CIPSO option. Returns a pointer | ||
1585 | * to the start of the CIPSO option on success, NULL if one if not found. | ||
1586 | * | ||
1587 | */ | ||
1588 | unsigned char *cipso_v4_optptr(const struct sk_buff *skb) | ||
1589 | { | ||
1590 | const struct iphdr *iph = ip_hdr(skb); | ||
1591 | unsigned char *optptr = (unsigned char *)&(ip_hdr(skb)[1]); | ||
1592 | int optlen; | ||
1593 | int taglen; | ||
1594 | |||
1595 | for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 0; ) { | ||
1596 | if (optptr[0] == IPOPT_CIPSO) | ||
1597 | return optptr; | ||
1598 | taglen = optptr[1]; | ||
1599 | optlen -= taglen; | ||
1600 | optptr += taglen; | ||
1601 | } | ||
1602 | |||
1603 | return NULL; | ||
1604 | } | ||
1605 | |||
1606 | /** | ||
1582 | * cipso_v4_validate - Validate a CIPSO option | 1607 | * cipso_v4_validate - Validate a CIPSO option |
1583 | * @option: the start of the option, on error it is set to point to the error | 1608 | * @option: the start of the option, on error it is set to point to the error |
1584 | * | 1609 | * |
@@ -2119,8 +2144,8 @@ void cipso_v4_req_delattr(struct request_sock *req) | |||
2119 | * on success and negative values on failure. | 2144 | * on success and negative values on failure. |
2120 | * | 2145 | * |
2121 | */ | 2146 | */ |
2122 | static int cipso_v4_getattr(const unsigned char *cipso, | 2147 | int cipso_v4_getattr(const unsigned char *cipso, |
2123 | struct netlbl_lsm_secattr *secattr) | 2148 | struct netlbl_lsm_secattr *secattr) |
2124 | { | 2149 | { |
2125 | int ret_val = -ENOMSG; | 2150 | int ret_val = -ENOMSG; |
2126 | u32 doi; | 2151 | u32 doi; |
@@ -2305,22 +2330,6 @@ int cipso_v4_skbuff_delattr(struct sk_buff *skb) | |||
2305 | return 0; | 2330 | return 0; |
2306 | } | 2331 | } |
2307 | 2332 | ||
2308 | /** | ||
2309 | * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option | ||
2310 | * @skb: the packet | ||
2311 | * @secattr: the security attributes | ||
2312 | * | ||
2313 | * Description: | ||
2314 | * Parse the given packet's CIPSO option and return the security attributes. | ||
2315 | * Returns zero on success and negative values on failure. | ||
2316 | * | ||
2317 | */ | ||
2318 | int cipso_v4_skbuff_getattr(const struct sk_buff *skb, | ||
2319 | struct netlbl_lsm_secattr *secattr) | ||
2320 | { | ||
2321 | return cipso_v4_getattr(CIPSO_V4_OPTPTR(skb), secattr); | ||
2322 | } | ||
2323 | |||
2324 | /* | 2333 | /* |
2325 | * Setup Functions | 2334 | * Setup Functions |
2326 | */ | 2335 | */ |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index a845cd4cf21e..28cddc85b700 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
@@ -1065,10 +1065,12 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, | |||
1065 | u16 family, | 1065 | u16 family, |
1066 | struct netlbl_lsm_secattr *secattr) | 1066 | struct netlbl_lsm_secattr *secattr) |
1067 | { | 1067 | { |
1068 | unsigned char *ptr; | ||
1069 | |||
1068 | switch (family) { | 1070 | switch (family) { |
1069 | case AF_INET: | 1071 | case AF_INET: |
1070 | if (CIPSO_V4_OPTEXIST(skb) && | 1072 | ptr = cipso_v4_optptr(skb); |
1071 | cipso_v4_skbuff_getattr(skb, secattr) == 0) | 1073 | if (ptr && cipso_v4_getattr(ptr, secattr) == 0) |
1072 | return 0; | 1074 | return 0; |
1073 | break; | 1075 | break; |
1074 | #if IS_ENABLED(CONFIG_IPV6) | 1076 | #if IS_ENABLED(CONFIG_IPV6) |
@@ -1094,7 +1096,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, | |||
1094 | */ | 1096 | */ |
1095 | void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway) | 1097 | void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway) |
1096 | { | 1098 | { |
1097 | if (CIPSO_V4_OPTEXIST(skb)) | 1099 | if (cipso_v4_optptr(skb)) |
1098 | cipso_v4_error(skb, error, gateway); | 1100 | cipso_v4_error(skb, error, gateway); |
1099 | } | 1101 | } |
1100 | 1102 | ||
@@ -1126,11 +1128,14 @@ void netlbl_cache_invalidate(void) | |||
1126 | int netlbl_cache_add(const struct sk_buff *skb, | 1128 | int netlbl_cache_add(const struct sk_buff *skb, |
1127 | const struct netlbl_lsm_secattr *secattr) | 1129 | const struct netlbl_lsm_secattr *secattr) |
1128 | { | 1130 | { |
1131 | unsigned char *ptr; | ||
1132 | |||
1129 | if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0) | 1133 | if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0) |
1130 | return -ENOMSG; | 1134 | return -ENOMSG; |
1131 | 1135 | ||
1132 | if (CIPSO_V4_OPTEXIST(skb)) | 1136 | ptr = cipso_v4_optptr(skb); |
1133 | return cipso_v4_cache_add(skb, secattr); | 1137 | if (ptr) |
1138 | return cipso_v4_cache_add(ptr, secattr); | ||
1134 | 1139 | ||
1135 | return -ENOMSG; | 1140 | return -ENOMSG; |
1136 | } | 1141 | } |
diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c index 91c4117637ae..7750e9c31483 100644 --- a/scripts/asn1_compiler.c +++ b/scripts/asn1_compiler.c | |||
@@ -311,6 +311,9 @@ struct token { | |||
311 | 311 | ||
312 | static struct token *token_list; | 312 | static struct token *token_list; |
313 | static unsigned nr_tokens; | 313 | static unsigned nr_tokens; |
314 | static _Bool verbose; | ||
315 | |||
316 | #define debug(fmt, ...) do { if (verbose) printf(fmt, ## __VA_ARGS__); } while (0) | ||
314 | 317 | ||
315 | static int directive_compare(const void *_key, const void *_pdir) | 318 | static int directive_compare(const void *_key, const void *_pdir) |
316 | { | 319 | { |
@@ -322,21 +325,21 @@ static int directive_compare(const void *_key, const void *_pdir) | |||
322 | dlen = strlen(dir); | 325 | dlen = strlen(dir); |
323 | clen = (dlen < token->size) ? dlen : token->size; | 326 | clen = (dlen < token->size) ? dlen : token->size; |
324 | 327 | ||
325 | //printf("cmp(%*.*s,%s) = ", | 328 | //debug("cmp(%*.*s,%s) = ", |
326 | // (int)token->size, (int)token->size, token->value, | 329 | // (int)token->size, (int)token->size, token->value, |
327 | // dir); | 330 | // dir); |
328 | 331 | ||
329 | val = memcmp(token->value, dir, clen); | 332 | val = memcmp(token->value, dir, clen); |
330 | if (val != 0) { | 333 | if (val != 0) { |
331 | //printf("%d [cmp]\n", val); | 334 | //debug("%d [cmp]\n", val); |
332 | return val; | 335 | return val; |
333 | } | 336 | } |
334 | 337 | ||
335 | if (dlen == token->size) { | 338 | if (dlen == token->size) { |
336 | //printf("0\n"); | 339 | //debug("0\n"); |
337 | return 0; | 340 | return 0; |
338 | } | 341 | } |
339 | //printf("%d\n", (int)dlen - (int)token->size); | 342 | //debug("%d\n", (int)dlen - (int)token->size); |
340 | return dlen - token->size; /* shorter -> negative */ | 343 | return dlen - token->size; /* shorter -> negative */ |
341 | } | 344 | } |
342 | 345 | ||
@@ -515,13 +518,13 @@ static void tokenise(char *buffer, char *end) | |||
515 | } | 518 | } |
516 | 519 | ||
517 | nr_tokens = tix; | 520 | nr_tokens = tix; |
518 | printf("Extracted %u tokens\n", nr_tokens); | 521 | debug("Extracted %u tokens\n", nr_tokens); |
519 | 522 | ||
520 | #if 0 | 523 | #if 0 |
521 | { | 524 | { |
522 | int n; | 525 | int n; |
523 | for (n = 0; n < nr_tokens; n++) | 526 | for (n = 0; n < nr_tokens; n++) |
524 | printf("Token %3u: '%*.*s'\n", | 527 | debug("Token %3u: '%*.*s'\n", |
525 | n, | 528 | n, |
526 | (int)token_list[n].size, (int)token_list[n].size, | 529 | (int)token_list[n].size, (int)token_list[n].size, |
527 | token_list[n].value); | 530 | token_list[n].value); |
@@ -542,6 +545,7 @@ int main(int argc, char **argv) | |||
542 | ssize_t readlen; | 545 | ssize_t readlen; |
543 | FILE *out, *hdr; | 546 | FILE *out, *hdr; |
544 | char *buffer, *p; | 547 | char *buffer, *p; |
548 | char *kbuild_verbose; | ||
545 | int fd; | 549 | int fd; |
546 | 550 | ||
547 | if (argc != 4) { | 551 | if (argc != 4) { |
@@ -550,6 +554,10 @@ int main(int argc, char **argv) | |||
550 | exit(2); | 554 | exit(2); |
551 | } | 555 | } |
552 | 556 | ||
557 | kbuild_verbose = getenv("KBUILD_VERBOSE"); | ||
558 | if (kbuild_verbose) | ||
559 | verbose = atoi(kbuild_verbose); | ||
560 | |||
553 | filename = argv[1]; | 561 | filename = argv[1]; |
554 | outputname = argv[2]; | 562 | outputname = argv[2]; |
555 | headername = argv[3]; | 563 | headername = argv[3]; |
@@ -748,11 +756,11 @@ static void build_type_list(void) | |||
748 | 756 | ||
749 | qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); | 757 | qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); |
750 | 758 | ||
751 | printf("Extracted %u types\n", nr_types); | 759 | debug("Extracted %u types\n", nr_types); |
752 | #if 0 | 760 | #if 0 |
753 | for (n = 0; n < nr_types; n++) { | 761 | for (n = 0; n < nr_types; n++) { |
754 | struct type *type = type_index[n]; | 762 | struct type *type = type_index[n]; |
755 | printf("- %*.*s\n", | 763 | debug("- %*.*s\n", |
756 | (int)type->name->size, | 764 | (int)type->name->size, |
757 | (int)type->name->size, | 765 | (int)type->name->size, |
758 | type->name->value); | 766 | type->name->value); |
@@ -793,7 +801,7 @@ static void parse(void) | |||
793 | 801 | ||
794 | } while (type++, !(type->flags & TYPE_STOP_MARKER)); | 802 | } while (type++, !(type->flags & TYPE_STOP_MARKER)); |
795 | 803 | ||
796 | printf("Extracted %u actions\n", nr_actions); | 804 | debug("Extracted %u actions\n", nr_actions); |
797 | } | 805 | } |
798 | 806 | ||
799 | static struct element *element_list; | 807 | static struct element *element_list; |
@@ -1284,7 +1292,7 @@ static void render(FILE *out, FILE *hdr) | |||
1284 | } | 1292 | } |
1285 | 1293 | ||
1286 | /* We do two passes - the first one calculates all the offsets */ | 1294 | /* We do two passes - the first one calculates all the offsets */ |
1287 | printf("Pass 1\n"); | 1295 | debug("Pass 1\n"); |
1288 | nr_entries = 0; | 1296 | nr_entries = 0; |
1289 | root = &type_list[0]; | 1297 | root = &type_list[0]; |
1290 | render_element(NULL, root->element, NULL); | 1298 | render_element(NULL, root->element, NULL); |
@@ -1295,7 +1303,7 @@ static void render(FILE *out, FILE *hdr) | |||
1295 | e->flags &= ~ELEMENT_RENDERED; | 1303 | e->flags &= ~ELEMENT_RENDERED; |
1296 | 1304 | ||
1297 | /* And then we actually render */ | 1305 | /* And then we actually render */ |
1298 | printf("Pass 2\n"); | 1306 | debug("Pass 2\n"); |
1299 | fprintf(out, "\n"); | 1307 | fprintf(out, "\n"); |
1300 | fprintf(out, "static const unsigned char %s_machine[] = {\n", | 1308 | fprintf(out, "static const unsigned char %s_machine[] = {\n", |
1301 | grammar_name); | 1309 | grammar_name); |
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 57515bc915c0..df303346029b 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig | |||
@@ -126,7 +126,6 @@ config IMA_TRUSTED_KEYRING | |||
126 | bool "Require all keys on the .ima keyring be signed" | 126 | bool "Require all keys on the .ima keyring be signed" |
127 | depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING | 127 | depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING |
128 | depends on INTEGRITY_ASYMMETRIC_KEYS | 128 | depends on INTEGRITY_ASYMMETRIC_KEYS |
129 | select KEYS_DEBUG_PROC_KEYS | ||
130 | default y | 129 | default y |
131 | help | 130 | help |
132 | This option requires that all keys added to the .ima | 131 | This option requires that all keys added to the .ima |
diff --git a/security/keys/Kconfig b/security/keys/Kconfig index a4f3f8c48d6e..72483b8f1be5 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig | |||
@@ -80,21 +80,3 @@ config ENCRYPTED_KEYS | |||
80 | Userspace only ever sees/stores encrypted blobs. | 80 | Userspace only ever sees/stores encrypted blobs. |
81 | 81 | ||
82 | If you are unsure as to whether this is required, answer N. | 82 | If you are unsure as to whether this is required, answer N. |
83 | |||
84 | config KEYS_DEBUG_PROC_KEYS | ||
85 | bool "Enable the /proc/keys file by which keys may be viewed" | ||
86 | depends on KEYS | ||
87 | help | ||
88 | This option turns on support for the /proc/keys file - through which | ||
89 | can be listed all the keys on the system that are viewable by the | ||
90 | reading process. | ||
91 | |||
92 | The only keys included in the list are those that grant View | ||
93 | permission to the reading process whether or not it possesses them. | ||
94 | Note that LSM security checks are still performed, and may further | ||
95 | filter out keys that the current process is not authorised to view. | ||
96 | |||
97 | Only key attributes are listed here; key payloads are not included in | ||
98 | the resulting table. | ||
99 | |||
100 | If you are unsure as to whether this is required, answer N. | ||
diff --git a/security/keys/proc.c b/security/keys/proc.c index 972eeb336b81..f0611a6368cd 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <asm/errno.h> | 18 | #include <asm/errno.h> |
19 | #include "internal.h" | 19 | #include "internal.h" |
20 | 20 | ||
21 | #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS | ||
22 | static int proc_keys_open(struct inode *inode, struct file *file); | 21 | static int proc_keys_open(struct inode *inode, struct file *file); |
23 | static void *proc_keys_start(struct seq_file *p, loff_t *_pos); | 22 | static void *proc_keys_start(struct seq_file *p, loff_t *_pos); |
24 | static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos); | 23 | static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos); |
@@ -38,7 +37,6 @@ static const struct file_operations proc_keys_fops = { | |||
38 | .llseek = seq_lseek, | 37 | .llseek = seq_lseek, |
39 | .release = seq_release, | 38 | .release = seq_release, |
40 | }; | 39 | }; |
41 | #endif | ||
42 | 40 | ||
43 | static int proc_key_users_open(struct inode *inode, struct file *file); | 41 | static int proc_key_users_open(struct inode *inode, struct file *file); |
44 | static void *proc_key_users_start(struct seq_file *p, loff_t *_pos); | 42 | static void *proc_key_users_start(struct seq_file *p, loff_t *_pos); |
@@ -67,11 +65,9 @@ static int __init key_proc_init(void) | |||
67 | { | 65 | { |
68 | struct proc_dir_entry *p; | 66 | struct proc_dir_entry *p; |
69 | 67 | ||
70 | #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS | ||
71 | p = proc_create("keys", 0, NULL, &proc_keys_fops); | 68 | p = proc_create("keys", 0, NULL, &proc_keys_fops); |
72 | if (!p) | 69 | if (!p) |
73 | panic("Cannot create /proc/keys\n"); | 70 | panic("Cannot create /proc/keys\n"); |
74 | #endif | ||
75 | 71 | ||
76 | p = proc_create("key-users", 0, NULL, &proc_key_users_fops); | 72 | p = proc_create("key-users", 0, NULL, &proc_key_users_fops); |
77 | if (!p) | 73 | if (!p) |
@@ -86,8 +82,6 @@ __initcall(key_proc_init); | |||
86 | * Implement "/proc/keys" to provide a list of the keys on the system that | 82 | * Implement "/proc/keys" to provide a list of the keys on the system that |
87 | * grant View permission to the caller. | 83 | * grant View permission to the caller. |
88 | */ | 84 | */ |
89 | #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS | ||
90 | |||
91 | static struct rb_node *key_serial_next(struct seq_file *p, struct rb_node *n) | 85 | static struct rb_node *key_serial_next(struct seq_file *p, struct rb_node *n) |
92 | { | 86 | { |
93 | struct user_namespace *user_ns = seq_user_ns(p); | 87 | struct user_namespace *user_ns = seq_user_ns(p); |
@@ -275,8 +269,6 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
275 | return 0; | 269 | return 0; |
276 | } | 270 | } |
277 | 271 | ||
278 | #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ | ||
279 | |||
280 | static struct rb_node *__key_user_next(struct user_namespace *user_ns, struct rb_node *n) | 272 | static struct rb_node *__key_user_next(struct user_namespace *user_ns, struct rb_node *n) |
281 | { | 273 | { |
282 | while (n) { | 274 | while (n) { |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index a18f1fa6440b..afcc0aed9393 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -517,11 +517,6 @@ out: | |||
517 | return rc; | 517 | return rc; |
518 | } | 518 | } |
519 | 519 | ||
520 | static inline int avc_sidcmp(u32 x, u32 y) | ||
521 | { | ||
522 | return (x == y || x == SECSID_WILD || y == SECSID_WILD); | ||
523 | } | ||
524 | |||
525 | /** | 520 | /** |
526 | * avc_update_node Update an AVC entry | 521 | * avc_update_node Update an AVC entry |
527 | * @event : Updating event | 522 | * @event : Updating event |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6da7532893a1..87a915656eab 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -401,23 +401,14 @@ static int selinux_is_sblabel_mnt(struct super_block *sb) | |||
401 | { | 401 | { |
402 | struct superblock_security_struct *sbsec = sb->s_security; | 402 | struct superblock_security_struct *sbsec = sb->s_security; |
403 | 403 | ||
404 | if (sbsec->behavior == SECURITY_FS_USE_XATTR || | 404 | return sbsec->behavior == SECURITY_FS_USE_XATTR || |
405 | sbsec->behavior == SECURITY_FS_USE_TRANS || | 405 | sbsec->behavior == SECURITY_FS_USE_TRANS || |
406 | sbsec->behavior == SECURITY_FS_USE_TASK) | 406 | sbsec->behavior == SECURITY_FS_USE_TASK || |
407 | return 1; | 407 | /* Special handling. Genfs but also in-core setxattr handler */ |
408 | 408 | !strcmp(sb->s_type->name, "sysfs") || | |
409 | /* Special handling for sysfs. Is genfs but also has setxattr handler*/ | 409 | !strcmp(sb->s_type->name, "pstore") || |
410 | if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0) | 410 | !strcmp(sb->s_type->name, "debugfs") || |
411 | return 1; | 411 | !strcmp(sb->s_type->name, "rootfs"); |
412 | |||
413 | /* | ||
414 | * Special handling for rootfs. Is genfs but supports | ||
415 | * setting SELinux context on in-core inodes. | ||
416 | */ | ||
417 | if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0) | ||
418 | return 1; | ||
419 | |||
420 | return 0; | ||
421 | } | 412 | } |
422 | 413 | ||
423 | static int sb_finish_set_opts(struct super_block *sb) | 414 | static int sb_finish_set_opts(struct super_block *sb) |
@@ -456,10 +447,6 @@ static int sb_finish_set_opts(struct super_block *sb) | |||
456 | if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | 447 | if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
457 | printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", | 448 | printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", |
458 | sb->s_id, sb->s_type->name); | 449 | sb->s_id, sb->s_type->name); |
459 | else | ||
460 | printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", | ||
461 | sb->s_id, sb->s_type->name, | ||
462 | labeling_behaviors[sbsec->behavior-1]); | ||
463 | 450 | ||
464 | sbsec->flags |= SE_SBINITIALIZED; | 451 | sbsec->flags |= SE_SBINITIALIZED; |
465 | if (selinux_is_sblabel_mnt(sb)) | 452 | if (selinux_is_sblabel_mnt(sb)) |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index bc2a586f095c..74aa224267c1 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -289,12 +289,16 @@ static int policydb_init(struct policydb *p) | |||
289 | goto out; | 289 | goto out; |
290 | 290 | ||
291 | p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10)); | 291 | p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10)); |
292 | if (!p->filename_trans) | 292 | if (!p->filename_trans) { |
293 | rc = -ENOMEM; | ||
293 | goto out; | 294 | goto out; |
295 | } | ||
294 | 296 | ||
295 | p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); | 297 | p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); |
296 | if (!p->range_tr) | 298 | if (!p->range_tr) { |
299 | rc = -ENOMEM; | ||
297 | goto out; | 300 | goto out; |
301 | } | ||
298 | 302 | ||
299 | ebitmap_init(&p->filename_trans_ttypes); | 303 | ebitmap_init(&p->filename_trans_ttypes); |
300 | ebitmap_init(&p->policycaps); | 304 | ebitmap_init(&p->policycaps); |
diff --git a/security/smack/Kconfig b/security/smack/Kconfig index b065f9789418..271adae81796 100644 --- a/security/smack/Kconfig +++ b/security/smack/Kconfig | |||
@@ -28,3 +28,15 @@ config SECURITY_SMACK_BRINGUP | |||
28 | access rule set once the behavior is well understood. | 28 | access rule set once the behavior is well understood. |
29 | This is a superior mechanism to the oft abused | 29 | This is a superior mechanism to the oft abused |
30 | "permissive" mode of other systems. | 30 | "permissive" mode of other systems. |
31 | If you are unsure how to answer this question, answer N. | ||
32 | |||
33 | config SECURITY_SMACK_NETFILTER | ||
34 | bool "Packet marking using secmarks for netfilter" | ||
35 | depends on SECURITY_SMACK | ||
36 | depends on NETWORK_SECMARK | ||
37 | depends on NETFILTER | ||
38 | default n | ||
39 | help | ||
40 | This enables security marking of network packets using | ||
41 | Smack labels. | ||
42 | If you are unsure how to answer this question, answer N. | ||
diff --git a/security/smack/Makefile b/security/smack/Makefile index 67a63aaec827..ee2ebd504541 100644 --- a/security/smack/Makefile +++ b/security/smack/Makefile | |||
@@ -5,3 +5,4 @@ | |||
5 | obj-$(CONFIG_SECURITY_SMACK) := smack.o | 5 | obj-$(CONFIG_SECURITY_SMACK) := smack.o |
6 | 6 | ||
7 | smack-y := smack_lsm.o smack_access.o smackfs.o | 7 | smack-y := smack_lsm.o smack_access.o smackfs.o |
8 | smack-$(CONFIG_SECURITY_SMACK_NETFILTER) += smack_netfilter.o | ||
diff --git a/security/smack/smack.h b/security/smack/smack.h index b828a379377c..67ccb7b2b89b 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -248,6 +248,7 @@ struct smack_known *smk_find_entry(const char *); | |||
248 | /* | 248 | /* |
249 | * Shared data. | 249 | * Shared data. |
250 | */ | 250 | */ |
251 | extern int smack_enabled; | ||
251 | extern int smack_cipso_direct; | 252 | extern int smack_cipso_direct; |
252 | extern int smack_cipso_mapped; | 253 | extern int smack_cipso_mapped; |
253 | extern struct smack_known *smack_net_ambient; | 254 | extern struct smack_known *smack_net_ambient; |
@@ -298,6 +299,16 @@ static inline struct smack_known *smk_of_task(const struct task_smack *tsp) | |||
298 | return tsp->smk_task; | 299 | return tsp->smk_task; |
299 | } | 300 | } |
300 | 301 | ||
302 | static inline struct smack_known *smk_of_task_struct(const struct task_struct *t) | ||
303 | { | ||
304 | struct smack_known *skp; | ||
305 | |||
306 | rcu_read_lock(); | ||
307 | skp = smk_of_task(__task_cred(t)->security); | ||
308 | rcu_read_unlock(); | ||
309 | return skp; | ||
310 | } | ||
311 | |||
301 | /* | 312 | /* |
302 | * Present a pointer to the forked smack label entry in an task blob. | 313 | * Present a pointer to the forked smack label entry in an task blob. |
303 | */ | 314 | */ |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index f1b17a476e12..a0ccce4e46f8 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #include <linux/binfmts.h> | 43 | #include <linux/binfmts.h> |
44 | #include "smack.h" | 44 | #include "smack.h" |
45 | 45 | ||
46 | #define task_security(task) (task_cred_xxx((task), security)) | ||
47 | |||
48 | #define TRANS_TRUE "TRUE" | 46 | #define TRANS_TRUE "TRUE" |
49 | #define TRANS_TRUE_SIZE 4 | 47 | #define TRANS_TRUE_SIZE 4 |
50 | 48 | ||
@@ -52,8 +50,11 @@ | |||
52 | #define SMK_RECEIVING 1 | 50 | #define SMK_RECEIVING 1 |
53 | #define SMK_SENDING 2 | 51 | #define SMK_SENDING 2 |
54 | 52 | ||
53 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | ||
55 | LIST_HEAD(smk_ipv6_port_list); | 54 | LIST_HEAD(smk_ipv6_port_list); |
55 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | ||
56 | static struct kmem_cache *smack_inode_cache; | 56 | static struct kmem_cache *smack_inode_cache; |
57 | int smack_enabled; | ||
57 | 58 | ||
58 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | 59 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP |
59 | static void smk_bu_mode(int mode, char *s) | 60 | static void smk_bu_mode(int mode, char *s) |
@@ -120,7 +121,7 @@ static int smk_bu_current(char *note, struct smack_known *oskp, | |||
120 | static int smk_bu_task(struct task_struct *otp, int mode, int rc) | 121 | static int smk_bu_task(struct task_struct *otp, int mode, int rc) |
121 | { | 122 | { |
122 | struct task_smack *tsp = current_security(); | 123 | struct task_smack *tsp = current_security(); |
123 | struct task_smack *otsp = task_security(otp); | 124 | struct smack_known *smk_task = smk_of_task_struct(otp); |
124 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | 125 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
125 | 126 | ||
126 | if (rc <= 0) | 127 | if (rc <= 0) |
@@ -128,7 +129,7 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc) | |||
128 | 129 | ||
129 | smk_bu_mode(mode, acc); | 130 | smk_bu_mode(mode, acc); |
130 | pr_info("Smack Bringup: (%s %s %s) %s to %s\n", | 131 | pr_info("Smack Bringup: (%s %s %s) %s to %s\n", |
131 | tsp->smk_task->smk_known, otsp->smk_task->smk_known, acc, | 132 | tsp->smk_task->smk_known, smk_task->smk_known, acc, |
132 | current->comm, otp->comm); | 133 | current->comm, otp->comm); |
133 | return 0; | 134 | return 0; |
134 | } | 135 | } |
@@ -160,7 +161,7 @@ static int smk_bu_file(struct file *file, int mode, int rc) | |||
160 | { | 161 | { |
161 | struct task_smack *tsp = current_security(); | 162 | struct task_smack *tsp = current_security(); |
162 | struct smack_known *sskp = tsp->smk_task; | 163 | struct smack_known *sskp = tsp->smk_task; |
163 | struct inode *inode = file->f_inode; | 164 | struct inode *inode = file_inode(file); |
164 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | 165 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
165 | 166 | ||
166 | if (rc <= 0) | 167 | if (rc <= 0) |
@@ -168,7 +169,7 @@ static int smk_bu_file(struct file *file, int mode, int rc) | |||
168 | 169 | ||
169 | smk_bu_mode(mode, acc); | 170 | smk_bu_mode(mode, acc); |
170 | pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n", | 171 | pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n", |
171 | sskp->smk_known, (char *)file->f_security, acc, | 172 | sskp->smk_known, smk_of_inode(inode)->smk_known, acc, |
172 | inode->i_sb->s_id, inode->i_ino, file, | 173 | inode->i_sb->s_id, inode->i_ino, file, |
173 | current->comm); | 174 | current->comm); |
174 | return 0; | 175 | return 0; |
@@ -202,6 +203,7 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file, | |||
202 | 203 | ||
203 | /** | 204 | /** |
204 | * smk_fetch - Fetch the smack label from a file. | 205 | * smk_fetch - Fetch the smack label from a file. |
206 | * @name: type of the label (attribute) | ||
205 | * @ip: a pointer to the inode | 207 | * @ip: a pointer to the inode |
206 | * @dp: a pointer to the dentry | 208 | * @dp: a pointer to the dentry |
207 | * | 209 | * |
@@ -254,7 +256,9 @@ struct inode_smack *new_inode_smack(struct smack_known *skp) | |||
254 | 256 | ||
255 | /** | 257 | /** |
256 | * new_task_smack - allocate a task security blob | 258 | * new_task_smack - allocate a task security blob |
257 | * @smack: a pointer to the Smack label to use in the blob | 259 | * @task: a pointer to the Smack label for the running task |
260 | * @forked: a pointer to the Smack label for the forked task | ||
261 | * @gfp: type of the memory for the allocation | ||
258 | * | 262 | * |
259 | * Returns the new blob or NULL if there's no memory available | 263 | * Returns the new blob or NULL if there's no memory available |
260 | */ | 264 | */ |
@@ -277,8 +281,9 @@ static struct task_smack *new_task_smack(struct smack_known *task, | |||
277 | 281 | ||
278 | /** | 282 | /** |
279 | * smk_copy_rules - copy a rule set | 283 | * smk_copy_rules - copy a rule set |
280 | * @nhead - new rules header pointer | 284 | * @nhead: new rules header pointer |
281 | * @ohead - old rules header pointer | 285 | * @ohead: old rules header pointer |
286 | * @gfp: type of the memory for the allocation | ||
282 | * | 287 | * |
283 | * Returns 0 on success, -ENOMEM on error | 288 | * Returns 0 on success, -ENOMEM on error |
284 | */ | 289 | */ |
@@ -345,7 +350,8 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, | |||
345 | saip = &ad; | 350 | saip = &ad; |
346 | } | 351 | } |
347 | 352 | ||
348 | tsp = task_security(tracer); | 353 | rcu_read_lock(); |
354 | tsp = __task_cred(tracer)->security; | ||
349 | tracer_known = smk_of_task(tsp); | 355 | tracer_known = smk_of_task(tsp); |
350 | 356 | ||
351 | if ((mode & PTRACE_MODE_ATTACH) && | 357 | if ((mode & PTRACE_MODE_ATTACH) && |
@@ -365,11 +371,14 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, | |||
365 | tracee_known->smk_known, | 371 | tracee_known->smk_known, |
366 | 0, rc, saip); | 372 | 0, rc, saip); |
367 | 373 | ||
374 | rcu_read_unlock(); | ||
368 | return rc; | 375 | return rc; |
369 | } | 376 | } |
370 | 377 | ||
371 | /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ | 378 | /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ |
372 | rc = smk_tskacc(tsp, tracee_known, smk_ptrace_mode(mode), saip); | 379 | rc = smk_tskacc(tsp, tracee_known, smk_ptrace_mode(mode), saip); |
380 | |||
381 | rcu_read_unlock(); | ||
373 | return rc; | 382 | return rc; |
374 | } | 383 | } |
375 | 384 | ||
@@ -396,7 +405,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
396 | if (rc != 0) | 405 | if (rc != 0) |
397 | return rc; | 406 | return rc; |
398 | 407 | ||
399 | skp = smk_of_task(task_security(ctp)); | 408 | skp = smk_of_task_struct(ctp); |
400 | 409 | ||
401 | rc = smk_ptrace_rule_check(current, skp, mode, __func__); | 410 | rc = smk_ptrace_rule_check(current, skp, mode, __func__); |
402 | return rc; | 411 | return rc; |
@@ -796,7 +805,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
796 | if (name) | 805 | if (name) |
797 | *name = XATTR_SMACK_SUFFIX; | 806 | *name = XATTR_SMACK_SUFFIX; |
798 | 807 | ||
799 | if (value) { | 808 | if (value && len) { |
800 | rcu_read_lock(); | 809 | rcu_read_lock(); |
801 | may = smk_access_entry(skp->smk_known, dsp->smk_known, | 810 | may = smk_access_entry(skp->smk_known, dsp->smk_known, |
802 | &skp->smk_rules); | 811 | &skp->smk_rules); |
@@ -817,10 +826,9 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
817 | *value = kstrdup(isp->smk_known, GFP_NOFS); | 826 | *value = kstrdup(isp->smk_known, GFP_NOFS); |
818 | if (*value == NULL) | 827 | if (*value == NULL) |
819 | return -ENOMEM; | 828 | return -ENOMEM; |
820 | } | ||
821 | 829 | ||
822 | if (len) | ||
823 | *len = strlen(isp->smk_known); | 830 | *len = strlen(isp->smk_known); |
831 | } | ||
824 | 832 | ||
825 | return 0; | 833 | return 0; |
826 | } | 834 | } |
@@ -1344,6 +1352,9 @@ static int smack_file_permission(struct file *file, int mask) | |||
1344 | * The security blob for a file is a pointer to the master | 1352 | * The security blob for a file is a pointer to the master |
1345 | * label list, so no allocation is done. | 1353 | * label list, so no allocation is done. |
1346 | * | 1354 | * |
1355 | * f_security is the owner security information. It | ||
1356 | * isn't used on file access checks, it's for send_sigio. | ||
1357 | * | ||
1347 | * Returns 0 | 1358 | * Returns 0 |
1348 | */ | 1359 | */ |
1349 | static int smack_file_alloc_security(struct file *file) | 1360 | static int smack_file_alloc_security(struct file *file) |
@@ -1381,17 +1392,18 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, | |||
1381 | { | 1392 | { |
1382 | int rc = 0; | 1393 | int rc = 0; |
1383 | struct smk_audit_info ad; | 1394 | struct smk_audit_info ad; |
1395 | struct inode *inode = file_inode(file); | ||
1384 | 1396 | ||
1385 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1397 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1386 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1398 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1387 | 1399 | ||
1388 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | 1400 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
1389 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); | 1401 | rc = smk_curacc(smk_of_inode(inode), MAY_WRITE, &ad); |
1390 | rc = smk_bu_file(file, MAY_WRITE, rc); | 1402 | rc = smk_bu_file(file, MAY_WRITE, rc); |
1391 | } | 1403 | } |
1392 | 1404 | ||
1393 | if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) { | 1405 | if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) { |
1394 | rc = smk_curacc(file->f_security, MAY_READ, &ad); | 1406 | rc = smk_curacc(smk_of_inode(inode), MAY_READ, &ad); |
1395 | rc = smk_bu_file(file, MAY_READ, rc); | 1407 | rc = smk_bu_file(file, MAY_READ, rc); |
1396 | } | 1408 | } |
1397 | 1409 | ||
@@ -1409,10 +1421,11 @@ static int smack_file_lock(struct file *file, unsigned int cmd) | |||
1409 | { | 1421 | { |
1410 | struct smk_audit_info ad; | 1422 | struct smk_audit_info ad; |
1411 | int rc; | 1423 | int rc; |
1424 | struct inode *inode = file_inode(file); | ||
1412 | 1425 | ||
1413 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1426 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1414 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1427 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1415 | rc = smk_curacc(file->f_security, MAY_LOCK, &ad); | 1428 | rc = smk_curacc(smk_of_inode(inode), MAY_LOCK, &ad); |
1416 | rc = smk_bu_file(file, MAY_LOCK, rc); | 1429 | rc = smk_bu_file(file, MAY_LOCK, rc); |
1417 | return rc; | 1430 | return rc; |
1418 | } | 1431 | } |
@@ -1434,7 +1447,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1434 | { | 1447 | { |
1435 | struct smk_audit_info ad; | 1448 | struct smk_audit_info ad; |
1436 | int rc = 0; | 1449 | int rc = 0; |
1437 | 1450 | struct inode *inode = file_inode(file); | |
1438 | 1451 | ||
1439 | switch (cmd) { | 1452 | switch (cmd) { |
1440 | case F_GETLK: | 1453 | case F_GETLK: |
@@ -1443,14 +1456,14 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1443 | case F_SETLKW: | 1456 | case F_SETLKW: |
1444 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1457 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1445 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1458 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1446 | rc = smk_curacc(file->f_security, MAY_LOCK, &ad); | 1459 | rc = smk_curacc(smk_of_inode(inode), MAY_LOCK, &ad); |
1447 | rc = smk_bu_file(file, MAY_LOCK, rc); | 1460 | rc = smk_bu_file(file, MAY_LOCK, rc); |
1448 | break; | 1461 | break; |
1449 | case F_SETOWN: | 1462 | case F_SETOWN: |
1450 | case F_SETSIG: | 1463 | case F_SETSIG: |
1451 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1464 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1452 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1465 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1453 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); | 1466 | rc = smk_curacc(smk_of_inode(inode), MAY_WRITE, &ad); |
1454 | rc = smk_bu_file(file, MAY_WRITE, rc); | 1467 | rc = smk_bu_file(file, MAY_WRITE, rc); |
1455 | break; | 1468 | break; |
1456 | default: | 1469 | default: |
@@ -1568,14 +1581,10 @@ static int smack_mmap_file(struct file *file, | |||
1568 | * smack_file_set_fowner - set the file security blob value | 1581 | * smack_file_set_fowner - set the file security blob value |
1569 | * @file: object in question | 1582 | * @file: object in question |
1570 | * | 1583 | * |
1571 | * Returns 0 | ||
1572 | * Further research may be required on this one. | ||
1573 | */ | 1584 | */ |
1574 | static void smack_file_set_fowner(struct file *file) | 1585 | static void smack_file_set_fowner(struct file *file) |
1575 | { | 1586 | { |
1576 | struct smack_known *skp = smk_of_current(); | 1587 | file->f_security = smk_of_current(); |
1577 | |||
1578 | file->f_security = skp; | ||
1579 | } | 1588 | } |
1580 | 1589 | ||
1581 | /** | 1590 | /** |
@@ -1627,6 +1636,7 @@ static int smack_file_receive(struct file *file) | |||
1627 | int rc; | 1636 | int rc; |
1628 | int may = 0; | 1637 | int may = 0; |
1629 | struct smk_audit_info ad; | 1638 | struct smk_audit_info ad; |
1639 | struct inode *inode = file_inode(file); | ||
1630 | 1640 | ||
1631 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1641 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1632 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1642 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
@@ -1638,7 +1648,7 @@ static int smack_file_receive(struct file *file) | |||
1638 | if (file->f_mode & FMODE_WRITE) | 1648 | if (file->f_mode & FMODE_WRITE) |
1639 | may |= MAY_WRITE; | 1649 | may |= MAY_WRITE; |
1640 | 1650 | ||
1641 | rc = smk_curacc(file->f_security, may, &ad); | 1651 | rc = smk_curacc(smk_of_inode(inode), may, &ad); |
1642 | rc = smk_bu_file(file, may, rc); | 1652 | rc = smk_bu_file(file, may, rc); |
1643 | return rc; | 1653 | return rc; |
1644 | } | 1654 | } |
@@ -1658,21 +1668,17 @@ static int smack_file_receive(struct file *file) | |||
1658 | static int smack_file_open(struct file *file, const struct cred *cred) | 1668 | static int smack_file_open(struct file *file, const struct cred *cred) |
1659 | { | 1669 | { |
1660 | struct task_smack *tsp = cred->security; | 1670 | struct task_smack *tsp = cred->security; |
1661 | struct inode_smack *isp = file_inode(file)->i_security; | 1671 | struct inode *inode = file_inode(file); |
1662 | struct smk_audit_info ad; | 1672 | struct smk_audit_info ad; |
1663 | int rc; | 1673 | int rc; |
1664 | 1674 | ||
1665 | if (smack_privileged(CAP_MAC_OVERRIDE)) { | 1675 | if (smack_privileged(CAP_MAC_OVERRIDE)) |
1666 | file->f_security = isp->smk_inode; | ||
1667 | return 0; | 1676 | return 0; |
1668 | } | ||
1669 | 1677 | ||
1670 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1678 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1671 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1679 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1672 | rc = smk_access(tsp->smk_task, isp->smk_inode, MAY_READ, &ad); | 1680 | rc = smk_access(tsp->smk_task, smk_of_inode(inode), MAY_READ, &ad); |
1673 | rc = smk_bu_credfile(cred, file, MAY_READ, rc); | 1681 | rc = smk_bu_credfile(cred, file, MAY_READ, rc); |
1674 | if (rc == 0) | ||
1675 | file->f_security = isp->smk_inode; | ||
1676 | 1682 | ||
1677 | return rc; | 1683 | return rc; |
1678 | } | 1684 | } |
@@ -1826,7 +1832,7 @@ static int smk_curacc_on_task(struct task_struct *p, int access, | |||
1826 | const char *caller) | 1832 | const char *caller) |
1827 | { | 1833 | { |
1828 | struct smk_audit_info ad; | 1834 | struct smk_audit_info ad; |
1829 | struct smack_known *skp = smk_of_task(task_security(p)); | 1835 | struct smack_known *skp = smk_of_task_struct(p); |
1830 | int rc; | 1836 | int rc; |
1831 | 1837 | ||
1832 | smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); | 1838 | smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); |
@@ -1879,7 +1885,7 @@ static int smack_task_getsid(struct task_struct *p) | |||
1879 | */ | 1885 | */ |
1880 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) | 1886 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) |
1881 | { | 1887 | { |
1882 | struct smack_known *skp = smk_of_task(task_security(p)); | 1888 | struct smack_known *skp = smk_of_task_struct(p); |
1883 | 1889 | ||
1884 | *secid = skp->smk_secid; | 1890 | *secid = skp->smk_secid; |
1885 | } | 1891 | } |
@@ -1986,7 +1992,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1986 | { | 1992 | { |
1987 | struct smk_audit_info ad; | 1993 | struct smk_audit_info ad; |
1988 | struct smack_known *skp; | 1994 | struct smack_known *skp; |
1989 | struct smack_known *tkp = smk_of_task(task_security(p)); | 1995 | struct smack_known *tkp = smk_of_task_struct(p); |
1990 | int rc; | 1996 | int rc; |
1991 | 1997 | ||
1992 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1998 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
@@ -2040,7 +2046,7 @@ static int smack_task_wait(struct task_struct *p) | |||
2040 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | 2046 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) |
2041 | { | 2047 | { |
2042 | struct inode_smack *isp = inode->i_security; | 2048 | struct inode_smack *isp = inode->i_security; |
2043 | struct smack_known *skp = smk_of_task(task_security(p)); | 2049 | struct smack_known *skp = smk_of_task_struct(p); |
2044 | 2050 | ||
2045 | isp->smk_inode = skp; | 2051 | isp->smk_inode = skp; |
2046 | } | 2052 | } |
@@ -2212,6 +2218,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
2212 | return smack_netlabel(sk, sk_lbl); | 2218 | return smack_netlabel(sk, sk_lbl); |
2213 | } | 2219 | } |
2214 | 2220 | ||
2221 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | ||
2215 | /** | 2222 | /** |
2216 | * smk_ipv6_port_label - Smack port access table management | 2223 | * smk_ipv6_port_label - Smack port access table management |
2217 | * @sock: socket | 2224 | * @sock: socket |
@@ -2361,6 +2368,7 @@ auditout: | |||
2361 | rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc); | 2368 | rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc); |
2362 | return rc; | 2369 | return rc; |
2363 | } | 2370 | } |
2371 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | ||
2364 | 2372 | ||
2365 | /** | 2373 | /** |
2366 | * smack_inode_setsecurity - set smack xattrs | 2374 | * smack_inode_setsecurity - set smack xattrs |
@@ -2421,8 +2429,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
2421 | } else | 2429 | } else |
2422 | return -EOPNOTSUPP; | 2430 | return -EOPNOTSUPP; |
2423 | 2431 | ||
2432 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | ||
2424 | if (sock->sk->sk_family == PF_INET6) | 2433 | if (sock->sk->sk_family == PF_INET6) |
2425 | smk_ipv6_port_label(sock, NULL); | 2434 | smk_ipv6_port_label(sock, NULL); |
2435 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | ||
2426 | 2436 | ||
2427 | return 0; | 2437 | return 0; |
2428 | } | 2438 | } |
@@ -2450,6 +2460,7 @@ static int smack_socket_post_create(struct socket *sock, int family, | |||
2450 | return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); | 2460 | return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); |
2451 | } | 2461 | } |
2452 | 2462 | ||
2463 | #ifndef CONFIG_SECURITY_SMACK_NETFILTER | ||
2453 | /** | 2464 | /** |
2454 | * smack_socket_bind - record port binding information. | 2465 | * smack_socket_bind - record port binding information. |
2455 | * @sock: the socket | 2466 | * @sock: the socket |
@@ -2463,11 +2474,14 @@ static int smack_socket_post_create(struct socket *sock, int family, | |||
2463 | static int smack_socket_bind(struct socket *sock, struct sockaddr *address, | 2474 | static int smack_socket_bind(struct socket *sock, struct sockaddr *address, |
2464 | int addrlen) | 2475 | int addrlen) |
2465 | { | 2476 | { |
2477 | #if IS_ENABLED(CONFIG_IPV6) | ||
2466 | if (sock->sk != NULL && sock->sk->sk_family == PF_INET6) | 2478 | if (sock->sk != NULL && sock->sk->sk_family == PF_INET6) |
2467 | smk_ipv6_port_label(sock, address); | 2479 | smk_ipv6_port_label(sock, address); |
2480 | #endif | ||
2468 | 2481 | ||
2469 | return 0; | 2482 | return 0; |
2470 | } | 2483 | } |
2484 | #endif /* !CONFIG_SECURITY_SMACK_NETFILTER */ | ||
2471 | 2485 | ||
2472 | /** | 2486 | /** |
2473 | * smack_socket_connect - connect access check | 2487 | * smack_socket_connect - connect access check |
@@ -2496,8 +2510,10 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, | |||
2496 | case PF_INET6: | 2510 | case PF_INET6: |
2497 | if (addrlen < sizeof(struct sockaddr_in6)) | 2511 | if (addrlen < sizeof(struct sockaddr_in6)) |
2498 | return -EINVAL; | 2512 | return -EINVAL; |
2513 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | ||
2499 | rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap, | 2514 | rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap, |
2500 | SMK_CONNECTING); | 2515 | SMK_CONNECTING); |
2516 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | ||
2501 | break; | 2517 | break; |
2502 | } | 2518 | } |
2503 | return rc; | 2519 | return rc; |
@@ -3033,7 +3049,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
3033 | * of the superblock. | 3049 | * of the superblock. |
3034 | */ | 3050 | */ |
3035 | if (opt_dentry->d_parent == opt_dentry) { | 3051 | if (opt_dentry->d_parent == opt_dentry) { |
3036 | if (sbp->s_magic == CGROUP_SUPER_MAGIC) { | 3052 | switch (sbp->s_magic) { |
3053 | case CGROUP_SUPER_MAGIC: | ||
3037 | /* | 3054 | /* |
3038 | * The cgroup filesystem is never mounted, | 3055 | * The cgroup filesystem is never mounted, |
3039 | * so there's no opportunity to set the mount | 3056 | * so there's no opportunity to set the mount |
@@ -3041,8 +3058,19 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
3041 | */ | 3058 | */ |
3042 | sbsp->smk_root = &smack_known_star; | 3059 | sbsp->smk_root = &smack_known_star; |
3043 | sbsp->smk_default = &smack_known_star; | 3060 | sbsp->smk_default = &smack_known_star; |
3061 | isp->smk_inode = sbsp->smk_root; | ||
3062 | break; | ||
3063 | case TMPFS_MAGIC: | ||
3064 | /* | ||
3065 | * What about shmem/tmpfs anonymous files with dentry | ||
3066 | * obtained from d_alloc_pseudo()? | ||
3067 | */ | ||
3068 | isp->smk_inode = smk_of_current(); | ||
3069 | break; | ||
3070 | default: | ||
3071 | isp->smk_inode = sbsp->smk_root; | ||
3072 | break; | ||
3044 | } | 3073 | } |
3045 | isp->smk_inode = sbsp->smk_root; | ||
3046 | isp->smk_flags |= SMK_INODE_INSTANT; | 3074 | isp->smk_flags |= SMK_INODE_INSTANT; |
3047 | goto unlockandout; | 3075 | goto unlockandout; |
3048 | } | 3076 | } |
@@ -3200,7 +3228,7 @@ unlockandout: | |||
3200 | */ | 3228 | */ |
3201 | static int smack_getprocattr(struct task_struct *p, char *name, char **value) | 3229 | static int smack_getprocattr(struct task_struct *p, char *name, char **value) |
3202 | { | 3230 | { |
3203 | struct smack_known *skp = smk_of_task(task_security(p)); | 3231 | struct smack_known *skp = smk_of_task_struct(p); |
3204 | char *cp; | 3232 | char *cp; |
3205 | int slen; | 3233 | int slen; |
3206 | 3234 | ||
@@ -3297,7 +3325,7 @@ static int smack_unix_stream_connect(struct sock *sock, | |||
3297 | 3325 | ||
3298 | if (!smack_privileged(CAP_MAC_OVERRIDE)) { | 3326 | if (!smack_privileged(CAP_MAC_OVERRIDE)) { |
3299 | skp = ssp->smk_out; | 3327 | skp = ssp->smk_out; |
3300 | okp = osp->smk_out; | 3328 | okp = osp->smk_in; |
3301 | #ifdef CONFIG_AUDIT | 3329 | #ifdef CONFIG_AUDIT |
3302 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | 3330 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
3303 | smk_ad_setfield_u_net_sk(&ad, other); | 3331 | smk_ad_setfield_u_net_sk(&ad, other); |
@@ -3305,7 +3333,9 @@ static int smack_unix_stream_connect(struct sock *sock, | |||
3305 | rc = smk_access(skp, okp, MAY_WRITE, &ad); | 3333 | rc = smk_access(skp, okp, MAY_WRITE, &ad); |
3306 | rc = smk_bu_note("UDS connect", skp, okp, MAY_WRITE, rc); | 3334 | rc = smk_bu_note("UDS connect", skp, okp, MAY_WRITE, rc); |
3307 | if (rc == 0) { | 3335 | if (rc == 0) { |
3308 | rc = smk_access(okp, skp, MAY_WRITE, NULL); | 3336 | okp = osp->smk_out; |
3337 | skp = ssp->smk_in; | ||
3338 | rc = smk_access(okp, skp, MAY_WRITE, &ad); | ||
3309 | rc = smk_bu_note("UDS connect", okp, skp, | 3339 | rc = smk_bu_note("UDS connect", okp, skp, |
3310 | MAY_WRITE, rc); | 3340 | MAY_WRITE, rc); |
3311 | } | 3341 | } |
@@ -3366,7 +3396,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
3366 | int size) | 3396 | int size) |
3367 | { | 3397 | { |
3368 | struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; | 3398 | struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; |
3399 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | ||
3369 | struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name; | 3400 | struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name; |
3401 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | ||
3370 | int rc = 0; | 3402 | int rc = 0; |
3371 | 3403 | ||
3372 | /* | 3404 | /* |
@@ -3380,7 +3412,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
3380 | rc = smack_netlabel_send(sock->sk, sip); | 3412 | rc = smack_netlabel_send(sock->sk, sip); |
3381 | break; | 3413 | break; |
3382 | case AF_INET6: | 3414 | case AF_INET6: |
3415 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | ||
3383 | rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING); | 3416 | rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING); |
3417 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | ||
3384 | break; | 3418 | break; |
3385 | } | 3419 | } |
3386 | return rc; | 3420 | return rc; |
@@ -3471,6 +3505,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, | |||
3471 | return smack_net_ambient; | 3505 | return smack_net_ambient; |
3472 | } | 3506 | } |
3473 | 3507 | ||
3508 | #if IS_ENABLED(CONFIG_IPV6) | ||
3474 | static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip) | 3509 | static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip) |
3475 | { | 3510 | { |
3476 | u8 nexthdr; | 3511 | u8 nexthdr; |
@@ -3517,6 +3552,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip) | |||
3517 | } | 3552 | } |
3518 | return proto; | 3553 | return proto; |
3519 | } | 3554 | } |
3555 | #endif /* CONFIG_IPV6 */ | ||
3520 | 3556 | ||
3521 | /** | 3557 | /** |
3522 | * smack_socket_sock_rcv_skb - Smack packet delivery access check | 3558 | * smack_socket_sock_rcv_skb - Smack packet delivery access check |
@@ -3529,15 +3565,30 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
3529 | { | 3565 | { |
3530 | struct netlbl_lsm_secattr secattr; | 3566 | struct netlbl_lsm_secattr secattr; |
3531 | struct socket_smack *ssp = sk->sk_security; | 3567 | struct socket_smack *ssp = sk->sk_security; |
3532 | struct smack_known *skp; | 3568 | struct smack_known *skp = NULL; |
3533 | struct sockaddr_in6 sadd; | ||
3534 | int rc = 0; | 3569 | int rc = 0; |
3535 | struct smk_audit_info ad; | 3570 | struct smk_audit_info ad; |
3536 | #ifdef CONFIG_AUDIT | 3571 | #ifdef CONFIG_AUDIT |
3537 | struct lsm_network_audit net; | 3572 | struct lsm_network_audit net; |
3538 | #endif | 3573 | #endif |
3574 | #if IS_ENABLED(CONFIG_IPV6) | ||
3575 | struct sockaddr_in6 sadd; | ||
3576 | int proto; | ||
3577 | #endif /* CONFIG_IPV6 */ | ||
3578 | |||
3539 | switch (sk->sk_family) { | 3579 | switch (sk->sk_family) { |
3540 | case PF_INET: | 3580 | case PF_INET: |
3581 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | ||
3582 | /* | ||
3583 | * If there is a secmark use it rather than the CIPSO label. | ||
3584 | * If there is no secmark fall back to CIPSO. | ||
3585 | * The secmark is assumed to reflect policy better. | ||
3586 | */ | ||
3587 | if (skb && skb->secmark != 0) { | ||
3588 | skp = smack_from_secid(skb->secmark); | ||
3589 | goto access_check; | ||
3590 | } | ||
3591 | #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ | ||
3541 | /* | 3592 | /* |
3542 | * Translate what netlabel gave us. | 3593 | * Translate what netlabel gave us. |
3543 | */ | 3594 | */ |
@@ -3551,6 +3602,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
3551 | 3602 | ||
3552 | netlbl_secattr_destroy(&secattr); | 3603 | netlbl_secattr_destroy(&secattr); |
3553 | 3604 | ||
3605 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | ||
3606 | access_check: | ||
3607 | #endif | ||
3554 | #ifdef CONFIG_AUDIT | 3608 | #ifdef CONFIG_AUDIT |
3555 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | 3609 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
3556 | ad.a.u.net->family = sk->sk_family; | 3610 | ad.a.u.net->family = sk->sk_family; |
@@ -3569,14 +3623,32 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
3569 | if (rc != 0) | 3623 | if (rc != 0) |
3570 | netlbl_skbuff_err(skb, rc, 0); | 3624 | netlbl_skbuff_err(skb, rc, 0); |
3571 | break; | 3625 | break; |
3626 | #if IS_ENABLED(CONFIG_IPV6) | ||
3572 | case PF_INET6: | 3627 | case PF_INET6: |
3573 | rc = smk_skb_to_addr_ipv6(skb, &sadd); | 3628 | proto = smk_skb_to_addr_ipv6(skb, &sadd); |
3574 | if (rc == IPPROTO_UDP || rc == IPPROTO_TCP) | 3629 | if (proto != IPPROTO_UDP && proto != IPPROTO_TCP) |
3575 | rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING); | 3630 | break; |
3631 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | ||
3632 | if (skb && skb->secmark != 0) | ||
3633 | skp = smack_from_secid(skb->secmark); | ||
3576 | else | 3634 | else |
3577 | rc = 0; | 3635 | skp = smack_net_ambient; |
3636 | #ifdef CONFIG_AUDIT | ||
3637 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | ||
3638 | ad.a.u.net->family = sk->sk_family; | ||
3639 | ad.a.u.net->netif = skb->skb_iif; | ||
3640 | ipv6_skb_to_auditdata(skb, &ad.a, NULL); | ||
3641 | #endif /* CONFIG_AUDIT */ | ||
3642 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); | ||
3643 | rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in, | ||
3644 | MAY_WRITE, rc); | ||
3645 | #else /* CONFIG_SECURITY_SMACK_NETFILTER */ | ||
3646 | rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING); | ||
3647 | #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ | ||
3578 | break; | 3648 | break; |
3649 | #endif /* CONFIG_IPV6 */ | ||
3579 | } | 3650 | } |
3651 | |||
3580 | return rc; | 3652 | return rc; |
3581 | } | 3653 | } |
3582 | 3654 | ||
@@ -3638,16 +3710,25 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
3638 | if (skb != NULL) { | 3710 | if (skb != NULL) { |
3639 | if (skb->protocol == htons(ETH_P_IP)) | 3711 | if (skb->protocol == htons(ETH_P_IP)) |
3640 | family = PF_INET; | 3712 | family = PF_INET; |
3713 | #if IS_ENABLED(CONFIG_IPV6) | ||
3641 | else if (skb->protocol == htons(ETH_P_IPV6)) | 3714 | else if (skb->protocol == htons(ETH_P_IPV6)) |
3642 | family = PF_INET6; | 3715 | family = PF_INET6; |
3716 | #endif /* CONFIG_IPV6 */ | ||
3643 | } | 3717 | } |
3644 | if (family == PF_UNSPEC && sock != NULL) | 3718 | if (family == PF_UNSPEC && sock != NULL) |
3645 | family = sock->sk->sk_family; | 3719 | family = sock->sk->sk_family; |
3646 | 3720 | ||
3647 | if (family == PF_UNIX) { | 3721 | switch (family) { |
3722 | case PF_UNIX: | ||
3648 | ssp = sock->sk->sk_security; | 3723 | ssp = sock->sk->sk_security; |
3649 | s = ssp->smk_out->smk_secid; | 3724 | s = ssp->smk_out->smk_secid; |
3650 | } else if (family == PF_INET || family == PF_INET6) { | 3725 | break; |
3726 | case PF_INET: | ||
3727 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | ||
3728 | s = skb->secmark; | ||
3729 | if (s != 0) | ||
3730 | break; | ||
3731 | #endif | ||
3651 | /* | 3732 | /* |
3652 | * Translate what netlabel gave us. | 3733 | * Translate what netlabel gave us. |
3653 | */ | 3734 | */ |
@@ -3660,6 +3741,14 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
3660 | s = skp->smk_secid; | 3741 | s = skp->smk_secid; |
3661 | } | 3742 | } |
3662 | netlbl_secattr_destroy(&secattr); | 3743 | netlbl_secattr_destroy(&secattr); |
3744 | break; | ||
3745 | #if IS_ENABLED(CONFIG_IPV6) | ||
3746 | case PF_INET6: | ||
3747 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | ||
3748 | s = skb->secmark; | ||
3749 | #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ | ||
3750 | break; | ||
3751 | #endif /* CONFIG_IPV6 */ | ||
3663 | } | 3752 | } |
3664 | *secid = s; | 3753 | *secid = s; |
3665 | if (s == 0) | 3754 | if (s == 0) |
@@ -3715,6 +3804,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3715 | struct lsm_network_audit net; | 3804 | struct lsm_network_audit net; |
3716 | #endif | 3805 | #endif |
3717 | 3806 | ||
3807 | #if IS_ENABLED(CONFIG_IPV6) | ||
3718 | if (family == PF_INET6) { | 3808 | if (family == PF_INET6) { |
3719 | /* | 3809 | /* |
3720 | * Handle mapped IPv4 packets arriving | 3810 | * Handle mapped IPv4 packets arriving |
@@ -3726,6 +3816,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3726 | else | 3816 | else |
3727 | return 0; | 3817 | return 0; |
3728 | } | 3818 | } |
3819 | #endif /* CONFIG_IPV6 */ | ||
3729 | 3820 | ||
3730 | netlbl_secattr_init(&secattr); | 3821 | netlbl_secattr_init(&secattr); |
3731 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | 3822 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
@@ -3834,11 +3925,11 @@ static void smack_key_free(struct key *key) | |||
3834 | key->security = NULL; | 3925 | key->security = NULL; |
3835 | } | 3926 | } |
3836 | 3927 | ||
3837 | /* | 3928 | /** |
3838 | * smack_key_permission - Smack access on a key | 3929 | * smack_key_permission - Smack access on a key |
3839 | * @key_ref: gets to the object | 3930 | * @key_ref: gets to the object |
3840 | * @cred: the credentials to use | 3931 | * @cred: the credentials to use |
3841 | * @perm: unused | 3932 | * @perm: requested key permissions |
3842 | * | 3933 | * |
3843 | * Return 0 if the task has read and write to the object, | 3934 | * Return 0 if the task has read and write to the object, |
3844 | * an error code otherwise | 3935 | * an error code otherwise |
@@ -4184,7 +4275,9 @@ struct security_operations smack_ops = { | |||
4184 | .unix_may_send = smack_unix_may_send, | 4275 | .unix_may_send = smack_unix_may_send, |
4185 | 4276 | ||
4186 | .socket_post_create = smack_socket_post_create, | 4277 | .socket_post_create = smack_socket_post_create, |
4278 | #ifndef CONFIG_SECURITY_SMACK_NETFILTER | ||
4187 | .socket_bind = smack_socket_bind, | 4279 | .socket_bind = smack_socket_bind, |
4280 | #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ | ||
4188 | .socket_connect = smack_socket_connect, | 4281 | .socket_connect = smack_socket_connect, |
4189 | .socket_sendmsg = smack_socket_sendmsg, | 4282 | .socket_sendmsg = smack_socket_sendmsg, |
4190 | .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, | 4283 | .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, |
@@ -4265,6 +4358,8 @@ static __init int smack_init(void) | |||
4265 | if (!security_module_enable(&smack_ops)) | 4358 | if (!security_module_enable(&smack_ops)) |
4266 | return 0; | 4359 | return 0; |
4267 | 4360 | ||
4361 | smack_enabled = 1; | ||
4362 | |||
4268 | smack_inode_cache = KMEM_CACHE(inode_smack, 0); | 4363 | smack_inode_cache = KMEM_CACHE(inode_smack, 0); |
4269 | if (!smack_inode_cache) | 4364 | if (!smack_inode_cache) |
4270 | return -ENOMEM; | 4365 | return -ENOMEM; |
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c new file mode 100644 index 000000000000..c952632afb0d --- /dev/null +++ b/security/smack/smack_netfilter.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Simplified MAC Kernel (smack) security module | ||
3 | * | ||
4 | * This file contains the Smack netfilter implementation | ||
5 | * | ||
6 | * Author: | ||
7 | * Casey Schaufler <casey@schaufler-ca.com> | ||
8 | * | ||
9 | * Copyright (C) 2014 Casey Schaufler <casey@schaufler-ca.com> | ||
10 | * Copyright (C) 2014 Intel Corporation. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2, | ||
14 | * as published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/netfilter_ipv4.h> | ||
18 | #include <linux/netfilter_ipv6.h> | ||
19 | #include <linux/netdevice.h> | ||
20 | #include "smack.h" | ||
21 | |||
22 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
23 | |||
24 | static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops, | ||
25 | struct sk_buff *skb, | ||
26 | const struct net_device *in, | ||
27 | const struct net_device *out, | ||
28 | int (*okfn)(struct sk_buff *)) | ||
29 | { | ||
30 | struct socket_smack *ssp; | ||
31 | struct smack_known *skp; | ||
32 | |||
33 | if (skb && skb->sk && skb->sk->sk_security) { | ||
34 | ssp = skb->sk->sk_security; | ||
35 | skp = ssp->smk_out; | ||
36 | skb->secmark = skp->smk_secid; | ||
37 | } | ||
38 | |||
39 | return NF_ACCEPT; | ||
40 | } | ||
41 | #endif /* IPV6 */ | ||
42 | |||
43 | static unsigned int smack_ipv4_output(const struct nf_hook_ops *ops, | ||
44 | struct sk_buff *skb, | ||
45 | const struct net_device *in, | ||
46 | const struct net_device *out, | ||
47 | int (*okfn)(struct sk_buff *)) | ||
48 | { | ||
49 | struct socket_smack *ssp; | ||
50 | struct smack_known *skp; | ||
51 | |||
52 | if (skb && skb->sk && skb->sk->sk_security) { | ||
53 | ssp = skb->sk->sk_security; | ||
54 | skp = ssp->smk_out; | ||
55 | skb->secmark = skp->smk_secid; | ||
56 | } | ||
57 | |||
58 | return NF_ACCEPT; | ||
59 | } | ||
60 | |||
61 | static struct nf_hook_ops smack_nf_ops[] = { | ||
62 | { | ||
63 | .hook = smack_ipv4_output, | ||
64 | .owner = THIS_MODULE, | ||
65 | .pf = NFPROTO_IPV4, | ||
66 | .hooknum = NF_INET_LOCAL_OUT, | ||
67 | .priority = NF_IP_PRI_SELINUX_FIRST, | ||
68 | }, | ||
69 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
70 | { | ||
71 | .hook = smack_ipv6_output, | ||
72 | .owner = THIS_MODULE, | ||
73 | .pf = NFPROTO_IPV6, | ||
74 | .hooknum = NF_INET_LOCAL_OUT, | ||
75 | .priority = NF_IP6_PRI_SELINUX_FIRST, | ||
76 | }, | ||
77 | #endif /* IPV6 */ | ||
78 | }; | ||
79 | |||
80 | static int __init smack_nf_ip_init(void) | ||
81 | { | ||
82 | int err; | ||
83 | |||
84 | if (smack_enabled == 0) | ||
85 | return 0; | ||
86 | |||
87 | printk(KERN_DEBUG "Smack: Registering netfilter hooks\n"); | ||
88 | |||
89 | err = nf_register_hooks(smack_nf_ops, ARRAY_SIZE(smack_nf_ops)); | ||
90 | if (err) | ||
91 | pr_info("Smack: nf_register_hooks: error %d\n", err); | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | __initcall(smack_nf_ip_init); | ||