Commit 8cc748aa authored by Linus Torvalds's avatar Linus Torvalds

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()
  ...
parents 7184487f 04f81f01
What: /sys/class/misc/tpmX/device/ What: /sys/class/tpm/tpmX/device/
Date: April 2005 Date: April 2005
KernelVersion: 2.6.12 KernelVersion: 2.6.12
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
...@@ -6,7 +6,7 @@ Description: The device/ directory under a specific TPM instance exposes ...@@ -6,7 +6,7 @@ Description: The device/ directory under a specific TPM instance exposes
the properties of that TPM chip the properties of that TPM chip
What: /sys/class/misc/tpmX/device/active What: /sys/class/tpm/tpmX/device/active
Date: April 2006 Date: April 2006
KernelVersion: 2.6.17 KernelVersion: 2.6.17
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
...@@ -18,7 +18,7 @@ Description: The "active" property prints a '1' if the TPM chip is accepting ...@@ -18,7 +18,7 @@ Description: The "active" property prints a '1' if the TPM chip is accepting
section 17 for more information on which commands are section 17 for more information on which commands are
available. available.
What: /sys/class/misc/tpmX/device/cancel What: /sys/class/tpm/tpmX/device/cancel
Date: June 2005 Date: June 2005
KernelVersion: 2.6.13 KernelVersion: 2.6.13
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
...@@ -26,7 +26,7 @@ Description: The "cancel" property allows you to cancel the currently ...@@ -26,7 +26,7 @@ Description: The "cancel" property allows you to cancel the currently
pending TPM command. Writing any value to cancel will call the pending TPM command. Writing any value to cancel will call the
TPM vendor specific cancel operation. TPM vendor specific cancel operation.
What: /sys/class/misc/tpmX/device/caps What: /sys/class/tpm/tpmX/device/caps
Date: April 2005 Date: April 2005
KernelVersion: 2.6.12 KernelVersion: 2.6.12
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
...@@ -43,7 +43,7 @@ Description: The "caps" property contains TPM manufacturer and version info. ...@@ -43,7 +43,7 @@ Description: The "caps" property contains TPM manufacturer and version info.
the chip supports. Firmware version is that of the chip and the chip supports. Firmware version is that of the chip and
is manufacturer specific. is manufacturer specific.
What: /sys/class/misc/tpmX/device/durations What: /sys/class/tpm/tpmX/device/durations
Date: March 2011 Date: March 2011
KernelVersion: 3.1 KernelVersion: 3.1
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
...@@ -66,7 +66,7 @@ Description: The "durations" property shows the 3 vendor-specific values ...@@ -66,7 +66,7 @@ Description: The "durations" property shows the 3 vendor-specific values
scaled to be displayed in usecs. In this case "[adjusted]" scaled to be displayed in usecs. In this case "[adjusted]"
will be displayed in place of "[original]". will be displayed in place of "[original]".
What: /sys/class/misc/tpmX/device/enabled What: /sys/class/tpm/tpmX/device/enabled
Date: April 2006 Date: April 2006
KernelVersion: 2.6.17 KernelVersion: 2.6.17
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
...@@ -75,7 +75,7 @@ Description: The "enabled" property prints a '1' if the TPM chip is enabled, ...@@ -75,7 +75,7 @@ Description: The "enabled" property prints a '1' if the TPM chip is enabled,
may be visible but produce a '0' after some operation that may be visible but produce a '0' after some operation that
disables the TPM. disables the TPM.
What: /sys/class/misc/tpmX/device/owned What: /sys/class/tpm/tpmX/device/owned
Date: April 2006 Date: April 2006
KernelVersion: 2.6.17 KernelVersion: 2.6.17
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
...@@ -83,7 +83,7 @@ Description: The "owned" property produces a '1' if the TPM_TakeOwnership ...@@ -83,7 +83,7 @@ Description: The "owned" property produces a '1' if the TPM_TakeOwnership
ordinal has been executed successfully in the chip. A '0' ordinal has been executed successfully in the chip. A '0'
indicates that ownership hasn't been taken. indicates that ownership hasn't been taken.
What: /sys/class/misc/tpmX/device/pcrs What: /sys/class/tpm/tpmX/device/pcrs
Date: April 2005 Date: April 2005
KernelVersion: 2.6.12 KernelVersion: 2.6.12
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
...@@ -106,7 +106,7 @@ Description: The "pcrs" property will dump the current value of all Platform ...@@ -106,7 +106,7 @@ Description: The "pcrs" property will dump the current value of all Platform
1.2 chips, PCRs represent SHA-1 hashes, which are 20 bytes 1.2 chips, PCRs represent SHA-1 hashes, which are 20 bytes
long. Use the "caps" property to determine TPM version. long. Use the "caps" property to determine TPM version.
What: /sys/class/misc/tpmX/device/pubek What: /sys/class/tpm/tpmX/device/pubek
Date: April 2005 Date: April 2005
KernelVersion: 2.6.12 KernelVersion: 2.6.12
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
...@@ -158,7 +158,7 @@ Description: The "pubek" property will return the TPM's public endorsement ...@@ -158,7 +158,7 @@ Description: The "pubek" property will return the TPM's public endorsement
Modulus Length: 256 (bytes) Modulus Length: 256 (bytes)
Modulus: The 256 byte Endorsement Key modulus Modulus: The 256 byte Endorsement Key modulus
What: /sys/class/misc/tpmX/device/temp_deactivated What: /sys/class/tpm/tpmX/device/temp_deactivated
Date: April 2006 Date: April 2006
KernelVersion: 2.6.17 KernelVersion: 2.6.17
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
...@@ -167,7 +167,7 @@ Description: The "temp_deactivated" property returns a '1' if the chip has ...@@ -167,7 +167,7 @@ Description: The "temp_deactivated" property returns a '1' if the chip has
cycle. Whether a warm boot (reboot) will clear a TPM chip cycle. Whether a warm boot (reboot) will clear a TPM chip
from a temp_deactivated state is platform specific. from a temp_deactivated state is platform specific.
What: /sys/class/misc/tpmX/device/timeouts What: /sys/class/tpm/tpmX/device/timeouts
Date: March 2011 Date: March 2011
KernelVersion: 3.1 KernelVersion: 3.1
Contact: tpmdd-devel@lists.sf.net Contact: tpmdd-devel@lists.sf.net
......
* STMicroelectronics SAS. ST33ZP24 TPM SoC
Required properties:
- compatible: Should be "st,st33zp24-i2c".
- clock-frequency: I²C work frequency.
- reg: address on the bus
Optional ST33ZP24 Properties:
- interrupt-parent: phandle for the interrupt gpio controller
- interrupts: GPIO interrupt to which the chip is connected
- lpcpd-gpios: Output GPIO pin used for ST33ZP24 power management D1/D2 state.
If set, power must be present when the platform is going into sleep/hibernate mode.
Optional SoC Specific Properties:
- pinctrl-names: Contains only one value - "default".
- pintctrl-0: Specifies the pin control groups used for this controller.
Example (for ARM-based BeagleBoard xM with ST33ZP24 on I2C2):
&i2c2 {
status = "okay";
st33zp24: st33zp24@13 {
compatible = "st,st33zp24-i2c";
reg = <0x13>;
clock-frequency = <400000>;
interrupt-parent = <&gpio5>;
interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
lpcpd-gpios = <&gpio5 15 GPIO_ACTIVE_HIGH>;
};
};
...@@ -323,8 +323,6 @@ about the status of the key service: ...@@ -323,8 +323,6 @@ about the status of the key service:
U Under construction by callback to userspace U Under construction by callback to userspace
N Negative key N Negative key
This file must be enabled at kernel configuration time as it allows anyone
to list the keys database.
(*) /proc/key-users (*) /proc/key-users
......
...@@ -4917,7 +4917,7 @@ F: drivers/ipack/ ...@@ -4917,7 +4917,7 @@ F: drivers/ipack/
INTEGRITY MEASUREMENT ARCHITECTURE (IMA) INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
M: Mimi Zohar <zohar@linux.vnet.ibm.com> M: Mimi Zohar <zohar@linux.vnet.ibm.com>
M: Dmitry Kasatkin <d.kasatkin@samsung.com> M: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
L: linux-ima-devel@lists.sourceforge.net L: linux-ima-devel@lists.sourceforge.net
L: linux-ima-user@lists.sourceforge.net L: linux-ima-user@lists.sourceforge.net
L: linux-security-module@vger.kernel.org L: linux-security-module@vger.kernel.org
...@@ -9817,13 +9817,21 @@ F: drivers/media/pci/tw68/ ...@@ -9817,13 +9817,21 @@ F: drivers/media/pci/tw68/
TPM DEVICE DRIVER TPM DEVICE DRIVER
M: Peter Huewe <peterhuewe@gmx.de> M: Peter Huewe <peterhuewe@gmx.de>
M: Ashley Lai <ashley@ashleylai.com>
M: Marcel Selhorst <tpmdd@selhorst.net> M: Marcel Selhorst <tpmdd@selhorst.net>
W: http://tpmdd.sourceforge.net W: http://tpmdd.sourceforge.net
L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers) L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
Q: git git://github.com/PeterHuewe/linux-tpmdd.git
T: https://github.com/PeterHuewe/linux-tpmdd
S: Maintained S: Maintained
F: drivers/char/tpm/ F: drivers/char/tpm/
TPM IBM_VTPM DEVICE DRIVER
M: Ashley Lai <ashleydlai@gmail.com>
W: http://tpmdd.sourceforge.net
L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
S: Maintained
F: drivers/char/tpm/tpm_ibmvtpm*
TRACING TRACING
M: Steven Rostedt <rostedt@goodmis.org> M: Steven Rostedt <rostedt@goodmis.org>
M: Ingo Molnar <mingo@redhat.com> M: Ingo Molnar <mingo@redhat.com>
......
...@@ -100,15 +100,15 @@ config TCG_IBMVTPM ...@@ -100,15 +100,15 @@ config TCG_IBMVTPM
will be accessible from within Linux. To compile this driver will be accessible from within Linux. To compile this driver
as a module, choose M here; the module will be called tpm_ibmvtpm. as a module, choose M here; the module will be called tpm_ibmvtpm.
config TCG_ST33_I2C config TCG_TIS_I2C_ST33
tristate "STMicroelectronics ST33 I2C TPM" tristate "TPM Interface Specification 1.2 Interface (I2C - STMicroelectronics)"
depends on I2C depends on I2C
depends on GPIOLIB depends on GPIOLIB
---help--- ---help---
If you have a TPM security chip from STMicroelectronics working with If you have a TPM security chip from STMicroelectronics working with
an I2C bus say Yes and it will be accessible from within Linux. an I2C bus say Yes and it will be accessible from within Linux.
To compile this driver as a module, choose M here; the module will be To compile this driver as a module, choose M here; the module will be
called tpm_stm_st33_i2c. called tpm_i2c_stm_st33.
config TCG_XEN config TCG_XEN
tristate "XEN TPM Interface" tristate "XEN TPM Interface"
...@@ -122,4 +122,13 @@ config TCG_XEN ...@@ -122,4 +122,13 @@ config TCG_XEN
To compile this driver as a module, choose M here; the module To compile this driver as a module, choose M here; the module
will be called xen-tpmfront. will be called xen-tpmfront.
config TCG_CRB
tristate "TPM 2.0 CRB Interface"
depends on X86 && ACPI
---help---
If you have a TPM security chip that is compliant with the
TCG CRB 2.0 TPM specification say Yes and it will be accessible
from within Linux. To compile this driver as a module, choose
M here; the module will be called tpm_crb.
endif # TCG_TPM endif # TCG_TPM
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for the kernel tpm device drivers. # Makefile for the kernel tpm device drivers.
# #
obj-$(CONFIG_TCG_TPM) += tpm.o obj-$(CONFIG_TCG_TPM) += tpm.o
tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o
tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm-$(CONFIG_ACPI) += tpm_ppi.o
ifdef CONFIG_ACPI ifdef CONFIG_ACPI
...@@ -20,5 +20,6 @@ obj-$(CONFIG_TCG_NSC) += tpm_nsc.o ...@@ -20,5 +20,6 @@ obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
obj-$(CONFIG_TCG_ST33_I2C) += tpm_i2c_stm_st33.o obj-$(CONFIG_TCG_TIS_I2C_ST33) += tpm_i2c_stm_st33.o
obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o
obj-$(CONFIG_TCG_CRB) += tpm_crb.o
/*
* Copyright (C) 2004 IBM Corporation
* Copyright (C) 2014 Intel Corporation
*
* Authors:
* Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
* Leendert van Doorn <leendert@watson.ibm.com>
* Dave Safford <safford@watson.ibm.com>
* Reiner Sailer <sailer@watson.ibm.com>
* Kylene Hall <kjhall@us.ibm.com>
*
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
*
* TPM chip management routines.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
*/
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/freezer.h>
#include <linux/major.h>
#include "tpm.h"
#include "tpm_eventlog.h"
static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
struct class *tpm_class;
dev_t tpm_devt;
/*
* tpm_chip_find_get - return tpm_chip for a given chip number
* @chip_num the device number for the chip
*/
struct tpm_chip *tpm_chip_find_get(int chip_num)
{
struct tpm_chip *pos, *chip = NULL;
rcu_read_lock();
list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
continue;
if (try_module_get(pos->pdev->driver->owner)) {
chip = pos;
break;
}
}
rcu_read_unlock();
return chip;
}
/**
* tpm_dev_release() - free chip memory and the device number
* @dev: the character device for the TPM chip
*
* This is used as the release function for the character device.
*/
static void tpm_dev_release(struct device *dev)
{
struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
spin_lock(&driver_lock);
clear_bit(chip->dev_num, dev_mask);
spin_unlock(&driver_lock);
kfree(chip);
}
/**
* tpmm_chip_alloc() - allocate a new struct tpm_chip instance
* @dev: device to which the chip is associated
* @ops: struct tpm_class_ops instance
*
* Allocates a new struct tpm_chip instance and assigns a free
* device number for it. Caller does not have to worry about
* freeing the allocated resources. When the devices is removed
* devres calls tpmm_chip_remove() to do the job.
*/
struct tpm_chip *tpmm_chip_alloc(struct device *dev,
const struct tpm_class_ops *ops)
{
struct tpm_chip *chip;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return ERR_PTR(-ENOMEM);
mutex_init(&chip->tpm_mutex);
INIT_LIST_HEAD(&chip->list);
chip->ops = ops;
spin_lock(&driver_lock);
chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
spin_unlock(&driver_lock);
if (chip->dev_num >= TPM_NUM_DEVICES) {
dev_err(dev, "No available tpm device numbers\n");
kfree(chip);
return ERR_PTR(-ENOMEM);
}
set_bit(chip->dev_num, dev_mask);
scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num);
chip->pdev = dev;
dev_set_drvdata(dev, chip);
chip->dev.class = tpm_class;
chip->dev.release = tpm_dev_release;
chip->dev.parent = chip->pdev;
if (chip->dev_num == 0)
chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
else
chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
dev_set_name(&chip->dev, "%s", chip->devname);
device_initialize(&chip->dev);
chip->cdev.owner = chip->pdev->driver->owner;
cdev_init(&chip->cdev, &tpm_fops);
return chip;
}
EXPORT_SYMBOL_GPL(tpmm_chip_alloc);
static int tpm_dev_add_device(struct tpm_chip *chip)
{
int rc;
rc = device_add(&chip->dev);
if (rc) {
dev_err(&chip->dev,
"unable to device_register() %s, major %d, minor %d, err=%d\n",
chip->devname, MAJOR(chip->dev.devt),
MINOR(chip->dev.devt), rc);
return rc;
}
rc = cdev_add(&chip->cdev, chip->dev.devt, 1);
if (rc) {
dev_err(&chip->dev,
"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
chip->devname, MAJOR(chip->dev.devt),
MINOR(chip->dev.devt), rc);
device_unregister(&chip->dev);
return rc;
}
return rc;
}
static void tpm_dev_del_device(struct tpm_chip *chip)
{
cdev_del(&chip->cdev);
device_unregister(&chip->dev);
}
/*
* tpm_chip_register() - create a character device for the TPM chip
* @chip: TPM chip to use.
*
* Creates a character device for the TPM chip and adds sysfs interfaces for
* the device, PPI and TCPA. As the last step this function adds the
* chip to the list of TPM chips available for use.
*
* NOTE: This function should be only called after the chip initialization
* is complete.
*
* Called from tpm_<specific>.c probe function only for devices
* the driver has determined it should claim. Prior to calling
* this function the specific probe function has called pci_enable_device
* upon errant exit from this function specific probe function should call
* pci_disable_device
*/
int tpm_chip_register(struct tpm_chip *chip)
{
int rc;
rc = tpm_dev_add_device(chip);
if (rc)
return rc;
/* Populate sysfs for TPM1 devices. */
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
rc = tpm_sysfs_add_device(chip);
if (rc)
goto del_misc;
rc = tpm_add_ppi(chip);
if (rc)
goto del_sysfs;
chip->bios_dir = tpm_bios_log_setup(chip->devname);
}
/* Make the chip available. */
spin_lock(&driver_lock);
list_add_rcu(&chip->list, &tpm_chip_list);
spin_unlock(&driver_lock);
chip->flags |= TPM_CHIP_FLAG_REGISTERED;
return 0;
del_sysfs:
tpm_sysfs_del_device(chip);
del_misc:
tpm_dev_del_device(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_chip_register);
/*
* tpm_chip_unregister() - release the TPM driver
* @chip: TPM chip to use.
*
* Takes the chip first away from the list of available TPM chips and then
* cleans up all the resources reserved by tpm_chip_register().
*
* NOTE: This function should be only called before deinitializing chip
* resources.
*/
void tpm_chip_unregister(struct tpm_chip *chip)
{
if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED))
return;
spin_lock(&driver_lock);
list_del_rcu(&chip->list);
spin_unlock(&driver_lock);
synchronize_rcu();
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
if (chip->bios_dir)
tpm_bios_log_teardown(chip->bios_dir);
tpm_remove_ppi(chip);
tpm_sysfs_del_device(chip);
}
tpm_dev_del_device(chip);
}
EXPORT_SYMBOL_GPL(tpm_chip_unregister);
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
* License. * License.
* *
*/ */
#include <linux/miscdevice.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include "tpm.h" #include "tpm.h"
...@@ -54,16 +53,15 @@ static void timeout_work(struct work_struct *work) ...@@ -54,16 +53,15 @@ static void timeout_work(struct work_struct *work)
static int tpm_open(struct inode *inode, struct file *file) static int tpm_open(struct inode *inode, struct file *file)
{ {
struct miscdevice *misc = file->private_data; struct tpm_chip *chip =
struct tpm_chip *chip = container_of(misc, struct tpm_chip, container_of(inode->i_cdev, struct tpm_chip, cdev);
vendor.miscdev);
struct file_priv *priv; struct file_priv *priv;
/* It's assured that the chip will be opened just once, /* It's assured that the chip will be opened just once,
* by the check of is_open variable, which is protected * by the check of is_open variable, which is protected
* by driver_lock. */ * by driver_lock. */
if (test_and_set_bit(0, &chip->is_open)) { if (test_and_set_bit(0, &chip->is_open)) {
dev_dbg(chip->dev, "Another process owns this TPM\n"); dev_dbg(chip->pdev, "Another process owns this TPM\n");
return -EBUSY; return -EBUSY;
} }
...@@ -81,7 +79,7 @@ static int tpm_open(struct inode *inode, struct file *file) ...@@ -81,7 +79,7 @@ static int tpm_open(struct inode *inode, struct file *file)
INIT_WORK(&priv->work, timeout_work); INIT_WORK(&priv->work, timeout_work);
file->private_data = priv; file->private_data = priv;
get_device(chip->dev); get_device(chip->pdev);
return 0; return 0;
} }
...@@ -168,12 +166,12 @@ static int tpm_release(struct inode *inode, struct file *file) ...@@ -168,12 +166,12 @@ static int tpm_release(struct inode *inode, struct file *file)
file->private_data = NULL; file->private_data = NULL;
atomic_set(&priv->data_pending, 0); atomic_set(&priv->data_pending, 0);
clear_bit(0, &priv->chip->is_open); clear_bit(0, &priv->chip->is_open);
put_device(priv->chip->dev); put_device(priv->chip->pdev);
kfree(priv); kfree(priv);
return 0; return 0;
} }
static const struct file_operations tpm_fops = { const struct file_operations tpm_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.open = tpm_open, .open = tpm_open,
...@@ -182,32 +180,4 @@ static const struct file_operations tpm_fops = { ...@@ -182,32 +180,4 @@ static const struct file_operations tpm_fops = {
.release = tpm_release, .release = tpm_release,
}; };
int tpm_dev_add_device(struct tpm_chip *chip)
{
int rc;
chip->vendor.miscdev.fops = &tpm_fops;
if (chip->dev_num == 0)
chip->vendor.miscdev.minor = TPM_MINOR;
else
chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
chip->vendor.miscdev.name = chip->devname;
chip->vendor.miscdev.parent = chip->dev;
rc = misc_register(&chip->vendor.miscdev);
if (rc) {
chip->vendor.miscdev.name = NULL;
dev_err(chip->dev,
"unable to misc_register %s, minor %d err=%d\n",
chip->vendor.miscdev.name,
chip->vendor.miscdev.minor, rc);
}
return rc;
}
void tpm_dev_del_device(struct tpm_chip *chip)
{
if (chip->vendor.miscdev.name)
misc_deregister(&chip->vendor.miscdev);
}
This diff is collapsed.
...@@ -20,25 +20,6 @@ ...@@ -20,25 +20,6 @@
#include <linux/device.h> #include <linux/device.h>
#include "tpm.h" #include "tpm.h"
/* XXX for now this helper is duplicated in tpm-interface.c */
static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
int len, const char *desc)
{
int err;
len = tpm_transmit(chip, (u8 *) cmd, len);
if (len < 0)
return len;
else if (len < TPM_HEADER_SIZE)
return -EFAULT;
err = be32_to_cpu(cmd->header.out.return_code);
if (err != 0 && desc)
dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
return err;
}
#define READ_PUBEK_RESULT_SIZE 314 #define READ_PUBEK_RESULT_SIZE 314
#define TPM_ORD_READPUBEK cpu_to_be32(124) #define TPM_ORD_READPUBEK cpu_to_be32(124)
static struct tpm_input_header tpm_readpubek_header = { static struct tpm_input_header tpm_readpubek_header = {
...@@ -58,7 +39,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, ...@@ -58,7 +39,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_cmd.header.in = tpm_readpubek_header; tpm_cmd.header.in = tpm_readpubek_header;
err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
"attempting to read the PUBEK"); "attempting to read the PUBEK");
if (err) if (err)
goto out; goto out;
...@@ -303,16 +284,16 @@ static const struct attribute_group tpm_dev_group = { ...@@ -303,16 +284,16 @@ static const struct attribute_group tpm_dev_group = {
int tpm_sysfs_add_device(struct tpm_chip *chip) int tpm_sysfs_add_device(struct tpm_chip *chip)
{ {
int err; int err;
err = sysfs_create_group(&chip->dev->kobj, err = sysfs_create_group(&chip->pdev->kobj,
&tpm_dev_group); &tpm_dev_group);
if (err) if (err)
dev_err(chip->dev, dev_err(chip->pdev,
"failed to create sysfs attributes, %d\n", err); "failed to create sysfs attributes, %d\n", err);
return err; return err;
} }
void tpm_sysfs_del_device(struct tpm_chip *chip) void tpm_sysfs_del_device(struct tpm_chip *chip)
{ {
sysfs_remove_group(&chip->dev->kobj, &tpm_dev_group); sysfs_remove_group(&chip->pdev->kobj, &tpm_dev_group);
} }
...@@ -23,10 +23,11 @@ ...@@ -23,10 +23,11 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/tpm.h> #include <linux/tpm.h>
#include <linux/acpi.h>
#include <linux/cdev.h>
enum tpm_const { enum tpm_const {
TPM_MINOR = 224, /* officially assigned */ TPM_MINOR = 224, /* officially assigned */
...@@ -61,6 +62,59 @@ enum tpm_duration { ...@@ -61,6 +62,59 @@ enum tpm_duration {
#define TPM_ERR_INVALID_POSTINIT 38 #define TPM_ERR_INVALID_POSTINIT 38
#define TPM_HEADER_SIZE 10 #define TPM_HEADER_SIZE 10
enum tpm2_const {
TPM2_PLATFORM_PCR = 24,
TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8),
TPM2_TIMEOUT_A = 750,
TPM2_TIMEOUT_B = 2000,
TPM2_TIMEOUT_C = 200,
TPM2_TIMEOUT_D = 30,
TPM2_DURATION_SHORT = 20,
TPM2_DURATION_MEDIUM = 750,
TPM2_DURATION_LONG = 2000,
};
enum tpm2_structures {
TPM2_ST_NO_SESSIONS = 0x8001,
TPM2_ST_SESSIONS = 0x8002,
};
enum tpm2_return_codes {
TPM2_RC_INITIALIZE = 0x0100,
TPM2_RC_TESTING = 0x090A,
TPM2_RC_DISABLED = 0x0120,
};
enum tpm2_algorithms {
TPM2_ALG_SHA1 = 0x0004,
};
enum tpm2_command_codes {
TPM2_CC_FIRST = 0x011F,
TPM2_CC_SELF_TEST = 0x0143,
TPM2_CC_STARTUP = 0x0144,
TPM2_CC_SHUTDOWN = 0x0145,
TPM2_CC_GET_CAPABILITY = 0x017A,
TPM2_CC_GET_RANDOM = 0x017B,
TPM2_CC_PCR_READ = 0x017E,
TPM2_CC_PCR_EXTEND = 0x0182,
TPM2_CC_LAST = 0x018F,
};
enum tpm2_permanent_handles {
TPM2_RS_PW = 0x40000009,
};
enum tpm2_capabilities {
TPM2_CAP_TPM_PROPERTIES = 6,
};
enum tpm2_startup_types {
TPM2_SU_CLEAR = 0x0000,
TPM2_SU_STATE = 0x0001,
};
struct tpm_chip; struct tpm_chip;
struct tpm_vendor_specific { struct tpm_vendor_specific {
...@@ -73,7 +127,6 @@ struct tpm_vendor_specific { ...@@ -73,7 +127,6 @@ struct tpm_vendor_specific {
int region_size; int region_size;
int have_region; int have_region;
struct miscdevice miscdev;
struct list_head list; struct list_head list;
int locality; int locality;
unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
...@@ -88,15 +141,27 @@ struct tpm_vendor_specific { ...@@ -88,15 +141,27 @@ struct tpm_vendor_specific {
u16 manufacturer_id; u16 manufacturer_id;
}; };
#define TPM_VPRIV(c) (c)->vendor.priv #define TPM_VPRIV(c) ((c)->vendor.priv)
#define TPM_VID_INTEL 0x8086 #define TPM_VID_INTEL 0x8086
#define TPM_VID_WINBOND 0x1050 #define TPM_VID_WINBOND 0x1050
#define TPM_VID_STM 0x104A #define TPM_VID_STM 0x104A
#define TPM_PPI_VERSION_LEN 3
enum tpm_chip_flags {
TPM_CHIP_FLAG_REGISTERED = BIT(0),
TPM_CHIP_FLAG_PPI = BIT(1),
TPM_CHIP_FLAG_TPM2 = BIT(2),
};
struct tpm_chip { struct tpm_chip {
struct device *dev; /* Device stuff */ struct device *pdev; /* Device stuff */
struct device dev;
struct cdev cdev;
const struct tpm_class_ops *ops; const struct tpm_class_ops *ops;
unsigned int flags;
int dev_num; /* /dev/tpm# */ int dev_num; /* /dev/tpm# */
char devname[7]; char devname[7];
...@@ -109,15 +174,19 @@ struct tpm_chip { ...@@ -109,15 +174,19 @@ struct tpm_chip {
struct dentry **bios_dir; struct dentry **bios_dir;
#ifdef CONFIG_ACPI
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
#endif /* CONFIG_ACPI */
struct list_head list; struct list_head list;
void (*release) (struct device *);
}; };
#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
static inline void tpm_chip_put(struct tpm_chip *chip) static inline void tpm_chip_put(struct tpm_chip *chip)
{ {
module_put(chip->dev->driver->owner); module_put(chip->pdev->driver->owner);
} }
static inline int tpm_read_index(int base, int index) static inline int tpm_read_index(int base, int index)
...@@ -313,40 +382,57 @@ struct tpm_cmd_t { ...@@ -313,40 +382,57 @@ struct tpm_cmd_t {
tpm_cmd_params params; tpm_cmd_params params;
} __packed; } __packed;
ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); extern struct class *tpm_class;
extern dev_t tpm_devt;
extern const struct file_operations tpm_fops;
ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *);
ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
size_t bufsiz); size_t bufsiz);
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, int len,
const char *desc);
extern int tpm_get_timeouts(struct tpm_chip *); extern int tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *); extern void tpm_gen_interrupt(struct tpm_chip *);
extern int tpm_do_selftest(struct tpm_chip *); extern int tpm_do_selftest(struct tpm_chip *);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern struct tpm_chip* tpm_register_hardware(struct device *,
const struct tpm_class_ops *ops);
extern void tpm_dev_vendor_release(struct tpm_chip *);
extern void tpm_remove_hardware(struct device *);
extern int tpm_pm_suspend(struct device *); extern int tpm_pm_suspend(struct device *);
extern int tpm_pm_resume(struct device *); extern int tpm_pm_resume(struct device *);
extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
wait_queue_head_t *, bool); wait_queue_head_t *, bool);
int tpm_dev_add_device(struct tpm_chip *chip); struct tpm_chip *tpm_chip_find_get(int chip_num);
void tpm_dev_del_device(struct tpm_chip *chip); extern struct tpm_chip *tpmm_chip_alloc(struct device *dev,
const struct tpm_class_ops *ops);
extern int tpm_chip_register(struct tpm_chip *chip);
extern void tpm_chip_unregister(struct tpm_chip *chip);
int tpm_sysfs_add_device(struct tpm_chip *chip); int tpm_sysfs_add_device(struct tpm_chip *chip);
void tpm_sysfs_del_device(struct tpm_chip *chip); void tpm_sysfs_del_device(struct tpm_chip *chip);
int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
extern int tpm_add_ppi(struct kobject *); extern int tpm_add_ppi(struct tpm_chip *chip);
extern void tpm_remove_ppi(struct kobject *); extern void tpm_remove_ppi(struct tpm_chip *chip);
#else #else
static inline int tpm_add_ppi(struct kobject *parent) static inline int tpm_add_ppi(struct tpm_chip *chip)
{ {
return 0; return 0;
} }
static inline void tpm_remove_ppi(struct kobject *parent) static inline void tpm_remove_ppi(struct tpm_chip *chip)
{ {
} }
#endif #endif
int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max);
ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
u32 *value, const char *desc);
extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type);
extern int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
extern int tpm2_do_selftest(struct tpm_chip *chip);
extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet);
This diff is collapsed.
...@@ -49,7 +49,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -49,7 +49,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
status = ioread8(chip->vendor.iobase + 1); status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) { if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading header\n"); dev_err(chip->pdev, "error reading header\n");
return -EIO; return -EIO;
} }
*buf++ = ioread8(chip->vendor.iobase); *buf++ = ioread8(chip->vendor.iobase);
...@@ -60,12 +60,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -60,12 +60,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
size = be32_to_cpu(*native_size); size = be32_to_cpu(*native_size);
if (count < size) { if (count < size) {
dev_err(chip->dev, dev_err(chip->pdev,
"Recv size(%d) less than available space\n", size); "Recv size(%d) less than available space\n", size);
for (; i < size; i++) { /* clear the waiting data anyway */ for (; i < size; i++) { /* clear the waiting data anyway */
status = ioread8(chip->vendor.iobase + 1); status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) { if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading data\n"); dev_err(chip->pdev, "error reading data\n");
return -EIO; return -EIO;
} }
} }
...@@ -76,7 +76,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -76,7 +76,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
for (; i < size; i++) { for (; i < size; i++) {
status = ioread8(chip->vendor.iobase + 1); status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) { if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading data\n"); dev_err(chip->pdev, "error reading data\n");
return -EIO; return -EIO;
} }
*buf++ = ioread8(chip->vendor.iobase); *buf++ = ioread8(chip->vendor.iobase);
...@@ -86,7 +86,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -86,7 +86,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
status = ioread8(chip->vendor.iobase + 1); status = ioread8(chip->vendor.iobase + 1);
if (status & ATML_STATUS_DATA_AVAIL) { if (status & ATML_STATUS_DATA_AVAIL) {
dev_err(chip->dev, "data available is stuck\n"); dev_err(chip->pdev, "data available is stuck\n");
return -EIO; return -EIO;
} }
...@@ -97,9 +97,9 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -97,9 +97,9 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
{ {
int i; int i;
dev_dbg(chip->dev, "tpm_atml_send:\n"); dev_dbg(chip->pdev, "tpm_atml_send:\n");
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); dev_dbg(chip->pdev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
iowrite8(buf[i], chip->vendor.iobase); iowrite8(buf[i], chip->vendor.iobase);
} }
...@@ -138,11 +138,11 @@ static void atml_plat_remove(void) ...@@ -138,11 +138,11 @@ static void atml_plat_remove(void)
struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
if (chip) { if (chip) {
tpm_chip_unregister(chip);
if (chip->vendor.have_region) if (chip->vendor.have_region)
atmel_release_region(chip->vendor.base, atmel_release_region(chip->vendor.base,
chip->vendor.region_size); chip->vendor.region_size);
atmel_put_base_addr(chip->vendor.iobase); atmel_put_base_addr(chip->vendor.iobase);
tpm_remove_hardware(chip->dev);
platform_device_unregister(pdev); platform_device_unregister(pdev);
} }
} }
...@@ -183,8 +183,9 @@ static int __init init_atmel(void) ...@@ -183,8 +183,9 @@ static int __init init_atmel(void)
goto err_rel_reg; goto err_rel_reg;
} }
if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) { chip = tpmm_chip_alloc(&pdev->dev, &tpm_atmel);
rc = -ENODEV; if (IS_ERR(chip)) {
rc = PTR_ERR(chip);
goto err_unreg_dev; goto err_unreg_dev;
} }
...@@ -193,6 +194,10 @@ static int __init init_atmel(void) ...@@ -193,6 +194,10 @@ static int __init init_atmel(void)
chip->vendor.have_region = have_region; chip->vendor.have_region = have_region;
chip->vendor.region_size = region_size; chip->vendor.region_size = region_size;
rc = tpm_chip_register(chip);
if (rc)
goto err_unreg_dev;
return 0; return 0;
err_unreg_dev: err_unreg_dev:
......
/*
* Copyright (C) 2014 Intel Corporation
*
* Authors:
* Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
*
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
*
* This device driver implements the TPM interface as defined in
* the TCG CRB 2.0 TPM specification.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*/
#include <linux/acpi.h>
#include <linux/highmem.h>
#include <linux/rculist.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "tpm.h"
#define ACPI_SIG_TPM2 "TPM2"
static const u8 CRB_ACPI_START_UUID[] = {
/* 0000 */ 0xAB, 0x6C, 0xBF, 0x6B, 0x63, 0x54, 0x14, 0x47,
/* 0008 */ 0xB7, 0xCD, 0xF0, 0x20, 0x3C, 0x03, 0x68, 0xD4
};
enum crb_defaults {
CRB_ACPI_START_REVISION_ID = 1,
CRB_ACPI_START_INDEX = 1,
};
enum crb_start_method {
CRB_SM_ACPI_START = 2,
CRB_SM_CRB = 7,
CRB_SM_CRB_WITH_ACPI_START = 8,
};
struct acpi_tpm2 {
struct acpi_table_header hdr;
u16 platform_class;
u16 reserved;
u64 control_area_pa;
u32 start_method;
} __packed;
enum crb_ca_request {
CRB_CA_REQ_GO_IDLE = BIT(0),
CRB_CA_REQ_CMD_READY = BIT(1),
};
enum crb_ca_status {
CRB_CA_STS_ERROR = BIT(0),
CRB_CA_STS_TPM_IDLE = BIT(1),
};
enum crb_start {
CRB_START_INVOKE = BIT(0),
};
enum crb_cancel {
CRB_CANCEL_INVOKE = BIT(0),
};
struct crb_control_area {
u32 req;
u32 sts;
u32 cancel;
u32 start;
u32 int_enable;
u32 int_sts;
u32 cmd_size;
u64 cmd_pa;
u32 rsp_size;
u64 rsp_pa;
} __packed;
enum crb_status {
CRB_STS_COMPLETE = BIT(0),
};
enum crb_flags {
CRB_FL_ACPI_START = BIT(0),
CRB_FL_CRB_START = BIT(1),
};
struct crb_priv {
unsigned int flags;
struct crb_control_area __iomem *cca;
u8 __iomem *cmd;
u8 __iomem *rsp;
};
#ifdef CONFIG_PM_SLEEP
static int crb_resume(struct device *dev)
{
int rc;
struct tpm_chip *chip = dev_get_drvdata(dev);
rc = tpm2_shutdown(chip, TPM2_SU_STATE);
if (!rc)
rc = tpm2_do_selftest(chip);
return rc;
}
#endif
static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, crb_resume);
static u8 crb_status(struct tpm_chip *chip)
{
struct crb_priv *priv = chip->vendor.priv;
u8 sts = 0;
if ((le32_to_cpu(ioread32(&priv->cca->start)) & CRB_START_INVOKE) !=
CRB_START_INVOKE)
sts |= CRB_STS_COMPLETE;
return sts;
}
static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct crb_priv *priv = chip->vendor.priv;
unsigned int expected;
/* sanity check */
if (count < 6)
return -EIO;
if (le32_to_cpu(ioread32(&priv->cca->sts)) & CRB_CA_STS_ERROR)
return -EIO;
memcpy_fromio(buf, priv->rsp, 6);
expected = be32_to_cpup((__be32 *) &buf[2]);
if (expected > count)
return -EIO;
memcpy_fromio(&buf[6], &priv->rsp[6], expected - 6);
return expected;
}
static int crb_do_acpi_start(struct tpm_chip *chip)
{
union acpi_object *obj;
int rc;
obj = acpi_evaluate_dsm(chip->acpi_dev_handle,
CRB_ACPI_START_UUID,
CRB_ACPI_START_REVISION_ID,
CRB_ACPI_START_INDEX,
NULL);
if (!obj)
return -ENXIO;
rc = obj->integer.value == 0 ? 0 : -ENXIO;
ACPI_FREE(obj);
return rc;
}
static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
struct crb_priv *priv = chip->vendor.priv;
int rc = 0;
if (len > le32_to_cpu(ioread32(&priv->cca->cmd_size))) {
dev_err(&chip->dev,
"invalid command count value %x %zx\n",
(unsigned int) len,
(size_t) le32_to_cpu(ioread32(&priv->cca->cmd_size)));
return -E2BIG;
}
memcpy_toio(priv->cmd, buf, len);
/* Make sure that cmd is populated before issuing start. */
wmb();
if (priv->flags & CRB_FL_CRB_START)
iowrite32(cpu_to_le32(CRB_START_INVOKE), &priv->cca->start);
if (priv->flags & CRB_FL_ACPI_START)
rc = crb_do_acpi_start(chip);
return rc;
}
static void crb_cancel(struct tpm_chip *chip)
{
struct crb_priv *priv = chip->vendor.priv;
iowrite32(cpu_to_le32(CRB_CANCEL_INVOKE), &priv->cca->cancel);
/* Make sure that cmd is populated before issuing cancel. */
wmb();
if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip))
dev_err(&chip->dev, "ACPI Start failed\n");
iowrite32(0, &priv->cca->cancel);
}
static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
{
struct crb_priv *priv = chip->vendor.priv;
u32 cancel = le32_to_cpu(ioread32(&priv->cca->cancel));
return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
}
static const struct tpm_class_ops tpm_crb = {
.status = crb_status,
.recv = crb_recv,
.send = crb_send,
.cancel = crb_cancel,
.req_canceled = crb_req_canceled,
.req_complete_mask = CRB_STS_COMPLETE,
.req_complete_val = CRB_STS_COMPLETE,
};
static int crb_acpi_add(struct acpi_device *device)
{
struct tpm_chip *chip;
struct acpi_tpm2 *buf;
struct crb_priv *priv;
struct device *dev = &device->dev;
acpi_status status;
u32 sm;
u64 pa;
int rc;
chip = tpmm_chip_alloc(dev, &tpm_crb);
if (IS_ERR(chip))
return PTR_ERR(chip);
chip->flags = TPM_CHIP_FLAG_TPM2;
status = acpi_get_table(ACPI_SIG_TPM2, 1,
(struct acpi_table_header **) &buf);
if (ACPI_FAILURE(status)) {
dev_err(dev, "failed to get TPM2 ACPI table\n");
return -ENODEV;
}
if (buf->hdr.length < sizeof(struct acpi_tpm2)) {
dev_err(dev, "TPM2 ACPI table has wrong size");
return -EINVAL;
}
priv = (struct crb_priv *) devm_kzalloc(dev, sizeof(struct crb_priv),
GFP_KERNEL);
if (!priv) {
dev_err(dev, "failed to devm_kzalloc for private data\n");
return -ENOMEM;
}
sm = le32_to_cpu(buf->start_method);
/* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs
* report only ACPI start but in practice seems to require both
* ACPI start and CRB start.
*/
if (sm == CRB_SM_CRB || sm == CRB_SM_CRB_WITH_ACPI_START ||
!strcmp(acpi_device_hid(device), "MSFT0101"))
priv->flags |= CRB_FL_CRB_START;
if (sm == CRB_SM_ACPI_START || sm == CRB_SM_CRB_WITH_ACPI_START)
priv->flags |= CRB_FL_ACPI_START;
priv->cca = (struct crb_control_area __iomem *)
devm_ioremap_nocache(dev, buf->control_area_pa, 0x1000);
if (!priv->cca) {
dev_err(dev, "ioremap of the control area failed\n");
return -ENOMEM;
}
memcpy_fromio(&pa, &priv->cca->cmd_pa, 8);
pa = le64_to_cpu(pa);
priv->cmd = devm_ioremap_nocache(dev, le64_to_cpu(pa),
ioread32(&priv->cca->cmd_size));
if (!priv->cmd) {
dev_err(dev, "ioremap of the command buffer failed\n");
return -ENOMEM;
}
memcpy_fromio(&pa, &priv->cca->rsp_pa, 8);
pa = le64_to_cpu(pa);
priv->rsp = devm_ioremap_nocache(dev, le64_to_cpu(pa),
ioread32(&priv->cca->rsp_size));
if (!priv->rsp) {
dev_err(dev, "ioremap of the response buffer failed\n");
return -ENOMEM;
}
chip->vendor.priv = priv;
/* Default timeouts and durations */
chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
chip->vendor.timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
chip->vendor.timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
chip->vendor.timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);
chip->vendor.duration[TPM_SHORT] =
msecs_to_jiffies(TPM2_DURATION_SHORT);
chip->vendor.duration[TPM_MEDIUM] =
msecs_to_jiffies(TPM2_DURATION_MEDIUM);
chip->vendor.duration[TPM_LONG] =
msecs_to_jiffies(TPM2_DURATION_LONG);
chip->acpi_dev_handle = device->handle;
rc = tpm2_do_selftest(chip);
if (rc)
return rc;
return tpm_chip_register(chip);
}
static int crb_acpi_remove(struct acpi_device *device)
{
struct device *dev = &device->dev;
struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_chip_unregister(chip);
return 0;
}
static struct acpi_device_id crb_device_ids[] = {
{"MSFT0101", 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, crb_device_ids);
static struct acpi_driver crb_acpi_driver = {
.name = "tpm_crb",
.ids = crb_device_ids,
.ops = {
.add = crb_acpi_add,
.remove = crb_acpi_remove,
},
.drv = {
.pm = &crb_pm,
},
};
module_acpi_driver(crb_acpi_driver);
MODULE_AUTHOR("Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>");
MODULE_DESCRIPTION("TPM2 Driver");
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");
...@@ -52,7 +52,7 @@ struct priv_data { ...@@ -52,7 +52,7 @@ struct priv_data {
static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
{ {
struct priv_data *priv = chip->vendor.priv; struct priv_data *priv = chip->vendor.priv;
struct i2c_client *client = to_i2c_client(chip->dev); struct i2c_client *client = to_i2c_client(chip->pdev);
s32 status; s32 status;
priv->len = 0; priv->len = 0;
...@@ -62,7 +62,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -62,7 +62,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
status = i2c_master_send(client, buf, len); status = i2c_master_send(client, buf, len);
dev_dbg(chip->dev, dev_dbg(chip->pdev,
"%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__, "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__,
(int)min_t(size_t, 64, len), buf, len, status); (int)min_t(size_t, 64, len), buf, len, status);
return status; return status;
...@@ -71,7 +71,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -71,7 +71,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{ {
struct priv_data *priv = chip->vendor.priv; struct priv_data *priv = chip->vendor.priv;
struct i2c_client *client = to_i2c_client(chip->dev); struct i2c_client *client = to_i2c_client(chip->pdev);
struct tpm_output_header *hdr = struct tpm_output_header *hdr =
(struct tpm_output_header *)priv->buffer; (struct tpm_output_header *)priv->buffer;
u32 expected_len; u32 expected_len;
...@@ -88,7 +88,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -88,7 +88,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return -ENOMEM; return -ENOMEM;
if (priv->len >= expected_len) { if (priv->len >= expected_len) {
dev_dbg(chip->dev, dev_dbg(chip->pdev,
"%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__, "%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
(int)min_t(size_t, 64, expected_len), buf, count, (int)min_t(size_t, 64, expected_len), buf, count,
expected_len); expected_len);
...@@ -97,7 +97,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -97,7 +97,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
} }
rc = i2c_master_recv(client, buf, expected_len); rc = i2c_master_recv(client, buf, expected_len);
dev_dbg(chip->dev, dev_dbg(chip->pdev,
"%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__, "%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
(int)min_t(size_t, 64, expected_len), buf, count, (int)min_t(size_t, 64, expected_len), buf, count,
expected_len); expected_len);
...@@ -106,13 +106,13 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -106,13 +106,13 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
static void i2c_atmel_cancel(struct tpm_chip *chip) static void i2c_atmel_cancel(struct tpm_chip *chip)
{ {
dev_err(chip->dev, "TPM operation cancellation was requested, but is not supported"); dev_err(chip->pdev, "TPM operation cancellation was requested, but is not supported");
} }
static u8 i2c_atmel_read_status(struct tpm_chip *chip) static u8 i2c_atmel_read_status(struct tpm_chip *chip)
{ {
struct priv_data *priv = chip->vendor.priv; struct priv_data *priv = chip->vendor.priv;
struct i2c_client *client = to_i2c_client(chip->dev); struct i2c_client *client = to_i2c_client(chip->pdev);
int rc; int rc;
/* The TPM fails the I2C read until it is ready, so we do the entire /* 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,7 +125,7 @@ static u8 i2c_atmel_read_status(struct tpm_chip *chip)
/* Once the TPM has completed the command the command remains readable /* Once the TPM has completed the command the command remains readable
* until another command is issued. */ * until another command is issued. */
rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer)); rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer));
dev_dbg(chip->dev, dev_dbg(chip->pdev,
"%s: sts=%d", __func__, rc); "%s: sts=%d", __func__, rc);
if (rc <= 0) if (rc <= 0)
return 0; return 0;
...@@ -153,21 +153,20 @@ static const struct tpm_class_ops i2c_atmel = { ...@@ -153,21 +153,20 @@ static const struct tpm_class_ops i2c_atmel = {
static int i2c_atmel_probe(struct i2c_client *client, static int i2c_atmel_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
int rc;
struct tpm_chip *chip; struct tpm_chip *chip;
struct device *dev = &client->dev; struct device *dev = &client->dev;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV; return -ENODEV;
chip = tpm_register_hardware(dev, &i2c_atmel); chip = tpmm_chip_alloc(dev, &i2c_atmel);
if (!chip) { if (IS_ERR(chip))
dev_err(dev, "%s() error in tpm_register_hardware\n", __func__); return PTR_ERR(chip);
return -ENODEV;
}
chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data),
GFP_KERNEL); GFP_KERNEL);
if (!chip->vendor.priv)
return -ENOMEM;
/* Default timeouts */ /* Default timeouts */
chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); 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,33 +178,20 @@ static int i2c_atmel_probe(struct i2c_client *client,
/* There is no known way to probe for this device, and all version /* There is no known way to probe for this device, and all version
* information seems to be read via TPM commands. Thus we rely on the * information seems to be read via TPM commands. Thus we rely on the
* TPM startup process in the common code to detect the device. */ * TPM startup process in the common code to detect the device. */
if (tpm_get_timeouts(chip)) { if (tpm_get_timeouts(chip))
rc = -ENODEV; return -ENODEV;
goto out_err;
}
if (tpm_do_selftest(chip)) {
rc = -ENODEV;
goto out_err;
}
return 0; if (tpm_do_selftest(chip))
return -ENODEV;
out_err: return tpm_chip_register(chip);
tpm_dev_vendor_release(chip);
tpm_remove_hardware(chip->dev);
return rc;
} }
static int i2c_atmel_remove(struct i2c_client *client) static int i2c_atmel_remove(struct i2c_client *client)
{ {
struct device *dev = &(client->dev); struct device *dev = &(client->dev);
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_chip_unregister(chip);
if (chip)
tpm_dev_vendor_release(chip);
tpm_remove_hardware(dev);
kfree(chip);
return 0; return 0;
} }
......
...@@ -446,7 +446,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -446,7 +446,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/* read first 10 bytes, including tag, paramsize, and result */ /* read first 10 bytes, including tag, paramsize, and result */
size = recv_data(chip, buf, TPM_HEADER_SIZE); size = recv_data(chip, buf, TPM_HEADER_SIZE);
if (size < TPM_HEADER_SIZE) { if (size < TPM_HEADER_SIZE) {
dev_err(chip->dev, "Unable to read header\n"); dev_err(chip->pdev, "Unable to read header\n");
goto out; goto out;
} }
...@@ -459,14 +459,14 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -459,14 +459,14 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
size += recv_data(chip, &buf[TPM_HEADER_SIZE], size += recv_data(chip, &buf[TPM_HEADER_SIZE],
expected - TPM_HEADER_SIZE); expected - TPM_HEADER_SIZE);
if (size < expected) { if (size < expected) {
dev_err(chip->dev, "Unable to read remainder of result\n"); dev_err(chip->pdev, "Unable to read remainder of result\n");
size = -ETIME; size = -ETIME;
goto out; goto out;
} }
wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
if (status & TPM_STS_DATA_AVAIL) { /* retry? */ if (status & TPM_STS_DATA_AVAIL) { /* retry? */
dev_err(chip->dev, "Error left over data\n"); dev_err(chip->pdev, "Error left over data\n");
size = -EIO; size = -EIO;
goto out; goto out;
} }
...@@ -581,12 +581,9 @@ static int tpm_tis_i2c_init(struct device *dev) ...@@ -581,12 +581,9 @@ static int tpm_tis_i2c_init(struct device *dev)
int rc = 0; int rc = 0;
struct tpm_chip *chip; struct tpm_chip *chip;
chip = tpm_register_hardware(dev, &tpm_tis_i2c); chip = tpmm_chip_alloc(dev, &tpm_tis_i2c);
if (!chip) { if (IS_ERR(chip))
dev_err(dev, "could not register hardware\n"); return PTR_ERR(chip);
rc = -ENODEV;
goto out_err;
}
/* Disable interrupts */ /* Disable interrupts */
chip->vendor.irq = 0; chip->vendor.irq = 0;
...@@ -600,7 +597,7 @@ static int tpm_tis_i2c_init(struct device *dev) ...@@ -600,7 +597,7 @@ static int tpm_tis_i2c_init(struct device *dev)
if (request_locality(chip, 0) != 0) { if (request_locality(chip, 0) != 0) {
dev_err(dev, "could not request locality\n"); dev_err(dev, "could not request locality\n");
rc = -ENODEV; rc = -ENODEV;
goto out_vendor; goto out_err;
} }
/* read four bytes from DID_VID register */ /* read four bytes from DID_VID register */
...@@ -628,21 +625,9 @@ static int tpm_tis_i2c_init(struct device *dev) ...@@ -628,21 +625,9 @@ static int tpm_tis_i2c_init(struct device *dev)
tpm_get_timeouts(chip); tpm_get_timeouts(chip);
tpm_do_selftest(chip); tpm_do_selftest(chip);
return 0; return tpm_chip_register(chip);
out_release: out_release:
release_locality(chip, chip->vendor.locality, 1); release_locality(chip, chip->vendor.locality, 1);
out_vendor:
/* close file handles */
tpm_dev_vendor_release(chip);
/* remove hardware */
tpm_remove_hardware(chip->dev);
/* reset these pointers, otherwise we oops */
chip->dev->release = NULL;
chip->release = NULL;
tpm_dev.client = NULL; tpm_dev.client = NULL;
out_err: out_err:
return rc; return rc;
...@@ -712,17 +697,9 @@ static int tpm_tis_i2c_probe(struct i2c_client *client, ...@@ -712,17 +697,9 @@ static int tpm_tis_i2c_probe(struct i2c_client *client,
static int tpm_tis_i2c_remove(struct i2c_client *client) static int tpm_tis_i2c_remove(struct i2c_client *client)
{ {
struct tpm_chip *chip = tpm_dev.chip; struct tpm_chip *chip = tpm_dev.chip;
release_locality(chip, chip->vendor.locality, 1);
/* close file handles */ tpm_chip_unregister(chip);
tpm_dev_vendor_release(chip); release_locality(chip, chip->vendor.locality, 1);
/* remove hardware */
tpm_remove_hardware(chip->dev);
/* reset these pointers, otherwise we oops */
chip->dev->release = NULL;
chip->release = NULL;
tpm_dev.client = NULL; tpm_dev.client = NULL;
return 0; return 0;
......
...@@ -96,13 +96,13 @@ static s32 i2c_nuvoton_write_buf(struct i2c_client *client, u8 offset, u8 size, ...@@ -96,13 +96,13 @@ static s32 i2c_nuvoton_write_buf(struct i2c_client *client, u8 offset, u8 size,
/* read TPM_STS register */ /* read TPM_STS register */
static u8 i2c_nuvoton_read_status(struct tpm_chip *chip) static u8 i2c_nuvoton_read_status(struct tpm_chip *chip)
{ {
struct i2c_client *client = to_i2c_client(chip->dev); struct i2c_client *client = to_i2c_client(chip->pdev);
s32 status; s32 status;
u8 data; u8 data;
status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data); status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data);
if (status <= 0) { if (status <= 0) {
dev_err(chip->dev, "%s() error return %d\n", __func__, dev_err(chip->pdev, "%s() error return %d\n", __func__,
status); status);
data = TPM_STS_ERR_VAL; data = TPM_STS_ERR_VAL;
} }
...@@ -127,13 +127,13 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data) ...@@ -127,13 +127,13 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data)
/* write commandReady to TPM_STS register */ /* write commandReady to TPM_STS register */
static void i2c_nuvoton_ready(struct tpm_chip *chip) static void i2c_nuvoton_ready(struct tpm_chip *chip)
{ {
struct i2c_client *client = to_i2c_client(chip->dev); struct i2c_client *client = to_i2c_client(chip->pdev);
s32 status; s32 status;
/* this causes the current command to be aborted */ /* this causes the current command to be aborted */
status = i2c_nuvoton_write_status(client, TPM_STS_COMMAND_READY); status = i2c_nuvoton_write_status(client, TPM_STS_COMMAND_READY);
if (status < 0) if (status < 0)
dev_err(chip->dev, dev_err(chip->pdev,
"%s() fail to write TPM_STS.commandReady\n", __func__); "%s() fail to write TPM_STS.commandReady\n", __func__);
} }
...@@ -212,7 +212,7 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value, ...@@ -212,7 +212,7 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value,
return 0; return 0;
} while (time_before(jiffies, stop)); } while (time_before(jiffies, stop));
} }
dev_err(chip->dev, "%s(%02x, %02x) -> timeout\n", __func__, mask, dev_err(chip->pdev, "%s(%02x, %02x) -> timeout\n", __func__, mask,
value); value);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -240,7 +240,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, ...@@ -240,7 +240,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client,
&chip->vendor.read_queue) == 0) { &chip->vendor.read_queue) == 0) {
burst_count = i2c_nuvoton_get_burstcount(client, chip); burst_count = i2c_nuvoton_get_burstcount(client, chip);
if (burst_count < 0) { if (burst_count < 0) {
dev_err(chip->dev, dev_err(chip->pdev,
"%s() fail to read burstCount=%d\n", __func__, "%s() fail to read burstCount=%d\n", __func__,
burst_count); burst_count);
return -EIO; return -EIO;
...@@ -249,12 +249,12 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, ...@@ -249,12 +249,12 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client,
rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_R, rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_R,
bytes2read, &buf[size]); bytes2read, &buf[size]);
if (rc < 0) { if (rc < 0) {
dev_err(chip->dev, dev_err(chip->pdev,
"%s() fail on i2c_nuvoton_read_buf()=%d\n", "%s() fail on i2c_nuvoton_read_buf()=%d\n",
__func__, rc); __func__, rc);
return -EIO; return -EIO;
} }
dev_dbg(chip->dev, "%s(%d):", __func__, bytes2read); dev_dbg(chip->pdev, "%s(%d):", __func__, bytes2read);
size += bytes2read; size += bytes2read;
} }
...@@ -264,7 +264,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, ...@@ -264,7 +264,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client,
/* Read TPM command results */ /* Read TPM command results */
static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{ {
struct device *dev = chip->dev; struct device *dev = chip->pdev;
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
s32 rc; s32 rc;
int expected, status, burst_count, retries, size = 0; 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,7 +334,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
break; break;
} }
i2c_nuvoton_ready(chip); i2c_nuvoton_ready(chip);
dev_dbg(chip->dev, "%s() -> %d\n", __func__, size); dev_dbg(chip->pdev, "%s() -> %d\n", __func__, size);
return size; return size;
} }
...@@ -347,7 +347,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -347,7 +347,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
*/ */
static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
{ {
struct device *dev = chip->dev; struct device *dev = chip->pdev;
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
u32 ordinal; u32 ordinal;
size_t count = 0; size_t count = 0;
...@@ -530,14 +530,15 @@ static int i2c_nuvoton_probe(struct i2c_client *client, ...@@ -530,14 +530,15 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
dev_info(dev, "VID: %04X DID: %02X RID: %02X\n", (u16) vid, dev_info(dev, "VID: %04X DID: %02X RID: %02X\n", (u16) vid,
(u8) (vid >> 16), (u8) (vid >> 24)); (u8) (vid >> 16), (u8) (vid >> 24));
chip = tpm_register_hardware(dev, &tpm_i2c); chip = tpmm_chip_alloc(dev, &tpm_i2c);
if (!chip) { if (IS_ERR(chip))
dev_err(dev, "%s() error in tpm_register_hardware\n", __func__); return PTR_ERR(chip);
return -ENODEV;
}
chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data),
GFP_KERNEL); GFP_KERNEL);
if (!chip->vendor.priv)
return -ENOMEM;
init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.read_queue);
init_waitqueue_head(&chip->vendor.int_queue); init_waitqueue_head(&chip->vendor.int_queue);
...@@ -559,7 +560,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client, ...@@ -559,7 +560,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
rc = devm_request_irq(dev, chip->vendor.irq, rc = devm_request_irq(dev, chip->vendor.irq,
i2c_nuvoton_int_handler, i2c_nuvoton_int_handler,
IRQF_TRIGGER_LOW, IRQF_TRIGGER_LOW,
chip->vendor.miscdev.name, chip->devname,
chip); chip);
if (rc) { if (rc) {
dev_err(dev, "%s() Unable to request irq: %d for use\n", 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,7 +585,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
TPM_DATA_FIFO_W, TPM_DATA_FIFO_W,
1, (u8 *) (&rc)); 1, (u8 *) (&rc));
if (rc < 0) if (rc < 0)
goto out_err; return rc;
/* TPM_STS <- 0x40 (commandReady) */ /* TPM_STS <- 0x40 (commandReady) */
i2c_nuvoton_ready(chip); i2c_nuvoton_ready(chip);
} else { } else {
...@@ -594,45 +595,29 @@ static int i2c_nuvoton_probe(struct i2c_client *client, ...@@ -594,45 +595,29 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
* only TPM_STS_VALID should be set * only TPM_STS_VALID should be set
*/ */
if (i2c_nuvoton_read_status(chip) != if (i2c_nuvoton_read_status(chip) !=
TPM_STS_VALID) { TPM_STS_VALID)
rc = -EIO; return -EIO;
goto out_err;
}
}
} }
} }
if (tpm_get_timeouts(chip)) {
rc = -ENODEV;
goto out_err;
} }
if (tpm_do_selftest(chip)) { if (tpm_get_timeouts(chip))
rc = -ENODEV; return -ENODEV;
goto out_err;
}
return 0; if (tpm_do_selftest(chip))
return -ENODEV;
out_err: return tpm_chip_register(chip);
tpm_dev_vendor_release(chip);
tpm_remove_hardware(chip->dev);
return rc;
} }
static int i2c_nuvoton_remove(struct i2c_client *client) static int i2c_nuvoton_remove(struct i2c_client *client)
{ {
struct device *dev = &(client->dev); struct device *dev = &(client->dev);
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_chip_unregister(chip);
if (chip)
tpm_dev_vendor_release(chip);
tpm_remove_hardware(dev);
kfree(chip);
return 0; return 0;
} }
static const struct i2c_device_id i2c_nuvoton_id[] = { static const struct i2c_device_id i2c_nuvoton_id[] = {
{I2C_DRIVER_NAME, 0}, {I2C_DRIVER_NAME, 0},
{} {}
......
This diff is collapsed.
/* /*
* Copyright (C) 2012 IBM Corporation * Copyright (C) 2012 IBM Corporation
* *
* Author: Ashley Lai <adlai@us.ibm.com> * Author: Ashley Lai <ashleydlai@gmail.com>
* *
* Maintained by: <tpmdd-devel@lists.sourceforge.net> * Maintained by: <tpmdd-devel@lists.sourceforge.net>
* *
...@@ -270,8 +270,11 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm) ...@@ -270,8 +270,11 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
static int tpm_ibmvtpm_remove(struct vio_dev *vdev) static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
{ {
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
struct tpm_chip *chip = dev_get_drvdata(ibmvtpm->dev);
int rc = 0; int rc = 0;
tpm_chip_unregister(chip);
free_irq(vdev->irq, ibmvtpm); free_irq(vdev->irq, ibmvtpm);
do { do {
...@@ -290,8 +293,6 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) ...@@ -290,8 +293,6 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
kfree(ibmvtpm->rtce_buf); kfree(ibmvtpm->rtce_buf);
} }
tpm_remove_hardware(ibmvtpm->dev);
kfree(ibmvtpm); kfree(ibmvtpm);
return 0; return 0;
...@@ -307,6 +308,14 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) ...@@ -307,6 +308,14 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev) static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
{ {
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
/* ibmvtpm initializes at probe time, so the data we are
* asking for may not be set yet. Estimate that 4K required
* for TCE-mapped buffer in addition to CRQ.
*/
if (!ibmvtpm)
return CRQ_RES_BUF_SIZE + PAGE_SIZE;
return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size; return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size;
} }
...@@ -555,11 +564,9 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, ...@@ -555,11 +564,9 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
struct tpm_chip *chip; struct tpm_chip *chip;
int rc = -ENOMEM, rc1; int rc = -ENOMEM, rc1;
chip = tpm_register_hardware(dev, &tpm_ibmvtpm); chip = tpmm_chip_alloc(dev, &tpm_ibmvtpm);
if (!chip) { if (IS_ERR(chip))
dev_err(dev, "tpm_register_hardware failed\n"); return PTR_ERR(chip);
return -ENODEV;
}
ibmvtpm = kzalloc(sizeof(struct ibmvtpm_dev), GFP_KERNEL); ibmvtpm = kzalloc(sizeof(struct ibmvtpm_dev), GFP_KERNEL);
if (!ibmvtpm) { if (!ibmvtpm) {
...@@ -629,7 +636,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, ...@@ -629,7 +636,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
if (rc) if (rc)
goto init_irq_cleanup; goto init_irq_cleanup;
return rc; return tpm_chip_register(chip);
init_irq_cleanup: init_irq_cleanup:
do { do {
rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address); rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address);
...@@ -644,8 +651,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, ...@@ -644,8 +651,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
kfree(ibmvtpm); kfree(ibmvtpm);
} }
tpm_remove_hardware(dev);
return rc; return rc;
} }
......
/* /*
* Copyright (C) 2012 IBM Corporation * Copyright (C) 2012 IBM Corporation
* *
* Author: Ashley Lai <adlai@us.ibm.com> * Author: Ashley Lai <ashleydlai@gmail.com>
* *
* Maintained by: <tpmdd-devel@lists.sourceforge.net> * Maintained by: <tpmdd-devel@lists.sourceforge.net>
* *
......
...@@ -195,9 +195,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) ...@@ -195,9 +195,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
} }
if (i == TPM_MAX_TRIES) { /* timeout occurs */ if (i == TPM_MAX_TRIES) { /* timeout occurs */
if (wait_for_bit == STAT_XFE) if (wait_for_bit == STAT_XFE)
dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n"); dev_err(chip->pdev, "Timeout in wait(STAT_XFE)\n");
if (wait_for_bit == STAT_RDA) if (wait_for_bit == STAT_RDA)
dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n"); dev_err(chip->pdev, "Timeout in wait(STAT_RDA)\n");
return -EIO; return -EIO;
} }
return 0; return 0;
...@@ -220,7 +220,7 @@ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) ...@@ -220,7 +220,7 @@ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
static void tpm_wtx(struct tpm_chip *chip) static void tpm_wtx(struct tpm_chip *chip)
{ {
number_of_wtx++; number_of_wtx++;
dev_info(chip->dev, "Granting WTX (%02d / %02d)\n", dev_info(chip->pdev, "Granting WTX (%02d / %02d)\n",
number_of_wtx, TPM_MAX_WTX_PACKAGES); number_of_wtx, TPM_MAX_WTX_PACKAGES);
wait_and_send(chip, TPM_VL_VER); wait_and_send(chip, TPM_VL_VER);
wait_and_send(chip, TPM_CTRL_WTX); wait_and_send(chip, TPM_CTRL_WTX);
...@@ -231,7 +231,7 @@ static void tpm_wtx(struct tpm_chip *chip) ...@@ -231,7 +231,7 @@ static void tpm_wtx(struct tpm_chip *chip)
static void tpm_wtx_abort(struct tpm_chip *chip) static void tpm_wtx_abort(struct tpm_chip *chip)
{ {
dev_info(chip->dev, "Aborting WTX\n"); dev_info(chip->pdev, "Aborting WTX\n");
wait_and_send(chip, TPM_VL_VER); wait_and_send(chip, TPM_VL_VER);
wait_and_send(chip, TPM_CTRL_WTX_ABORT); wait_and_send(chip, TPM_CTRL_WTX_ABORT);
wait_and_send(chip, 0x00); wait_and_send(chip, 0x00);
...@@ -257,7 +257,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -257,7 +257,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
} }
if (buf[0] != TPM_VL_VER) { if (buf[0] != TPM_VL_VER) {
dev_err(chip->dev, dev_err(chip->pdev,
"Wrong transport protocol implementation!\n"); "Wrong transport protocol implementation!\n");
return -EIO; return -EIO;
} }
...@@ -272,7 +272,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -272,7 +272,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
} }
if ((size == 0x6D00) && (buf[1] == 0x80)) { if ((size == 0x6D00) && (buf[1] == 0x80)) {
dev_err(chip->dev, "Error handling on vendor layer!\n"); dev_err(chip->pdev, "Error handling on vendor layer!\n");
return -EIO; return -EIO;
} }
...@@ -284,7 +284,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -284,7 +284,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
} }
if (buf[1] == TPM_CTRL_WTX) { if (buf[1] == TPM_CTRL_WTX) {
dev_info(chip->dev, "WTX-package received\n"); dev_info(chip->pdev, "WTX-package received\n");
if (number_of_wtx < TPM_MAX_WTX_PACKAGES) { if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
tpm_wtx(chip); tpm_wtx(chip);
goto recv_begin; goto recv_begin;
...@@ -295,14 +295,14 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -295,14 +295,14 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
} }
if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) { if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
dev_info(chip->dev, "WTX-abort acknowledged\n"); dev_info(chip->pdev, "WTX-abort acknowledged\n");
return size; return size;
} }
if (buf[1] == TPM_CTRL_ERROR) { if (buf[1] == TPM_CTRL_ERROR) {
dev_err(chip->dev, "ERROR-package received:\n"); dev_err(chip->pdev, "ERROR-package received:\n");
if (buf[4] == TPM_INF_NAK) if (buf[4] == TPM_INF_NAK)
dev_err(chip->dev, dev_err(chip->pdev,
"-> Negative acknowledgement" "-> Negative acknowledgement"
" - retransmit command!\n"); " - retransmit command!\n");
return -EIO; return -EIO;
...@@ -321,7 +321,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -321,7 +321,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
ret = empty_fifo(chip, 1); ret = empty_fifo(chip, 1);
if (ret) { if (ret) {
dev_err(chip->dev, "Timeout while clearing FIFO\n"); dev_err(chip->pdev, "Timeout while clearing FIFO\n");
return -EIO; return -EIO;
} }
...@@ -546,7 +546,14 @@ static int tpm_inf_pnp_probe(struct pnp_dev *dev, ...@@ -546,7 +546,14 @@ static int tpm_inf_pnp_probe(struct pnp_dev *dev,
vendorid[0], vendorid[1], vendorid[0], vendorid[1],
productid[0], productid[1], chipname); productid[0], productid[1], chipname);
if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) chip = tpmm_chip_alloc(&dev->dev, &tpm_inf);
if (IS_ERR(chip)) {
rc = PTR_ERR(chip);
goto err_release_region;
}
rc = tpm_chip_register(chip);
if (rc)
goto err_release_region; goto err_release_region;
return 0; return 0;
...@@ -572,7 +579,8 @@ static void tpm_inf_pnp_remove(struct pnp_dev *dev) ...@@ -572,7 +579,8 @@ static void tpm_inf_pnp_remove(struct pnp_dev *dev)
{ {
struct tpm_chip *chip = pnp_get_drvdata(dev); struct tpm_chip *chip = pnp_get_drvdata(dev);
if (chip) { tpm_chip_unregister(chip);
if (tpm_dev.iotype == TPM_INF_IO_PORT) { if (tpm_dev.iotype == TPM_INF_IO_PORT) {
release_region(tpm_dev.data_regs, tpm_dev.data_size); release_region(tpm_dev.data_regs, tpm_dev.data_size);
release_region(tpm_dev.config_port, release_region(tpm_dev.config_port,
...@@ -581,9 +589,6 @@ static void tpm_inf_pnp_remove(struct pnp_dev *dev) ...@@ -581,9 +589,6 @@ static void tpm_inf_pnp_remove(struct pnp_dev *dev)
iounmap(tpm_dev.mem_base); iounmap(tpm_dev.mem_base);
release_mem_region(tpm_dev.map_base, tpm_dev.map_size); release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
} }
tpm_dev_vendor_release(chip);
tpm_remove_hardware(chip->dev);
}
} }
static int tpm_inf_pnp_suspend(struct pnp_dev *dev, pm_message_t pm_state) static int tpm_inf_pnp_suspend(struct pnp_dev *dev, pm_message_t pm_state)
......
...@@ -113,7 +113,7 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) ...@@ -113,7 +113,7 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
} }
while (time_before(jiffies, stop)); while (time_before(jiffies, stop));
dev_info(chip->dev, "wait for ready failed\n"); dev_info(chip->pdev, "wait for ready failed\n");
return -EBUSY; return -EBUSY;
} }
...@@ -129,12 +129,12 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -129,12 +129,12 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO; return -EIO;
if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) { if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
dev_err(chip->dev, "F0 timeout\n"); dev_err(chip->pdev, "F0 timeout\n");
return -EIO; return -EIO;
} }
if ((data = if ((data =
inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
dev_err(chip->dev, "not in normal mode (0x%x)\n", dev_err(chip->pdev, "not in normal mode (0x%x)\n",
data); data);
return -EIO; return -EIO;
} }
...@@ -143,7 +143,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -143,7 +143,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
for (p = buffer; p < &buffer[count]; p++) { for (p = buffer; p < &buffer[count]; p++) {
if (wait_for_stat if (wait_for_stat
(chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) { (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
dev_err(chip->dev, dev_err(chip->pdev,
"OBF timeout (while reading data)\n"); "OBF timeout (while reading data)\n");
return -EIO; return -EIO;
} }
...@@ -154,11 +154,11 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -154,11 +154,11 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
if ((data & NSC_STATUS_F0) == 0 && if ((data & NSC_STATUS_F0) == 0 &&
(wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) { (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
dev_err(chip->dev, "F0 not set\n"); dev_err(chip->pdev, "F0 not set\n");
return -EIO; return -EIO;
} }
if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
dev_err(chip->dev, dev_err(chip->pdev,
"expected end of command(0x%x)\n", data); "expected end of command(0x%x)\n", data);
return -EIO; return -EIO;
} }
...@@ -189,19 +189,19 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -189,19 +189,19 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO; return -EIO;
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
dev_err(chip->dev, "IBF timeout\n"); dev_err(chip->pdev, "IBF timeout\n");
return -EIO; return -EIO;
} }
outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
dev_err(chip->dev, "IBR timeout\n"); dev_err(chip->pdev, "IBR timeout\n");
return -EIO; return -EIO;
} }
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
dev_err(chip->dev, dev_err(chip->pdev,
"IBF timeout (while writing data)\n"); "IBF timeout (while writing data)\n");
return -EIO; return -EIO;
} }
...@@ -209,7 +209,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -209,7 +209,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
} }
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
dev_err(chip->dev, "IBF timeout\n"); dev_err(chip->pdev, "IBF timeout\n");
return -EIO; return -EIO;
} }
outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
...@@ -247,10 +247,9 @@ static struct platform_device *pdev = NULL; ...@@ -247,10 +247,9 @@ static struct platform_device *pdev = NULL;
static void tpm_nsc_remove(struct device *dev) static void tpm_nsc_remove(struct device *dev)
{ {
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = dev_get_drvdata(dev);
if ( chip ) {
tpm_chip_unregister(chip);
release_region(chip->vendor.base, 2); release_region(chip->vendor.base, 2);
tpm_remove_hardware(chip->dev);
}
} }
static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume); 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,11 +306,16 @@ static int __init init_nsc(void)
goto err_del_dev; goto err_del_dev;
} }
if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { chip = tpmm_chip_alloc(&pdev->dev, &tpm_nsc);
if (IS_ERR(chip)) {
rc = -ENODEV; rc = -ENODEV;
goto err_rel_reg; goto err_rel_reg;
} }
rc = tpm_chip_register(chip);
if (rc)
goto err_rel_reg;
dev_dbg(&pdev->dev, "NSC TPM detected\n"); dev_dbg(&pdev->dev, "NSC TPM detected\n");
dev_dbg(&pdev->dev, dev_dbg(&pdev->dev,
"NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n", "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
......
/* /*
* Copyright 2012 IBM Corporation * Copyright 2012 IBM Corporation
* *
* Author: Ashley Lai <adlai@us.ibm.com> * Author: Ashley Lai <ashleydlai@gmail.com>
* *
* Maintained by: <tpmdd-devel@lists.sourceforge.net> * Maintained by: <tpmdd-devel@lists.sourceforge.net>
* *
......
/*
* Copyright (C) 2012-2014 Intel Corporation
*
* Authors:
* Xiaoyan Zhang <xiaoyan.zhang@intel.com>
* Jiang Liu <jiang.liu@linux.intel.com>
* Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
*
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
*
* This file contains implementation of the sysfs interface for PPI.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*/
#include <linux/acpi.h> #include <linux/acpi.h>
#include "tpm.h" #include "tpm.h"
...@@ -12,7 +31,6 @@ ...@@ -12,7 +31,6 @@
#define PPI_TPM_REQ_MAX 22 #define PPI_TPM_REQ_MAX 22
#define PPI_VS_REQ_START 128 #define PPI_VS_REQ_START 128
#define PPI_VS_REQ_END 255 #define PPI_VS_REQ_END 255
#define PPI_VERSION_LEN 3
static const u8 tpm_ppi_uuid[] = { static const u8 tpm_ppi_uuid[] = {
0xA6, 0xFA, 0xDD, 0x3D, 0xA6, 0xFA, 0xDD, 0x3D,
...@@ -22,45 +40,22 @@ static const u8 tpm_ppi_uuid[] = { ...@@ -22,45 +40,22 @@ static const u8 tpm_ppi_uuid[] = {
0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53
}; };
static char tpm_ppi_version[PPI_VERSION_LEN + 1];
static acpi_handle tpm_ppi_handle;
static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
void **return_value)
{
union acpi_object *obj;
if (!acpi_check_dsm(handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID,
1 << TPM_PPI_FN_VERSION))
return AE_OK;
/* Cache version string */
obj = acpi_evaluate_dsm_typed(handle, tpm_ppi_uuid,
TPM_PPI_REVISION_ID, TPM_PPI_FN_VERSION,
NULL, ACPI_TYPE_STRING);
if (obj) {
strlcpy(tpm_ppi_version, obj->string.pointer,
PPI_VERSION_LEN + 1);
ACPI_FREE(obj);
}
*return_value = handle;
return AE_CTRL_TERMINATE;
}
static inline union acpi_object * static inline union acpi_object *
tpm_eval_dsm(int func, acpi_object_type type, union acpi_object *argv4) tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type,
union acpi_object *argv4)
{ {
BUG_ON(!tpm_ppi_handle); BUG_ON(!ppi_handle);
return acpi_evaluate_dsm_typed(tpm_ppi_handle, tpm_ppi_uuid, return acpi_evaluate_dsm_typed(ppi_handle, tpm_ppi_uuid,
TPM_PPI_REVISION_ID, func, argv4, type); TPM_PPI_REVISION_ID,
func, argv4, type);
} }
static ssize_t tpm_show_ppi_version(struct device *dev, static ssize_t tpm_show_ppi_version(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return scnprintf(buf, PAGE_SIZE, "%s\n", tpm_ppi_version); struct tpm_chip *chip = dev_get_drvdata(dev);
return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version);
} }
static ssize_t tpm_show_ppi_request(struct device *dev, 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,8 +63,10 @@ static ssize_t tpm_show_ppi_request(struct device *dev,
{ {
ssize_t size = -EINVAL; ssize_t size = -EINVAL;
union acpi_object *obj; union acpi_object *obj;
struct tpm_chip *chip = dev_get_drvdata(dev);
obj = tpm_eval_dsm(TPM_PPI_FN_GETREQ, ACPI_TYPE_PACKAGE, NULL); obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ,
ACPI_TYPE_PACKAGE, NULL);
if (!obj) if (!obj)
return -ENXIO; return -ENXIO;
...@@ -103,14 +100,15 @@ static ssize_t tpm_store_ppi_request(struct device *dev, ...@@ -103,14 +100,15 @@ static ssize_t tpm_store_ppi_request(struct device *dev,
int func = TPM_PPI_FN_SUBREQ; int func = TPM_PPI_FN_SUBREQ;
union acpi_object *obj, tmp; union acpi_object *obj, tmp;
union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp); union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp);
struct tpm_chip *chip = dev_get_drvdata(dev);
/* /*
* the function to submit TPM operation request to pre-os environment * the function to submit TPM operation request to pre-os environment
* is updated with function index from SUBREQ to SUBREQ2 since PPI * is updated with function index from SUBREQ to SUBREQ2 since PPI
* version 1.1 * version 1.1
*/ */
if (acpi_check_dsm(tpm_ppi_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, if (acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid,
1 << TPM_PPI_FN_SUBREQ2)) TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_SUBREQ2))
func = TPM_PPI_FN_SUBREQ2; func = TPM_PPI_FN_SUBREQ2;
/* /*
...@@ -119,7 +117,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev, ...@@ -119,7 +117,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev,
* string/package type. For PPI version 1.0 and 1.1, use buffer type * string/package type. For PPI version 1.0 and 1.1, use buffer type
* for compatibility, and use package type since 1.2 according to spec. * for compatibility, and use package type since 1.2 according to spec.
*/ */
if (strcmp(tpm_ppi_version, "1.2") < 0) { if (strcmp(chip->ppi_version, "1.2") < 0) {
if (sscanf(buf, "%d", &req) != 1) if (sscanf(buf, "%d", &req) != 1)
return -EINVAL; return -EINVAL;
argv4.type = ACPI_TYPE_BUFFER; argv4.type = ACPI_TYPE_BUFFER;
...@@ -131,7 +129,8 @@ static ssize_t tpm_store_ppi_request(struct device *dev, ...@@ -131,7 +129,8 @@ static ssize_t tpm_store_ppi_request(struct device *dev,
return -EINVAL; return -EINVAL;
} }
obj = tpm_eval_dsm(func, ACPI_TYPE_INTEGER, &argv4); obj = tpm_eval_dsm(chip->acpi_dev_handle, func, ACPI_TYPE_INTEGER,
&argv4);
if (!obj) { if (!obj) {
return -ENXIO; return -ENXIO;
} else { } else {
...@@ -157,6 +156,7 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev, ...@@ -157,6 +156,7 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev,
.buffer.length = 0, .buffer.length = 0,
.buffer.pointer = NULL .buffer.pointer = NULL
}; };
struct tpm_chip *chip = dev_get_drvdata(dev);
static char *info[] = { static char *info[] = {
"None", "None",
...@@ -171,9 +171,10 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev, ...@@ -171,9 +171,10 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev,
* (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
* compatibility, define params[3].type as buffer, if PPI version < 1.2 * compatibility, define params[3].type as buffer, if PPI version < 1.2
*/ */
if (strcmp(tpm_ppi_version, "1.2") < 0) if (strcmp(chip->ppi_version, "1.2") < 0)
obj = &tmp; obj = &tmp;
obj = tpm_eval_dsm(TPM_PPI_FN_GETACT, ACPI_TYPE_INTEGER, obj); obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETACT,
ACPI_TYPE_INTEGER, obj);
if (!obj) { if (!obj) {
return -ENXIO; return -ENXIO;
} else { } else {
...@@ -196,8 +197,10 @@ static ssize_t tpm_show_ppi_response(struct device *dev, ...@@ -196,8 +197,10 @@ static ssize_t tpm_show_ppi_response(struct device *dev,
acpi_status status = -EINVAL; acpi_status status = -EINVAL;
union acpi_object *obj, *ret_obj; union acpi_object *obj, *ret_obj;
u64 req, res; u64 req, res;
struct tpm_chip *chip = dev_get_drvdata(dev);
obj = tpm_eval_dsm(TPM_PPI_FN_GETRSP, ACPI_TYPE_PACKAGE, NULL); obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP,
ACPI_TYPE_PACKAGE, NULL);
if (!obj) if (!obj)
return -ENXIO; return -ENXIO;
...@@ -248,7 +251,8 @@ static ssize_t tpm_show_ppi_response(struct device *dev, ...@@ -248,7 +251,8 @@ static ssize_t tpm_show_ppi_response(struct device *dev,
return status; return status;
} }
static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start,
u32 end)
{ {
int i; int i;
u32 ret; u32 ret;
...@@ -264,14 +268,15 @@ static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) ...@@ -264,14 +268,15 @@ static ssize_t show_ppi_operations(char *buf, u32 start, u32 end)
"User not required", "User not required",
}; };
if (!acpi_check_dsm(tpm_ppi_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, if (!acpi_check_dsm(dev_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID,
1 << TPM_PPI_FN_GETOPR)) 1 << TPM_PPI_FN_GETOPR))
return -EPERM; return -EPERM;
tmp.integer.type = ACPI_TYPE_INTEGER; tmp.integer.type = ACPI_TYPE_INTEGER;
for (i = start; i <= end; i++) { for (i = start; i <= end; i++) {
tmp.integer.value = i; tmp.integer.value = i;
obj = tpm_eval_dsm(TPM_PPI_FN_GETOPR, ACPI_TYPE_INTEGER, &argv); obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR,
ACPI_TYPE_INTEGER, &argv);
if (!obj) { if (!obj) {
return -ENOMEM; return -ENOMEM;
} else { } else {
...@@ -291,14 +296,20 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device *dev, ...@@ -291,14 +296,20 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
return show_ppi_operations(buf, 0, PPI_TPM_REQ_MAX); struct tpm_chip *chip = dev_get_drvdata(dev);
return show_ppi_operations(chip->acpi_dev_handle, buf, 0,
PPI_TPM_REQ_MAX);
} }
static ssize_t tpm_show_ppi_vs_operations(struct device *dev, static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
return show_ppi_operations(buf, PPI_VS_REQ_START, PPI_VS_REQ_END); struct tpm_chip *chip = dev_get_drvdata(dev);
return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START,
PPI_VS_REQ_END);
} }
static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL); static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
...@@ -323,16 +334,38 @@ static struct attribute_group ppi_attr_grp = { ...@@ -323,16 +334,38 @@ static struct attribute_group ppi_attr_grp = {
.attrs = ppi_attrs .attrs = ppi_attrs
}; };
int tpm_add_ppi(struct kobject *parent) int tpm_add_ppi(struct tpm_chip *chip)
{ {
/* Cache TPM ACPI handle and version string */ union acpi_object *obj;
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, int rc;
ppi_callback, NULL, NULL, &tpm_ppi_handle);
return tpm_ppi_handle ? sysfs_create_group(parent, &ppi_attr_grp) : 0; if (!chip->acpi_dev_handle)
return 0;
if (!acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid,
TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_VERSION))
return 0;
/* Cache PPI version string. */
obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, tpm_ppi_uuid,
TPM_PPI_REVISION_ID, TPM_PPI_FN_VERSION,
NULL, ACPI_TYPE_STRING);
if (obj) {
strlcpy(chip->ppi_version, obj->string.pointer,
sizeof(chip->ppi_version));
ACPI_FREE(obj);
}
rc = sysfs_create_group(&chip->pdev->kobj, &ppi_attr_grp);
if (!rc)
chip->flags |= TPM_CHIP_FLAG_PPI;
return rc;
} }
void tpm_remove_ppi(struct kobject *parent) void tpm_remove_ppi(struct tpm_chip *chip)
{ {
if (tpm_ppi_handle) if (chip->flags & TPM_CHIP_FLAG_PPI)
sysfs_remove_group(parent, &ppi_attr_grp); sysfs_remove_group(&chip->pdev->kobj, &ppi_attr_grp);
} }
This diff is collapsed.
...@@ -175,9 +175,9 @@ static int setup_chip(struct device *dev, struct tpm_private *priv) ...@@ -175,9 +175,9 @@ static int setup_chip(struct device *dev, struct tpm_private *priv)
{ {
struct tpm_chip *chip; struct tpm_chip *chip;
chip = tpm_register_hardware(dev, &tpm_vtpm); chip = tpmm_chip_alloc(dev, &tpm_vtpm);
if (!chip) if (IS_ERR(chip))
return -ENODEV; return PTR_ERR(chip);
init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.read_queue);
...@@ -286,6 +286,7 @@ static int tpmfront_probe(struct xenbus_device *dev, ...@@ -286,6 +286,7 @@ static int tpmfront_probe(struct xenbus_device *dev,
const struct xenbus_device_id *id) const struct xenbus_device_id *id)
{ {
struct tpm_private *priv; struct tpm_private *priv;
struct tpm_chip *chip;
int rv; int rv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL); priv = kzalloc(sizeof(*priv), GFP_KERNEL);
...@@ -302,21 +303,22 @@ static int tpmfront_probe(struct xenbus_device *dev, ...@@ -302,21 +303,22 @@ static int tpmfront_probe(struct xenbus_device *dev,
rv = setup_ring(dev, priv); rv = setup_ring(dev, priv);
if (rv) { if (rv) {
tpm_remove_hardware(&dev->dev); chip = dev_get_drvdata(&dev->dev);
tpm_chip_unregister(chip);
ring_free(priv); ring_free(priv);
return rv; return rv;
} }
tpm_get_timeouts(priv->chip); tpm_get_timeouts(priv->chip);
return rv; return tpm_chip_register(priv->chip);
} }
static int tpmfront_remove(struct xenbus_device *dev) static int tpmfront_remove(struct xenbus_device *dev)
{ {
struct tpm_chip *chip = dev_get_drvdata(&dev->dev); struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
struct tpm_private *priv = TPM_VPRIV(chip); struct tpm_private *priv = TPM_VPRIV(chip);
tpm_remove_hardware(&dev->dev); tpm_chip_unregister(chip);
ring_free(priv); ring_free(priv);
TPM_VPRIV(chip) = NULL; TPM_VPRIV(chip) = NULL;
return 0; return 0;
......
...@@ -12,9 +12,8 @@ ...@@ -12,9 +12,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License
* with this program; if not, write to the Free Software Foundation, Inc., * along with this program; if not, see <http://www.gnu.org/licenses/>.
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* STMicroelectronics version 1.2.0, Copyright (C) 2010 * STMicroelectronics version 1.2.0, Copyright (C) 2010
* STMicroelectronics comes with ABSOLUTELY NO WARRANTY. * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
...@@ -23,39 +22,18 @@ ...@@ -23,39 +22,18 @@
* *
* @Author: Christophe RICARD tpmsupport@st.com * @Author: Christophe RICARD tpmsupport@st.com
* *
* @File: stm_st33_tpm_i2c.h * @File: stm_st33_tpm.h
* *
* @Date: 09/15/2010 * @Date: 09/15/2010
*/ */
#ifndef __STM_ST33_TPM_I2C_MAIN_H__ #ifndef __STM_ST33_TPM_H__
#define __STM_ST33_TPM_I2C_MAIN_H__ #define __STM_ST33_TPM_H__
#define TPM_ACCESS (0x0) #define TPM_ST33_I2C "st33zp24-i2c"
#define TPM_STS (0x18) #define TPM_ST33_SPI "st33zp24-spi"
#define TPM_HASH_END (0x20)
#define TPM_DATA_FIFO (0x24)
#define TPM_HASH_DATA (0x24)
#define TPM_HASH_START (0x28)
#define TPM_INTF_CAPABILITY (0x14)
#define TPM_INT_STATUS (0x10)
#define TPM_INT_ENABLE (0x08)
#define TPM_DUMMY_BYTE 0xAA
#define TPM_WRITE_DIRECTION 0x80
#define TPM_HEADER_SIZE 10
#define TPM_BUFSIZE 2048
#define LOCALITY0 0
#define TPM_ST33_I2C "st33zp24_i2c"
struct st33zp24_platform_data { struct st33zp24_platform_data {
int io_serirq;
int io_lpcpd; int io_lpcpd;
struct i2c_client *client;
u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */
struct completion irq_detection;
struct mutex lock;
}; };
#endif /* __STM_ST33_TPM_I2C_MAIN_H__ */ #endif /* __STM_ST33_TPM_H__ */
...@@ -120,13 +120,6 @@ extern int cipso_v4_rbm_optfmt; ...@@ -120,13 +120,6 @@ extern int cipso_v4_rbm_optfmt;
extern int cipso_v4_rbm_strictvalid; extern int cipso_v4_rbm_strictvalid;
#endif #endif
/*
* Helper Functions
*/
#define CIPSO_V4_OPTEXIST(x) (IPCB(x)->opt.cipso != 0)
#define CIPSO_V4_OPTPTR(x) (skb_network_header(x) + IPCB(x)->opt.cipso)
/* /*
* DOI List Functions * DOI List Functions
*/ */
...@@ -190,7 +183,7 @@ static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, ...@@ -190,7 +183,7 @@ static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
#ifdef CONFIG_NETLABEL #ifdef CONFIG_NETLABEL
void cipso_v4_cache_invalidate(void); void cipso_v4_cache_invalidate(void);
int cipso_v4_cache_add(const struct sk_buff *skb, int cipso_v4_cache_add(const unsigned char *cipso_ptr,
const struct netlbl_lsm_secattr *secattr); const struct netlbl_lsm_secattr *secattr);
#else #else
static inline void cipso_v4_cache_invalidate(void) static inline void cipso_v4_cache_invalidate(void)
...@@ -198,7 +191,7 @@ static inline void cipso_v4_cache_invalidate(void) ...@@ -198,7 +191,7 @@ static inline void cipso_v4_cache_invalidate(void)
return; return;
} }
static inline int cipso_v4_cache_add(const struct sk_buff *skb, static inline int cipso_v4_cache_add(const unsigned char *cipso_ptr,
const struct netlbl_lsm_secattr *secattr) const struct netlbl_lsm_secattr *secattr)
{ {
return 0; return 0;
...@@ -211,6 +204,8 @@ static inline int cipso_v4_cache_add(const struct sk_buff *skb, ...@@ -211,6 +204,8 @@ static inline int cipso_v4_cache_add(const struct sk_buff *skb,
#ifdef CONFIG_NETLABEL #ifdef CONFIG_NETLABEL
void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway); void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
int cipso_v4_getattr(const unsigned char *cipso,
struct netlbl_lsm_secattr *secattr);
int cipso_v4_sock_setattr(struct sock *sk, int cipso_v4_sock_setattr(struct sock *sk,
const struct cipso_v4_doi *doi_def, const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr); const struct netlbl_lsm_secattr *secattr);
...@@ -226,6 +221,7 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb, ...@@ -226,6 +221,7 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb,
int cipso_v4_skbuff_delattr(struct sk_buff *skb); int cipso_v4_skbuff_delattr(struct sk_buff *skb);
int cipso_v4_skbuff_getattr(const struct sk_buff *skb, int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr); struct netlbl_lsm_secattr *secattr);
unsigned char *cipso_v4_optptr(const struct sk_buff *skb);
int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option); int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option);
#else #else
static inline void cipso_v4_error(struct sk_buff *skb, 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,6 +231,12 @@ static inline void cipso_v4_error(struct sk_buff *skb,
return; return;
} }
static inline int cipso_v4_getattr(const unsigned char *cipso,
struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline int cipso_v4_sock_setattr(struct sock *sk, static inline int cipso_v4_sock_setattr(struct sock *sk,
const struct cipso_v4_doi *doi_def, const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr) const struct netlbl_lsm_secattr *secattr)
...@@ -282,6 +284,11 @@ static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb, ...@@ -282,6 +284,11 @@ static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
return -ENOSYS; return -ENOSYS;
} }
static inline unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
{
return NULL;
}
static inline int cipso_v4_validate(const struct sk_buff *skb, static inline int cipso_v4_validate(const struct sk_buff *skb,
unsigned char **option) unsigned char **option)
{ {
......
...@@ -143,7 +143,7 @@ endif ...@@ -143,7 +143,7 @@ endif
kernel/system_certificates.o: $(obj)/x509_certificate_list kernel/system_certificates.o: $(obj)/x509_certificate_list
quiet_cmd_x509certs = CERTS $@ quiet_cmd_x509certs = CERTS $@
cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; echo " - Including cert $(X509)") cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; $(kecho) " - Including cert $(X509)")
targets += $(obj)/x509_certificate_list targets += $(obj)/x509_certificate_list
$(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list
......
...@@ -57,14 +57,12 @@ int mpi_cmp(MPI u, MPI v) ...@@ -57,14 +57,12 @@ int mpi_cmp(MPI u, MPI v)
if (usize != vsize && !u->sign && !v->sign) if (usize != vsize && !u->sign && !v->sign)
return usize - vsize; return usize - vsize;
if (usize != vsize && u->sign && v->sign) if (usize != vsize && u->sign && v->sign)
return vsize + usize; return vsize - usize;
if (!usize) if (!usize)
return 0; return 0;
cmp = mpihelp_cmp(u->d, v->d, usize); cmp = mpihelp_cmp(u->d, v->d, usize);
if (!cmp) if (u->sign)
return 0; return -cmp;
if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) return cmp;
return 1;
return -1;
} }
EXPORT_SYMBOL_GPL(mpi_cmp); EXPORT_SYMBOL_GPL(mpi_cmp);
...@@ -84,7 +84,7 @@ static inline int RESIZE_IF_NEEDED(MPI a, unsigned b) ...@@ -84,7 +84,7 @@ static inline int RESIZE_IF_NEEDED(MPI a, unsigned b)
do { \ do { \
mpi_size_t _i; \ mpi_size_t _i; \
for (_i = 0; _i < (n); _i++) \ for (_i = 0; _i < (n); _i++) \
(d)[_i] = (d)[_i]; \ (d)[_i] = (s)[_i]; \
} while (0) } while (0)
#define MPN_COPY_DECR(d, s, n) \ #define MPN_COPY_DECR(d, s, n) \
......
This diff is collapsed.
...@@ -1065,10 +1065,12 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, ...@@ -1065,10 +1065,12 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
u16 family, u16 family,
struct netlbl_lsm_secattr *secattr) struct netlbl_lsm_secattr *secattr)
{ {
unsigned char *ptr;
switch (family) { switch (family) {
case AF_INET: case AF_INET:
if (CIPSO_V4_OPTEXIST(skb) && ptr = cipso_v4_optptr(skb);
cipso_v4_skbuff_getattr(skb, secattr) == 0) if (ptr && cipso_v4_getattr(ptr, secattr) == 0)
return 0; return 0;
break; break;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
...@@ -1094,7 +1096,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, ...@@ -1094,7 +1096,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
*/ */
void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway) void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
{ {
if (CIPSO_V4_OPTEXIST(skb)) if (cipso_v4_optptr(skb))
cipso_v4_error(skb, error, gateway); cipso_v4_error(skb, error, gateway);
} }
...@@ -1126,11 +1128,14 @@ void netlbl_cache_invalidate(void) ...@@ -1126,11 +1128,14 @@ void netlbl_cache_invalidate(void)
int netlbl_cache_add(const struct sk_buff *skb, int netlbl_cache_add(const struct sk_buff *skb,
const struct netlbl_lsm_secattr *secattr) const struct netlbl_lsm_secattr *secattr)
{ {
unsigned char *ptr;
if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0) if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
return -ENOMSG; return -ENOMSG;
if (CIPSO_V4_OPTEXIST(skb)) ptr = cipso_v4_optptr(skb);
return cipso_v4_cache_add(skb, secattr); if (ptr)
return cipso_v4_cache_add(ptr, secattr);
return -ENOMSG; return -ENOMSG;
} }
......
This diff is collapsed.
...@@ -126,7 +126,6 @@ config IMA_TRUSTED_KEYRING ...@@ -126,7 +126,6 @@ config IMA_TRUSTED_KEYRING
bool "Require all keys on the .ima keyring be signed" bool "Require all keys on the .ima keyring be signed"
depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING
depends on INTEGRITY_ASYMMETRIC_KEYS depends on INTEGRITY_ASYMMETRIC_KEYS
select KEYS_DEBUG_PROC_KEYS
default y default y
help help
This option requires that all keys added to the .ima This option requires that all keys added to the .ima
......
This diff is collapsed.
This diff is collapsed.
...@@ -517,11 +517,6 @@ int __init avc_add_callback(int (*callback)(u32 event), u32 events) ...@@ -517,11 +517,6 @@ int __init avc_add_callback(int (*callback)(u32 event), u32 events)
return rc; return rc;
} }
static inline int avc_sidcmp(u32 x, u32 y)
{
return (x == y || x == SECSID_WILD || y == SECSID_WILD);
}
/** /**
* avc_update_node Update an AVC entry * avc_update_node Update an AVC entry
* @event : Updating event * @event : Updating event
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment