linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
@ 2012-08-22 21:52 Kent Yoder
  2012-08-22 23:42 ` Jeff Garzik
  2012-08-23 20:32 ` James Morris
  0 siblings, 2 replies; 14+ messages in thread
From: Kent Yoder @ 2012-08-22 21:52 UTC (permalink / raw)
  To: James Morris
  Cc: linux-kernel, linux-security-module, tpmdd-devel, adlai,
	xiaoyan.zhang, jj, key, peter.huewe

  Hi James,

The following changes since commit 51b743fe87d7fb3dba7a2ff4a1fe23bb65dc2245:

  Merge tag 'v3.6-rc2' into next (2012-08-17 20:42:30 +1000)

are available in the git repository at:

  git://github.com/shpedoikal/linux.git v3.6-rc2-tpmdd

New stuff since my last pull request are Jesper's error checking of the
acpi_os_map_memory call, Ashley's vTPM driver for PPC64, my enabling the
vTPM driver when IMA is selected on PPC64 and Xiaoyan's addition of
Physical Presence Interface.

Thanks,
Kent

Ashley Lai (3):
      drivers/char/tpm: Add new device driver to support IBM vTPM
      PPC64: Add support for instantiating SML from Open Firmware
      drivers/char/tpm: Add securityfs support for event log

Jesper Juhl (1):
      tpm: Do not dereference NULL pointer if acpi_os_map_memory() fails.

Kent Yoder (6):
      tpm: modularize event log collection
      tpm: Move tpm_get_random api into the TPM device driver
      hw_random: add support for the TPM chip as a hardware RNG source
      tpm: fix double write race and tpm_release free issue
      tpm: compile out unused code in the PNP and PM cases
      ima: enable the IBM vTPM as the default TPM in the PPC64 case

Peter Huewe (1):
      char/tpm: Add new driver for Infineon I2C TIS TPM

Xiaoyan Zhang (2):
      Documentation: sysfs for Physical Presence Interface
      driver: add PPI support in tpm driver

 Documentation/ABI/testing/sysfs-driver-ppi      |   70 +++
 arch/powerpc/kernel/prom_init.c                 |   62 ++
 drivers/char/hw_random/Kconfig                  |   13 +
 drivers/char/hw_random/Makefile                 |    1 +
 drivers/char/hw_random/tpm-rng.c                |   50 ++
 drivers/char/tpm/Kconfig                        |   19 +
 drivers/char/tpm/Makefile                       |    8 +
 drivers/char/tpm/tpm.c                          |   70 ++-
 drivers/char/tpm/tpm.h                          |   35 +-
 drivers/char/tpm/tpm_acpi.c                     |  109 ++++
 drivers/char/tpm/{tpm_bios.c => tpm_eventlog.c} |  147 +-----
 drivers/char/tpm/tpm_eventlog.h                 |   86 +++
 drivers/char/tpm/tpm_i2c_infineon.c             |  695 +++++++++++++++++++++
 drivers/char/tpm/tpm_ibmvtpm.c                  |  749 +++++++++++++++++++++++
 drivers/char/tpm/tpm_ibmvtpm.h                  |   77 +++
 drivers/char/tpm/tpm_of.c                       |   73 +++
 drivers/char/tpm/tpm_ppi.c                      |  460 ++++++++++++++
 drivers/char/tpm/tpm_tis.c                      |    3 +-
 include/linux/tpm.h                             |    4 +
 security/integrity/ima/Kconfig                  |    1 +
 security/keys/trusted.c                         |   54 +--
 21 files changed, 2586 insertions(+), 200 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-ppi
 create mode 100644 drivers/char/hw_random/tpm-rng.c
 create mode 100644 drivers/char/tpm/tpm_acpi.c
 rename drivers/char/tpm/{tpm_bios.c => tpm_eventlog.c} (75%)
 create mode 100644 drivers/char/tpm/tpm_eventlog.h
 create mode 100644 drivers/char/tpm/tpm_i2c_infineon.c
 create mode 100644 drivers/char/tpm/tpm_ibmvtpm.c
 create mode 100644 drivers/char/tpm/tpm_ibmvtpm.h
 create mode 100644 drivers/char/tpm/tpm_of.c
 create mode 100644 drivers/char/tpm/tpm_ppi.c

diff --git a/Documentation/ABI/testing/sysfs-driver-ppi b/Documentation/ABI/testing/sysfs-driver-ppi
new file mode 100644
index 0000000..97a003e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-ppi
@@ -0,0 +1,70 @@
+What:		/sys/devices/pnp0/<bus-num>/ppi/
+Date:		August 2012
+Kernel Version:	3.6
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This folder includes the attributes related with PPI (Physical
+		Presence Interface). Only if TPM is supported by BIOS, this
+		folder makes sence. The folder path can be got by command
+		'find /sys/ -name 'pcrs''. For the detail information of PPI,
+		please refer to the PPI specification from
+		http://www.trustedcomputinggroup.org/
+
+What:		/sys/devices/pnp0/<bus-num>/ppi/version
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows the version of the PPI supported by the
+		platform.
+		This file is readonly.
+
+What:		/sys/devices/pnp0/<bus-num>/ppi/request
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows the request for an operation to be
+		executed in the pre-OS environment. It is the only input from
+		the OS to the pre-OS environment. The request should be an
+		integer value range from 1 to 160, and 0 means no request.
+		This file can be read and written.
+
+What:		/sys/devices/pnp0/00:<bus-num>/ppi/response
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows the response to the most recent operation
+		request it acted upon. The format is "<request> <response num>
+		: <response description>".
+		This file is readonly.
+
+What:		/sys/devices/pnp0/<bus-num>/ppi/transition_action
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows the platform-specific action that should
+		take place in order to transition to the BIOS for execution of
+		a requested operation. The format is "<action num>: <action
+		description>".
+		This file is readonly.
+
+What:		/sys/devices/pnp0/<bus-num>/ppi/tcg_operations
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows whether it is allowed to request an
+		operation to be executed in the pre-OS environment by the BIOS
+		for the requests defined by TCG, i.e. requests from 1 to 22.
+		The format is "<request> <status num>: <status description>".
+		This attribute is only supported by PPI version 1.2+.
+		This file is readonly.
+
+What:		/sys/devices/pnp0/<bus-num>/ppi/vs_operations
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows whether it is allowed to request an
+		operation to be executed in the pre-OS environment by the BIOS
+		for the verdor specific requests, i.e. requests from 128 to
+		255. The format is same with tcg_operations. This attribute
+		is also only supported by PPI version 1.2+.
+		This file is readonly.
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 0794a30..e144498 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -1624,6 +1624,63 @@ static void __init prom_instantiate_rtas(void)
 
 #ifdef CONFIG_PPC64
 /*
+ * Allocate room for and instantiate Stored Measurement Log (SML)
+ */
+static void __init prom_instantiate_sml(void)
+{
+	phandle ibmvtpm_node;
+	ihandle ibmvtpm_inst;
+	u32 entry = 0, size = 0;
+	u64 base;
+
+	prom_debug("prom_instantiate_sml: start...\n");
+
+	ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/ibm,vtpm"));
+	prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
+	if (!PHANDLE_VALID(ibmvtpm_node))
+		return;
+
+	ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/ibm,vtpm"));
+	if (!IHANDLE_VALID(ibmvtpm_inst)) {
+		prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
+		return;
+	}
+
+	if (call_prom_ret("call-method", 2, 2, &size,
+			  ADDR("sml-get-handover-size"),
+			  ibmvtpm_inst) != 0 || size == 0) {
+		prom_printf("SML get handover size failed\n");
+		return;
+	}
+
+	base = alloc_down(size, PAGE_SIZE, 0);
+	if (base == 0)
+		prom_panic("Could not allocate memory for sml\n");
+
+	prom_printf("instantiating sml at 0x%x...", base);
+
+	if (call_prom_ret("call-method", 4, 2, &entry,
+			  ADDR("sml-handover"),
+			  ibmvtpm_inst, size, base) != 0 || entry == 0) {
+		prom_printf("SML handover failed\n");
+		return;
+	}
+	prom_printf(" done\n");
+
+	reserve_mem(base, size);
+
+	prom_setprop(ibmvtpm_node, "/ibm,vtpm", "linux,sml-base",
+		     &base, sizeof(base));
+	prom_setprop(ibmvtpm_node, "/ibm,vtpm", "linux,sml-size",
+		     &size, sizeof(size));
+
+	prom_debug("sml base     = 0x%x\n", base);
+	prom_debug("sml size     = 0x%x\n", (long)size);
+
+	prom_debug("prom_instantiate_sml: end...\n");
+}
+
+/*
  * Allocate room for and initialize TCE tables
  */
 static void __init prom_initialize_tce_table(void)
@@ -2916,6 +2973,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
 		prom_instantiate_opal();
 #endif
 
+#ifdef CONFIG_PPC64
+	/* instantiate sml */
+	prom_instantiate_sml();
+#endif
+
 	/*
 	 * On non-powermacs, put all CPUs in spin-loops.
 	 *
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 7c0d391..fbd9b2b 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -289,3 +289,16 @@ config HW_RANDOM_EXYNOS
 	  module will be called exynos-rng.
 
 	  If unsure, say Y.
+
+config HW_RANDOM_TPM
+	tristate "TPM HW Random Number Generator support"
+	depends on HW_RANDOM && TCG_TPM
+	default HW_RANDOM
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator in the Trusted Platform Module
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tpm-rng.
+
+	  If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 39a757c..1fd7eec 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
 obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
 obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
 obj-$(CONFIG_HW_RANDOM_EXYNOS)	+= exynos-rng.o
+obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
diff --git a/drivers/char/hw_random/tpm-rng.c b/drivers/char/hw_random/tpm-rng.c
new file mode 100644
index 0000000..d6d4482
--- /dev/null
+++ b/drivers/char/hw_random/tpm-rng.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Kent Yoder IBM Corporation
+ *
+ * HWRNG interfaces to pull RNG data from a TPM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/hw_random.h>
+#include <linux/tpm.h>
+
+#define MODULE_NAME "tpm-rng"
+
+static int tpm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+	return tpm_get_random(TPM_ANY_NUM, data, max);
+}
+
+static struct hwrng tpm_rng = {
+	.name = MODULE_NAME,
+	.read = tpm_rng_read,
+};
+
+static int __init rng_init(void)
+{
+	return hwrng_register(&tpm_rng);
+}
+module_init(rng_init);
+
+static void __exit rng_exit(void)
+{
+	hwrng_unregister(&tpm_rng);
+}
+module_exit(rng_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Kent Yoder <key@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("RNG driver for TPM devices");
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index a048199..915875e 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -33,6 +33,17 @@ config TCG_TIS
 	  from within Linux.  To compile this driver as a module, choose
 	  M here; the module will be called tpm_tis.
 
+config TCG_TIS_I2C_INFINEON
+	tristate "TPM Interface Specification 1.2 Interface (I2C - Infineon)"
+	depends on I2C
+	---help---
+	  If you have a TPM security chip that is compliant with the
+	  TCG TIS 1.2 TPM specification and Infineon's I2C Protocol Stack
+	  Specification 0.20 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_tis_i2c_infineon.
+
 config TCG_NSC
 	tristate "National Semiconductor TPM Interface"
 	depends on X86
@@ -62,4 +73,12 @@ config TCG_INFINEON
 	  Further information on this driver and the supported hardware
 	  can be found at http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ 
 
+config TCG_IBMVTPM
+	tristate "IBM VTPM Interface"
+	depends on PPC64
+	---help---
+	  If you have IBM virtual TPM (VTPM) support 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_ibmvtpm.
+
 endif # TCG_TPM
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index ea3a1e0..5b3fc8b 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -4,8 +4,16 @@
 obj-$(CONFIG_TCG_TPM) += tpm.o
 ifdef CONFIG_ACPI
 	obj-$(CONFIG_TCG_TPM) += tpm_bios.o
+	tpm_bios-objs += tpm_eventlog.o tpm_acpi.o tpm_ppi.o
+else
+ifdef CONFIG_TCG_IBMVTPM
+	obj-$(CONFIG_TCG_TPM) += tpm_bios.o
+	tpm_bios-objs += tpm_eventlog.o tpm_of.o
+endif
 endif
 obj-$(CONFIG_TCG_TIS) += tpm_tis.o
+obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
 obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
 obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
 obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
+obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 817f0ee..39526c0 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -30,12 +30,7 @@
 #include <linux/freezer.h>
 
 #include "tpm.h"
-
-enum tpm_const {
-	TPM_MINOR = 224,	/* officially assigned */
-	TPM_BUFSIZE = 4096,
-	TPM_NUM_DEVICES = 256,
-};
+#include "tpm_eventlog.h"
 
 enum tpm_duration {
 	TPM_SHORT = 0,
@@ -482,6 +477,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
 #define TPM_INTERNAL_RESULT_SIZE 200
 #define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
 #define TPM_ORD_GET_CAP cpu_to_be32(101)
+#define TPM_ORD_GET_RANDOM cpu_to_be32(70)
 
 static const struct tpm_input_header tpm_getcap_header = {
 	.tag = TPM_TAG_RQU_COMMAND,
@@ -1175,7 +1171,7 @@ int tpm_release(struct inode *inode, struct file *file)
 	flush_work_sync(&chip->work);
 	file->private_data = NULL;
 	atomic_set(&chip->data_pending, 0);
-	kfree(chip->data_buffer);
+	kzfree(chip->data_buffer);
 	clear_bit(0, &chip->is_open);
 	put_device(chip->dev);
 	return 0;
@@ -1227,7 +1223,6 @@ ssize_t tpm_read(struct file *file, char __user *buf,
 	del_singleshot_timer_sync(&chip->user_read_timer);
 	flush_work_sync(&chip->work);
 	ret_size = atomic_read(&chip->data_pending);
-	atomic_set(&chip->data_pending, 0);
 	if (ret_size > 0) {	/* relay data */
 		ssize_t orig_ret_size = ret_size;
 		if (size < ret_size)
@@ -1242,6 +1237,8 @@ ssize_t tpm_read(struct file *file, char __user *buf,
 		mutex_unlock(&chip->buffer_mutex);
 	}
 
+	atomic_set(&chip->data_pending, 0);
+
 	return ret_size;
 }
 EXPORT_SYMBOL_GPL(tpm_read);
@@ -1326,6 +1323,58 @@ int tpm_pm_resume(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(tpm_pm_resume);
 
+#define TPM_GETRANDOM_RESULT_SIZE	18
+static struct tpm_input_header tpm_getrandom_header = {
+	.tag = TPM_TAG_RQU_COMMAND,
+	.length = cpu_to_be32(14),
+	.ordinal = TPM_ORD_GET_RANDOM
+};
+
+/**
+ * tpm_get_random() - Get random bytes from the tpm's RNG
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @out: destination buffer for the random bytes
+ * @max: the max number of bytes to write to @out
+ *
+ * Returns < 0 on error and the number of bytes read on success
+ */
+int tpm_get_random(u32 chip_num, u8 *out, size_t max)
+{
+	struct tpm_chip *chip;
+	struct tpm_cmd_t tpm_cmd;
+	u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
+	int err, total = 0, retries = 5;
+	u8 *dest = out;
+
+	chip = tpm_chip_find_get(chip_num);
+	if (chip == NULL)
+		return -ENODEV;
+
+	if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
+		return -EINVAL;
+
+	do {
+		tpm_cmd.header.in = tpm_getrandom_header;
+		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
+
+		err = transmit_cmd(chip, &tpm_cmd,
+				   TPM_GETRANDOM_RESULT_SIZE + num_bytes,
+				   "attempting get random");
+		if (err)
+			break;
+
+		recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
+		memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
+
+		dest += recd;
+		total += recd;
+		num_bytes -= recd;
+	} while (retries-- && total < max);
+
+	return total ? total : -EIO;
+}
+EXPORT_SYMBOL_GPL(tpm_get_random);
+
 /* In case vendor provided release function, call it too.*/
 
 void tpm_dev_vendor_release(struct tpm_chip *chip)
@@ -1427,6 +1476,11 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
 		goto put_device;
 	}
 
+	if (sys_add_ppi(&dev->kobj)) {
+		misc_deregister(&chip->vendor.miscdev);
+		goto put_device;
+	}
+
 	chip->bios_dir = tpm_bios_log_setup(devname);
 
 	/* Make chip available */
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 917f727..02c266a 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -28,6 +28,12 @@
 #include <linux/io.h>
 #include <linux/tpm.h>
 
+enum tpm_const {
+	TPM_MINOR = 224,	/* officially assigned */
+	TPM_BUFSIZE = 4096,
+	TPM_NUM_DEVICES = 256,
+};
+
 enum tpm_timeout {
 	TPM_TIMEOUT = 5,	/* msecs */
 };
@@ -94,6 +100,7 @@ struct tpm_vendor_specific {
 	bool timeout_adjusted;
 	unsigned long duration[3]; /* jiffies */
 	bool duration_adjusted;
+	void *data;
 
 	wait_queue_head_t read_queue;
 	wait_queue_head_t int_queue;
@@ -269,6 +276,21 @@ struct tpm_pcrextend_in {
 	u8	hash[TPM_DIGEST_SIZE];
 }__attribute__((packed));
 
+/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
+ * bytes, but 128 is still a relatively large number of random bytes and
+ * anything much bigger causes users of struct tpm_cmd_t to start getting
+ * compiler warnings about stack frame size. */
+#define TPM_MAX_RNG_DATA	128
+
+struct tpm_getrandom_out {
+	__be32 rng_data_len;
+	u8     rng_data[TPM_MAX_RNG_DATA];
+}__attribute__((packed));
+
+struct tpm_getrandom_in {
+	__be32 num_bytes;
+}__attribute__((packed));
+
 typedef union {
 	struct	tpm_getcap_params_out getcap_out;
 	struct	tpm_readpubek_params_out readpubek_out;
@@ -277,6 +299,8 @@ typedef union {
 	struct	tpm_pcrread_in	pcrread_in;
 	struct	tpm_pcrread_out	pcrread_out;
 	struct	tpm_pcrextend_in pcrextend_in;
+	struct	tpm_getrandom_in getrandom_in;
+	struct	tpm_getrandom_out getrandom_out;
 } tpm_cmd_params;
 
 struct tpm_cmd_t {
@@ -303,15 +327,12 @@ extern int tpm_pm_suspend(struct device *);
 extern int tpm_pm_resume(struct device *);
 extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
 			     wait_queue_head_t *);
+
 #ifdef CONFIG_ACPI
-extern struct dentry ** tpm_bios_log_setup(char *);
-extern void tpm_bios_log_teardown(struct dentry **);
+extern ssize_t sys_add_ppi(struct kobject *parent);
 #else
-static inline struct dentry ** tpm_bios_log_setup(char *name)
-{
-	return NULL;
-}
-static inline void tpm_bios_log_teardown(struct dentry **dir)
+static inline ssize_t sys_add_ppi(struct kobject *parent)
 {
+	return 0;
 }
 #endif
diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_acpi.c
new file mode 100644
index 0000000..fe3fa94
--- /dev/null
+++ b/drivers/char/tpm/tpm_acpi.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2005 IBM Corporation
+ *
+ * Authors:
+ *	Seiji Munetoh <munetoh@jp.ibm.com>
+ *	Stefan Berger <stefanb@us.ibm.com>
+ *	Reiner Sailer <sailer@watson.ibm.com>
+ *	Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Access to the eventlog extended by the TCG BIOS of PC platform
+ *
+ * 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; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/seq_file.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <acpi/acpi.h>
+
+#include "tpm.h"
+#include "tpm_eventlog.h"
+
+struct acpi_tcpa {
+	struct acpi_table_header hdr;
+	u16 platform_class;
+	union {
+		struct client_hdr {
+			u32 log_max_len __attribute__ ((packed));
+			u64 log_start_addr __attribute__ ((packed));
+		} client;
+		struct server_hdr {
+			u16 reserved;
+			u64 log_max_len __attribute__ ((packed));
+			u64 log_start_addr __attribute__ ((packed));
+		} server;
+	};
+};
+
+/* read binary bios log */
+int read_log(struct tpm_bios_log *log)
+{
+	struct acpi_tcpa *buff;
+	acpi_status status;
+	struct acpi_table_header *virt;
+	u64 len, start;
+
+	if (log->bios_event_log != NULL) {
+		printk(KERN_ERR
+		       "%s: ERROR - Eventlog already initialized\n",
+		       __func__);
+		return -EFAULT;
+	}
+
+	/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
+	status = acpi_get_table(ACPI_SIG_TCPA, 1,
+				(struct acpi_table_header **)&buff);
+
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
+		       __func__);
+		return -EIO;
+	}
+
+	switch(buff->platform_class) {
+	case BIOS_SERVER:
+		len = buff->server.log_max_len;
+		start = buff->server.log_start_addr;
+		break;
+	case BIOS_CLIENT:
+	default:
+		len = buff->client.log_max_len;
+		start = buff->client.log_start_addr;
+		break;
+	}
+	if (!len) {
+		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
+		return -EIO;
+	}
+
+	/* malloc EventLog space */
+	log->bios_event_log = kmalloc(len, GFP_KERNEL);
+	if (!log->bios_event_log) {
+		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	log->bios_event_log_end = log->bios_event_log + len;
+
+	virt = acpi_os_map_memory(start, len);
+	if (!virt) {
+		kfree(log->bios_event_log);
+		printk("%s: ERROR - Unable to map memory\n", __func__);
+		return -EIO;
+	}
+
+	memcpy(log->bios_event_log, virt, len);
+
+	acpi_os_unmap_memory(virt, len);
+	return 0;
+}
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_eventlog.c
similarity index 75%
rename from drivers/char/tpm/tpm_bios.c
rename to drivers/char/tpm/tpm_eventlog.c
index 0636520..84ddc55 100644
--- a/drivers/char/tpm/tpm_bios.c
+++ b/drivers/char/tpm/tpm_eventlog.c
@@ -1,7 +1,8 @@
 /*
- * Copyright (C) 2005 IBM Corporation
+ * Copyright (C) 2005, 2012 IBM Corporation
  *
  * Authors:
+ *	Kent Yoder <key@linux.vnet.ibm.com>
  *	Seiji Munetoh <munetoh@jp.ibm.com>
  *	Stefan Berger <stefanb@us.ibm.com>
  *	Reiner Sailer <sailer@watson.ibm.com>
@@ -9,7 +10,7 @@
  *
  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
  *
- * Access to the eventlog extended by the TCG BIOS of PC platform
+ * Access to the eventlog created by a system's firmware / BIOS
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -23,67 +24,10 @@
 #include <linux/security.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <acpi/acpi.h>
-#include "tpm.h"
-
-#define TCG_EVENT_NAME_LEN_MAX	255
-#define MAX_TEXT_EVENT		1000	/* Max event string length */
-#define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
-
-enum bios_platform_class {
-	BIOS_CLIENT = 0x00,
-	BIOS_SERVER = 0x01,
-};
-
-struct tpm_bios_log {
-	void *bios_event_log;
-	void *bios_event_log_end;
-};
-
-struct acpi_tcpa {
-	struct acpi_table_header hdr;
-	u16 platform_class;
-	union {
-		struct client_hdr {
-			u32 log_max_len __attribute__ ((packed));
-			u64 log_start_addr __attribute__ ((packed));
-		} client;
-		struct server_hdr {
-			u16 reserved;
-			u64 log_max_len __attribute__ ((packed));
-			u64 log_start_addr __attribute__ ((packed));
-		} server;
-	};
-};
 
-struct tcpa_event {
-	u32 pcr_index;
-	u32 event_type;
-	u8 pcr_value[20];	/* SHA1 */
-	u32 event_size;
-	u8 event_data[0];
-};
+#include "tpm.h"
+#include "tpm_eventlog.h"
 
-enum tcpa_event_types {
-	PREBOOT = 0,
-	POST_CODE,
-	UNUSED,
-	NO_ACTION,
-	SEPARATOR,
-	ACTION,
-	EVENT_TAG,
-	SCRTM_CONTENTS,
-	SCRTM_VERSION,
-	CPU_MICROCODE,
-	PLATFORM_CONFIG_FLAGS,
-	TABLE_OF_DEVICES,
-	COMPACT_HASH,
-	IPL,
-	IPL_PARTITION_DATA,
-	NONHOST_CODE,
-	NONHOST_CONFIG,
-	NONHOST_INFO,
-};
 
 static const char* tcpa_event_type_strings[] = {
 	"PREBOOT",
@@ -106,28 +50,6 @@ static const char* tcpa_event_type_strings[] = {
 	"Non-Host Info"
 };
 
-struct tcpa_pc_event {
-	u32 event_id;
-	u32 event_size;
-	u8 event_data[0];
-};
-
-enum tcpa_pc_event_ids {
-	SMBIOS = 1,
-	BIS_CERT,
-	POST_BIOS_ROM,
-	ESCD,
-	CMOS,
-	NVRAM,
-	OPTION_ROM_EXEC,
-	OPTION_ROM_CONFIG,
-	OPTION_ROM_MICROCODE = 10,
-	S_CRTM_VERSION,
-	S_CRTM_CONTENTS,
-	POST_CONTENTS,
-	HOST_TABLE_OF_DEVICES,
-};
-
 static const char* tcpa_pc_event_id_strings[] = {
 	"",
 	"SMBIOS",
@@ -358,65 +280,6 @@ static const struct seq_operations tpm_binary_b_measurments_seqops = {
 	.show = tpm_binary_bios_measurements_show,
 };
 
-/* read binary bios log */
-static int read_log(struct tpm_bios_log *log)
-{
-	struct acpi_tcpa *buff;
-	acpi_status status;
-	struct acpi_table_header *virt;
-	u64 len, start;
-
-	if (log->bios_event_log != NULL) {
-		printk(KERN_ERR
-		       "%s: ERROR - Eventlog already initialized\n",
-		       __func__);
-		return -EFAULT;
-	}
-
-	/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
-	status = acpi_get_table(ACPI_SIG_TCPA, 1,
-				(struct acpi_table_header **)&buff);
-
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
-		       __func__);
-		return -EIO;
-	}
-
-	switch(buff->platform_class) {
-	case BIOS_SERVER:
-		len = buff->server.log_max_len;
-		start = buff->server.log_start_addr;
-		break;
-	case BIOS_CLIENT:
-	default:
-		len = buff->client.log_max_len;
-		start = buff->client.log_start_addr;
-		break;
-	}
-	if (!len) {
-		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
-		return -EIO;
-	}
-
-	/* malloc EventLog space */
-	log->bios_event_log = kmalloc(len, GFP_KERNEL);
-	if (!log->bios_event_log) {
-		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
-			__func__);
-		return -ENOMEM;
-	}
-
-	log->bios_event_log_end = log->bios_event_log + len;
-
-	virt = acpi_os_map_memory(start, len);
-
-	memcpy(log->bios_event_log, virt, len);
-
-	acpi_os_unmap_memory(virt, len);
-	return 0;
-}
-
 static int tpm_ascii_bios_measurements_open(struct inode *inode,
 					    struct file *file)
 {
diff --git a/drivers/char/tpm/tpm_eventlog.h b/drivers/char/tpm/tpm_eventlog.h
new file mode 100644
index 0000000..e7da086
--- /dev/null
+++ b/drivers/char/tpm/tpm_eventlog.h
@@ -0,0 +1,86 @@
+
+#ifndef __TPM_EVENTLOG_H__
+#define __TPM_EVENTLOG_H__
+
+#define TCG_EVENT_NAME_LEN_MAX	255
+#define MAX_TEXT_EVENT		1000	/* Max event string length */
+#define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
+
+enum bios_platform_class {
+	BIOS_CLIENT = 0x00,
+	BIOS_SERVER = 0x01,
+};
+
+struct tpm_bios_log {
+	void *bios_event_log;
+	void *bios_event_log_end;
+};
+
+struct tcpa_event {
+	u32 pcr_index;
+	u32 event_type;
+	u8 pcr_value[20];	/* SHA1 */
+	u32 event_size;
+	u8 event_data[0];
+};
+
+enum tcpa_event_types {
+	PREBOOT = 0,
+	POST_CODE,
+	UNUSED,
+	NO_ACTION,
+	SEPARATOR,
+	ACTION,
+	EVENT_TAG,
+	SCRTM_CONTENTS,
+	SCRTM_VERSION,
+	CPU_MICROCODE,
+	PLATFORM_CONFIG_FLAGS,
+	TABLE_OF_DEVICES,
+	COMPACT_HASH,
+	IPL,
+	IPL_PARTITION_DATA,
+	NONHOST_CODE,
+	NONHOST_CONFIG,
+	NONHOST_INFO,
+};
+
+struct tcpa_pc_event {
+	u32 event_id;
+	u32 event_size;
+	u8 event_data[0];
+};
+
+enum tcpa_pc_event_ids {
+	SMBIOS = 1,
+	BIS_CERT,
+	POST_BIOS_ROM,
+	ESCD,
+	CMOS,
+	NVRAM,
+	OPTION_ROM_EXEC,
+	OPTION_ROM_CONFIG,
+	OPTION_ROM_MICROCODE = 10,
+	S_CRTM_VERSION,
+	S_CRTM_CONTENTS,
+	POST_CONTENTS,
+	HOST_TABLE_OF_DEVICES,
+};
+
+int read_log(struct tpm_bios_log *log);
+
+#if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \
+	defined(CONFIG_ACPI)
+extern struct dentry **tpm_bios_log_setup(char *);
+extern void tpm_bios_log_teardown(struct dentry **);
+#else
+static inline struct dentry **tpm_bios_log_setup(char *name)
+{
+	return NULL;
+}
+static inline void tpm_bios_log_teardown(struct dentry **dir)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
new file mode 100644
index 0000000..5a831ae
--- /dev/null
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -0,0 +1,695 @@
+/*
+ * Copyright (C) 2012 Infineon Technologies
+ *
+ * Authors:
+ * Peter Huewe <peter.huewe@infineon.com>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
+ * Infineon I2C Protocol Stack Specification v0.20.
+ *
+ * It is based on the original tpm_tis device driver from Leendert van
+ * Dorn and Kyleen Hall.
+ *
+ * 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/init.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/wait.h>
+#include "tpm.h"
+
+/* max. buffer size supported by our TPM */
+#define TPM_BUFSIZE 1260
+
+/* max. number of iterations after I2C NAK */
+#define MAX_COUNT 3
+
+#define SLEEP_DURATION_LOW 55
+#define SLEEP_DURATION_HI 65
+
+/* max. number of iterations after I2C NAK for 'long' commands
+ * we need this especially for sending TPM_READY, since the cleanup after the
+ * transtion to the ready state may take some time, but it is unpredictable
+ * how long it will take.
+ */
+#define MAX_COUNT_LONG 50
+
+#define SLEEP_DURATION_LONG_LOW 200
+#define SLEEP_DURATION_LONG_HI 220
+
+/* After sending TPM_READY to 'reset' the TPM we have to sleep even longer */
+#define SLEEP_DURATION_RESET_LOW 2400
+#define SLEEP_DURATION_RESET_HI 2600
+
+/* we want to use usleep_range instead of msleep for the 5ms TPM_TIMEOUT */
+#define TPM_TIMEOUT_US_LOW (TPM_TIMEOUT * 1000)
+#define TPM_TIMEOUT_US_HI  (TPM_TIMEOUT_US_LOW + 2000)
+
+/* expected value for DIDVID register */
+#define TPM_TIS_I2C_DID_VID 0x000b15d1L
+
+/* Structure to store I2C TPM specific stuff */
+struct tpm_inf_dev {
+	struct i2c_client *client;
+	u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */
+	struct tpm_chip *chip;
+};
+
+static struct tpm_inf_dev tpm_dev;
+static struct i2c_driver tpm_tis_i2c_driver;
+
+/*
+ * iic_tpm_read() - read from TPM register
+ * @addr: register address to read from
+ * @buffer: provided by caller
+ * @len: number of bytes to read
+ *
+ * Read len bytes from TPM register and put them into
+ * buffer (little-endian format, i.e. first byte is put into buffer[0]).
+ *
+ * NOTE: TPM is big-endian for multi-byte values. Multi-byte
+ * values have to be swapped.
+ *
+ * NOTE: We can't unfortunately use the combined read/write functions
+ * provided by the i2c core as the TPM currently does not support the
+ * repeated start condition and due to it's special requirements.
+ * The i2c_smbus* functions do not work for this chip.
+ *
+ * Return -EIO on error, 0 on success.
+ */
+static int iic_tpm_read(u8 addr, u8 *buffer, size_t len)
+{
+
+	struct i2c_msg msg1 = { tpm_dev.client->addr, 0, 1, &addr };
+	struct i2c_msg msg2 = { tpm_dev.client->addr, I2C_M_RD, len, buffer };
+
+	int rc;
+	int count;
+
+	/* Lock the adapter for the duration of the whole sequence. */
+	if (!tpm_dev.client->adapter->algo->master_xfer)
+		return -EOPNOTSUPP;
+	i2c_lock_adapter(tpm_dev.client->adapter);
+
+	for (count = 0; count < MAX_COUNT; count++) {
+		rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
+		if (rc > 0)
+			break;	/* break here to skip sleep */
+
+		usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
+	}
+
+	if (rc <= 0)
+		goto out;
+
+	/* After the TPM has successfully received the register address it needs
+	 * some time, thus we're sleeping here again, before retrieving the data
+	 */
+	for (count = 0; count < MAX_COUNT; count++) {
+		usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
+		rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1);
+		if (rc > 0)
+			break;
+
+	}
+
+out:
+	i2c_unlock_adapter(tpm_dev.client->adapter);
+	if (rc <= 0)
+		return -EIO;
+
+	return 0;
+}
+
+static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len,
+				 unsigned int sleep_low,
+				 unsigned int sleep_hi, u8 max_count)
+{
+	int rc = -EIO;
+	int count;
+
+	struct i2c_msg msg1 = { tpm_dev.client->addr, 0, len + 1, tpm_dev.buf };
+
+	if (len > TPM_BUFSIZE)
+		return -EINVAL;
+
+	if (!tpm_dev.client->adapter->algo->master_xfer)
+		return -EOPNOTSUPP;
+	i2c_lock_adapter(tpm_dev.client->adapter);
+
+	/* prepend the 'register address' to the buffer */
+	tpm_dev.buf[0] = addr;
+	memcpy(&(tpm_dev.buf[1]), buffer, len);
+
+	/*
+	 * NOTE: We have to use these special mechanisms here and unfortunately
+	 * cannot rely on the standard behavior of i2c_transfer.
+	 */
+	for (count = 0; count < max_count; count++) {
+		rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
+		if (rc > 0)
+			break;
+
+		usleep_range(sleep_low, sleep_hi);
+	}
+
+	i2c_unlock_adapter(tpm_dev.client->adapter);
+	if (rc <= 0)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * iic_tpm_write() - write to TPM register
+ * @addr: register address to write to
+ * @buffer: containing data to be written
+ * @len: number of bytes to write
+ *
+ * Write len bytes from provided buffer to TPM register (little
+ * endian format, i.e. buffer[0] is written as first byte).
+ *
+ * NOTE: TPM is big-endian for multi-byte values. Multi-byte
+ * values have to be swapped.
+ *
+ * NOTE: use this function instead of the iic_tpm_write_generic function.
+ *
+ * Return -EIO on error, 0 on success
+ */
+static int iic_tpm_write(u8 addr, u8 *buffer, size_t len)
+{
+	return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LOW,
+				     SLEEP_DURATION_HI, MAX_COUNT);
+}
+
+/*
+ * This function is needed especially for the cleanup situation after
+ * sending TPM_READY
+ * */
+static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len)
+{
+	return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG_LOW,
+				     SLEEP_DURATION_LONG_HI, MAX_COUNT_LONG);
+}
+
+enum tis_access {
+	TPM_ACCESS_VALID = 0x80,
+	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+	TPM_ACCESS_REQUEST_PENDING = 0x04,
+	TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+	TPM_STS_VALID = 0x80,
+	TPM_STS_COMMAND_READY = 0x40,
+	TPM_STS_GO = 0x20,
+	TPM_STS_DATA_AVAIL = 0x10,
+	TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum tis_defaults {
+	TIS_SHORT_TIMEOUT = 750,	/* ms */
+	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
+};
+
+#define	TPM_ACCESS(l)			(0x0000 | ((l) << 4))
+#define	TPM_STS(l)			(0x0001 | ((l) << 4))
+#define	TPM_DATA_FIFO(l)		(0x0005 | ((l) << 4))
+#define	TPM_DID_VID(l)			(0x0006 | ((l) << 4))
+
+static int check_locality(struct tpm_chip *chip, int loc)
+{
+	u8 buf;
+	int rc;
+
+	rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1);
+	if (rc < 0)
+		return rc;
+
+	if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
+		chip->vendor.locality = loc;
+		return loc;
+	}
+
+	return -EIO;
+}
+
+/* implementation similar to tpm_tis */
+static void release_locality(struct tpm_chip *chip, int loc, int force)
+{
+	u8 buf;
+	if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0)
+		return;
+
+	if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
+	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) {
+		buf = TPM_ACCESS_ACTIVE_LOCALITY;
+		iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
+	}
+}
+
+static int request_locality(struct tpm_chip *chip, int loc)
+{
+	unsigned long stop;
+	u8 buf = TPM_ACCESS_REQUEST_USE;
+
+	if (check_locality(chip, loc) >= 0)
+		return loc;
+
+	iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
+
+	/* wait for burstcount */
+	stop = jiffies + chip->vendor.timeout_a;
+	do {
+		if (check_locality(chip, loc) >= 0)
+			return loc;
+		usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
+	} while (time_before(jiffies, stop));
+
+	return -ETIME;
+}
+
+static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
+{
+	/* NOTE: since I2C read may fail, return 0 in this case --> time-out */
+	u8 buf;
+	if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0)
+		return 0;
+	else
+		return buf;
+}
+
+static void tpm_tis_i2c_ready(struct tpm_chip *chip)
+{
+	/* this causes the current command to be aborted */
+	u8 buf = TPM_STS_COMMAND_READY;
+	iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1);
+}
+
+static ssize_t get_burstcount(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	ssize_t burstcnt;
+	u8 buf[3];
+
+	/* wait for burstcount */
+	/* which timeout value, spec has 2 answers (c & d) */
+	stop = jiffies + chip->vendor.timeout_d;
+	do {
+		/* Note: STS is little endian */
+		if (iic_tpm_read(TPM_STS(chip->vendor.locality)+1, buf, 3) < 0)
+			burstcnt = 0;
+		else
+			burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
+
+		if (burstcnt)
+			return burstcnt;
+
+		usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
+	} while (time_before(jiffies, stop));
+	return -EBUSY;
+}
+
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+			 int *status)
+{
+	unsigned long stop;
+
+	/* check current status */
+	*status = tpm_tis_i2c_status(chip);
+	if ((*status & mask) == mask)
+		return 0;
+
+	stop = jiffies + timeout;
+	do {
+		/* since we just checked the status, give the TPM some time */
+		usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
+		*status = tpm_tis_i2c_status(chip);
+		if ((*status & mask) == mask)
+			return 0;
+
+	} while (time_before(jiffies, stop));
+
+	return -ETIME;
+}
+
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	size_t size = 0;
+	ssize_t burstcnt;
+	u8 retries = 0;
+	int rc;
+
+	while (size < count) {
+		burstcnt = get_burstcount(chip);
+
+		/* burstcnt < 0 = TPM is busy */
+		if (burstcnt < 0)
+			return burstcnt;
+
+		/* limit received data to max. left */
+		if (burstcnt > (count - size))
+			burstcnt = count - size;
+
+		rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality),
+				  &(buf[size]), burstcnt);
+		if (rc == 0)
+			size += burstcnt;
+		else if (rc < 0)
+			retries++;
+
+		/* avoid endless loop in case of broken HW */
+		if (retries > MAX_COUNT_LONG)
+			return -EIO;
+
+	}
+	return size;
+}
+
+static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0;
+	int expected, status;
+
+	if (count < TPM_HEADER_SIZE) {
+		size = -EIO;
+		goto out;
+	}
+
+	/* read first 10 bytes, including tag, paramsize, and result */
+	size = recv_data(chip, buf, TPM_HEADER_SIZE);
+	if (size < TPM_HEADER_SIZE) {
+		dev_err(chip->dev, "Unable to read header\n");
+		goto out;
+	}
+
+	expected = be32_to_cpu(*(__be32 *)(buf + 2));
+	if ((size_t) expected > count) {
+		size = -EIO;
+		goto out;
+	}
+
+	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
+			  expected - TPM_HEADER_SIZE);
+	if (size < expected) {
+		dev_err(chip->dev, "Unable to read remainder of result\n");
+		size = -ETIME;
+		goto out;
+	}
+
+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
+	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
+		dev_err(chip->dev, "Error left over data\n");
+		size = -EIO;
+		goto out;
+	}
+
+out:
+	tpm_tis_i2c_ready(chip);
+	/* The TPM needs some time to clean up here,
+	 * so we sleep rather than keeping the bus busy
+	 */
+	usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
+	release_locality(chip, chip->vendor.locality, 0);
+	return size;
+}
+
+static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	int rc, status;
+	ssize_t burstcnt;
+	size_t count = 0;
+	u8 retries = 0;
+	u8 sts = TPM_STS_GO;
+
+	if (len > TPM_BUFSIZE)
+		return -E2BIG;	/* command is too long for our tpm, sorry */
+
+	if (request_locality(chip, 0) < 0)
+		return -EBUSY;
+
+	status = tpm_tis_i2c_status(chip);
+	if ((status & TPM_STS_COMMAND_READY) == 0) {
+		tpm_tis_i2c_ready(chip);
+		if (wait_for_stat
+		    (chip, TPM_STS_COMMAND_READY,
+		     chip->vendor.timeout_b, &status) < 0) {
+			rc = -ETIME;
+			goto out_err;
+		}
+	}
+
+	while (count < len - 1) {
+		burstcnt = get_burstcount(chip);
+
+		/* burstcnt < 0 = TPM is busy */
+		if (burstcnt < 0)
+			return burstcnt;
+
+		if (burstcnt > (len - 1 - count))
+			burstcnt = len - 1 - count;
+
+		rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality),
+				   &(buf[count]), burstcnt);
+		if (rc == 0)
+			count += burstcnt;
+		else if (rc < 0)
+			retries++;
+
+		/* avoid endless loop in case of broken HW */
+		if (retries > MAX_COUNT_LONG) {
+			rc = -EIO;
+			goto out_err;
+		}
+
+		wait_for_stat(chip, TPM_STS_VALID,
+			      chip->vendor.timeout_c, &status);
+
+		if ((status & TPM_STS_DATA_EXPECT) == 0) {
+			rc = -EIO;
+			goto out_err;
+		}
+
+	}
+
+	/* write last byte */
+	iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1);
+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
+		rc = -EIO;
+		goto out_err;
+	}
+
+	/* go and do it */
+	iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1);
+
+	return len;
+out_err:
+	tpm_tis_i2c_ready(chip);
+	/* The TPM needs some time to clean up here,
+	 * so we sleep rather than keeping the bus busy
+	 */
+	usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
+	release_locality(chip, chip->vendor.locality, 0);
+	return rc;
+}
+
+static const struct file_operations tis_ops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpm_open,
+	.read = tpm_read,
+	.write = tpm_write,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
+static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
+
+static struct attribute *tis_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr,
+	&dev_attr_durations.attr,
+	&dev_attr_timeouts.attr,
+	NULL,
+};
+
+static struct attribute_group tis_attr_grp = {
+	.attrs = tis_attrs
+};
+
+static struct tpm_vendor_specific tpm_tis_i2c = {
+	.status = tpm_tis_i2c_status,
+	.recv = tpm_tis_i2c_recv,
+	.send = tpm_tis_i2c_send,
+	.cancel = tpm_tis_i2c_ready,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = TPM_STS_COMMAND_READY,
+	.attr_group = &tis_attr_grp,
+	.miscdev.fops = &tis_ops,
+};
+
+static int __devinit tpm_tis_i2c_init(struct device *dev)
+{
+	u32 vendor;
+	int rc = 0;
+	struct tpm_chip *chip;
+
+	chip = tpm_register_hardware(dev, &tpm_tis_i2c);
+	if (!chip) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* Disable interrupts */
+	chip->vendor.irq = 0;
+
+	/* Default timeouts */
+	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+	if (request_locality(chip, 0) != 0) {
+		rc = -ENODEV;
+		goto out_vendor;
+	}
+
+	/* read four bytes from DID_VID register */
+	if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) {
+		rc = -EIO;
+		goto out_release;
+	}
+
+	/* create DID_VID register value, after swapping to little-endian */
+	vendor = be32_to_cpu((__be32) vendor);
+
+	if (vendor != TPM_TIS_I2C_DID_VID) {
+		rc = -ENODEV;
+		goto out_release;
+	}
+
+	dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16);
+
+	INIT_LIST_HEAD(&chip->vendor.list);
+	tpm_dev.chip = chip;
+
+	tpm_get_timeouts(chip);
+	tpm_do_selftest(chip);
+
+	return 0;
+
+out_release:
+	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;
+	dev_set_drvdata(chip->dev, chip);
+out_err:
+	return rc;
+}
+
+static const struct i2c_device_id tpm_tis_i2c_table[] = {
+	{"tpm_i2c_infineon", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
+static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
+
+static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	int rc;
+	if (tpm_dev.client != NULL)
+		return -EBUSY;	/* We only support one client */
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev,
+			"no algorithms associated to the i2c bus\n");
+		return -ENODEV;
+	}
+
+	client->driver = &tpm_tis_i2c_driver;
+	tpm_dev.client = client;
+	rc = tpm_tis_i2c_init(&client->dev);
+	if (rc != 0) {
+		client->driver = NULL;
+		tpm_dev.client = NULL;
+		rc = -ENODEV;
+	}
+	return rc;
+}
+
+static int __devexit tpm_tis_i2c_remove(struct i2c_client *client)
+{
+	struct tpm_chip *chip = tpm_dev.chip;
+	release_locality(chip, chip->vendor.locality, 1);
+
+	/* 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;
+	dev_set_drvdata(chip->dev, chip);
+
+	return 0;
+}
+
+static struct i2c_driver tpm_tis_i2c_driver = {
+
+	.id_table = tpm_tis_i2c_table,
+	.probe = tpm_tis_i2c_probe,
+	.remove = tpm_tis_i2c_remove,
+	.driver = {
+		   .name = "tpm_i2c_infineon",
+		   .owner = THIS_MODULE,
+		   .pm = &tpm_tis_i2c_ops,
+		   },
+};
+
+module_i2c_driver(tpm_tis_i2c_driver);
+MODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>");
+MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver");
+MODULE_VERSION("2.1.5");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
new file mode 100644
index 0000000..efc4ab3
--- /dev/null
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -0,0 +1,749 @@
+/*
+ * Copyright (C) 2012 IBM Corporation
+ *
+ * Author: Ashley Lai <adlai@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * 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/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/slab.h>
+#include <asm/vio.h>
+#include <asm/irq.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <asm/prom.h>
+
+#include "tpm.h"
+#include "tpm_ibmvtpm.h"
+
+static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm";
+
+static struct vio_device_id tpm_ibmvtpm_device_table[] __devinitdata = {
+	{ "IBM,vtpm", "IBM,vtpm"},
+	{ "", "" }
+};
+MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table);
+
+DECLARE_WAIT_QUEUE_HEAD(wq);
+
+/**
+ * ibmvtpm_send_crq - Send a CRQ request
+ * @vdev:	vio device struct
+ * @w1:		first word
+ * @w2:		second word
+ *
+ * Return value:
+ *	0 -Sucess
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2)
+{
+	return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2);
+}
+
+/**
+ * ibmvtpm_get_data - Retrieve ibm vtpm data
+ * @dev:	device struct
+ *
+ * Return value:
+ *	vtpm device struct
+ */
+static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip)
+		return (struct ibmvtpm_dev *)chip->vendor.data;
+	return NULL;
+}
+
+/**
+ * tpm_ibmvtpm_recv - Receive data after send
+ * @chip:	tpm chip struct
+ * @buf:	buffer to read
+ * count:	size of buffer
+ *
+ * Return value:
+ *	Number of bytes read
+ */
+static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	struct ibmvtpm_dev *ibmvtpm;
+	u16 len;
+
+	ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
+
+	if (!ibmvtpm->rtce_buf) {
+		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
+		return 0;
+	}
+
+	wait_event_interruptible(wq, ibmvtpm->crq_res.len != 0);
+
+	if (count < ibmvtpm->crq_res.len) {
+		dev_err(ibmvtpm->dev,
+			"Invalid size in recv: count=%ld, crq_size=%d\n",
+			count, ibmvtpm->crq_res.len);
+		return -EIO;
+	}
+
+	spin_lock(&ibmvtpm->rtce_lock);
+	memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, ibmvtpm->crq_res.len);
+	memset(ibmvtpm->rtce_buf, 0, ibmvtpm->crq_res.len);
+	ibmvtpm->crq_res.valid = 0;
+	ibmvtpm->crq_res.msg = 0;
+	len = ibmvtpm->crq_res.len;
+	ibmvtpm->crq_res.len = 0;
+	spin_unlock(&ibmvtpm->rtce_lock);
+	return len;
+}
+
+/**
+ * tpm_ibmvtpm_send - Send tpm request
+ * @chip:	tpm chip struct
+ * @buf:	buffer contains data to send
+ * count:	size of buffer
+ *
+ * Return value:
+ *	Number of bytes sent
+ */
+static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	struct ibmvtpm_dev *ibmvtpm;
+	struct ibmvtpm_crq crq;
+	u64 *word = (u64 *) &crq;
+	int rc;
+
+	ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
+
+	if (!ibmvtpm->rtce_buf) {
+		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
+		return 0;
+	}
+
+	if (count > ibmvtpm->rtce_size) {
+		dev_err(ibmvtpm->dev,
+			"Invalid size in send: count=%ld, rtce_size=%d\n",
+			count, ibmvtpm->rtce_size);
+		return -EIO;
+	}
+
+	spin_lock(&ibmvtpm->rtce_lock);
+	memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
+	crq.valid = (u8)IBMVTPM_VALID_CMD;
+	crq.msg = (u8)VTPM_TPM_COMMAND;
+	crq.len = (u16)count;
+	crq.data = ibmvtpm->rtce_dma_handle;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]);
+	if (rc != H_SUCCESS) {
+		dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
+		rc = 0;
+	} else
+		rc = count;
+
+	spin_unlock(&ibmvtpm->rtce_lock);
+	return rc;
+}
+
+static void tpm_ibmvtpm_cancel(struct tpm_chip *chip)
+{
+	return;
+}
+
+static u8 tpm_ibmvtpm_status(struct tpm_chip *chip)
+{
+	return 0;
+}
+
+/**
+ * ibmvtpm_crq_get_rtce_size - Send a CRQ request to get rtce size
+ * @ibmvtpm:	vtpm device struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
+{
+	struct ibmvtpm_crq crq;
+	u64 *buf = (u64 *) &crq;
+	int rc;
+
+	crq.valid = (u8)IBMVTPM_VALID_CMD;
+	crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
+ * ibmvtpm_crq_get_version - Send a CRQ request to get vtpm version
+ *			   - Note that this is vtpm version and not tpm version
+ * @ibmvtpm:	vtpm device struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
+{
+	struct ibmvtpm_crq crq;
+	u64 *buf = (u64 *) &crq;
+	int rc;
+
+	crq.valid = (u8)IBMVTPM_VALID_CMD;
+	crq.msg = (u8)VTPM_GET_VERSION;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"ibmvtpm_crq_get_version failed rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
+ * ibmvtpm_crq_send_init_complete - Send a CRQ initialize complete message
+ * @ibmvtpm:	vtpm device struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
+{
+	int rc;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_COMP_CMD, 0);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"ibmvtpm_crq_send_init_complete failed rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
+ * ibmvtpm_crq_send_init - Send a CRQ initialize message
+ * @ibmvtpm:	vtpm device struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
+{
+	int rc;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_CMD, 0);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"ibmvtpm_crq_send_init failed rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
+ * tpm_ibmvtpm_remove - ibm vtpm remove entry point
+ * @vdev:	vio device struct
+ *
+ * Return value:
+ *	0
+ */
+static int __devexit tpm_ibmvtpm_remove(struct vio_dev *vdev)
+{
+	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
+	int rc = 0;
+
+	free_irq(vdev->irq, ibmvtpm);
+	tasklet_kill(&ibmvtpm->tasklet);
+
+	do {
+		if (rc)
+			msleep(100);
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+	dma_unmap_single(ibmvtpm->dev, ibmvtpm->crq_dma_handle,
+			 CRQ_RES_BUF_SIZE, DMA_BIDIRECTIONAL);
+	free_page((unsigned long)ibmvtpm->crq_queue.crq_addr);
+
+	if (ibmvtpm->rtce_buf) {
+		dma_unmap_single(ibmvtpm->dev, ibmvtpm->rtce_dma_handle,
+				 ibmvtpm->rtce_size, DMA_BIDIRECTIONAL);
+		kfree(ibmvtpm->rtce_buf);
+	}
+
+	tpm_remove_hardware(ibmvtpm->dev);
+
+	kfree(ibmvtpm);
+
+	return 0;
+}
+
+/**
+ * tpm_ibmvtpm_get_desired_dma - Get DMA size needed by this driver
+ * @vdev:	vio device struct
+ *
+ * Return value:
+ *	Number of bytes the driver needs to DMA map
+ */
+static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
+{
+	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
+	return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size;
+}
+
+/**
+ * tpm_ibmvtpm_suspend - Suspend
+ * @dev:	device struct
+ *
+ * Return value:
+ *	0
+ */
+static int tpm_ibmvtpm_suspend(struct device *dev)
+{
+	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
+	struct ibmvtpm_crq crq;
+	u64 *buf = (u64 *) &crq;
+	int rc = 0;
+
+	crq.valid = (u8)IBMVTPM_VALID_CMD;
+	crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"tpm_ibmvtpm_suspend failed rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
+ * ibmvtpm_reset_crq - Reset CRQ
+ * @ibmvtpm:	ibm vtpm struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
+{
+	int rc = 0;
+
+	do {
+		if (rc)
+			msleep(100);
+		rc = plpar_hcall_norets(H_FREE_CRQ,
+					ibmvtpm->vdev->unit_address);
+	} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+	memset(ibmvtpm->crq_queue.crq_addr, 0, CRQ_RES_BUF_SIZE);
+	ibmvtpm->crq_queue.index = 0;
+
+	return plpar_hcall_norets(H_REG_CRQ, ibmvtpm->vdev->unit_address,
+				  ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
+}
+
+/**
+ * tpm_ibmvtpm_resume - Resume from suspend
+ * @dev:	device struct
+ *
+ * Return value:
+ *	0
+ */
+static int tpm_ibmvtpm_resume(struct device *dev)
+{
+	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
+	unsigned long flags;
+	int rc = 0;
+
+	do {
+		if (rc)
+			msleep(100);
+		rc = plpar_hcall_norets(H_ENABLE_CRQ,
+					ibmvtpm->vdev->unit_address);
+	} while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+	if (rc) {
+		dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
+		return rc;
+	}
+
+	spin_lock_irqsave(&ibmvtpm->lock, flags);
+	vio_disable_interrupts(ibmvtpm->vdev);
+	tasklet_schedule(&ibmvtpm->tasklet);
+	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+
+	rc = ibmvtpm_crq_send_init(ibmvtpm);
+	if (rc)
+		dev_err(dev, "Error send_init rc=%d\n", rc);
+
+	return rc;
+}
+
+static const struct file_operations ibmvtpm_ops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpm_open,
+	.read = tpm_read,
+	.write = tpm_write,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
+		   NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
+static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
+
+static struct attribute *ibmvtpm_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr,
+	&dev_attr_durations.attr,
+	&dev_attr_timeouts.attr, NULL,
+};
+
+static struct attribute_group ibmvtpm_attr_grp = { .attrs = ibmvtpm_attrs };
+
+static const struct tpm_vendor_specific tpm_ibmvtpm = {
+	.recv = tpm_ibmvtpm_recv,
+	.send = tpm_ibmvtpm_send,
+	.cancel = tpm_ibmvtpm_cancel,
+	.status = tpm_ibmvtpm_status,
+	.req_complete_mask = 0,
+	.req_complete_val = 0,
+	.req_canceled = 0,
+	.attr_group = &ibmvtpm_attr_grp,
+	.miscdev = { .fops = &ibmvtpm_ops, },
+};
+
+static const struct dev_pm_ops tpm_ibmvtpm_pm_ops = {
+	.suspend = tpm_ibmvtpm_suspend,
+	.resume = tpm_ibmvtpm_resume,
+};
+
+/**
+ * ibmvtpm_crq_get_next - Get next responded crq
+ * @ibmvtpm	vtpm device struct
+ *
+ * Return value:
+ *	vtpm crq pointer
+ */
+static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm)
+{
+	struct ibmvtpm_crq_queue *crq_q = &ibmvtpm->crq_queue;
+	struct ibmvtpm_crq *crq = &crq_q->crq_addr[crq_q->index];
+
+	if (crq->valid & VTPM_MSG_RES) {
+		if (++crq_q->index == crq_q->num_entry)
+			crq_q->index = 0;
+		rmb();
+	} else
+		crq = NULL;
+	return crq;
+}
+
+/**
+ * ibmvtpm_crq_process - Process responded crq
+ * @crq		crq to be processed
+ * @ibmvtpm	vtpm device struct
+ *
+ * Return value:
+ *	Nothing
+ */
+static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
+				struct ibmvtpm_dev *ibmvtpm)
+{
+	int rc = 0;
+
+	switch (crq->valid) {
+	case VALID_INIT_CRQ:
+		switch (crq->msg) {
+		case INIT_CRQ_RES:
+			dev_info(ibmvtpm->dev, "CRQ initialized\n");
+			rc = ibmvtpm_crq_send_init_complete(ibmvtpm);
+			if (rc)
+				dev_err(ibmvtpm->dev, "Unable to send CRQ init complete rc=%d\n", rc);
+			return;
+		case INIT_CRQ_COMP_RES:
+			dev_info(ibmvtpm->dev,
+				 "CRQ initialization completed\n");
+			return;
+		default:
+			dev_err(ibmvtpm->dev, "Unknown crq message type: %d\n", crq->msg);
+			return;
+		}
+		return;
+	case IBMVTPM_VALID_CMD:
+		switch (crq->msg) {
+		case VTPM_GET_RTCE_BUFFER_SIZE_RES:
+			if (crq->len <= 0) {
+				dev_err(ibmvtpm->dev, "Invalid rtce size\n");
+				return;
+			}
+			ibmvtpm->rtce_size = crq->len;
+			ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size,
+						    GFP_KERNEL);
+			if (!ibmvtpm->rtce_buf) {
+				dev_err(ibmvtpm->dev, "Failed to allocate memory for rtce buffer\n");
+				return;
+			}
+
+			ibmvtpm->rtce_dma_handle = dma_map_single(ibmvtpm->dev,
+				ibmvtpm->rtce_buf, ibmvtpm->rtce_size,
+				DMA_BIDIRECTIONAL);
+
+			if (dma_mapping_error(ibmvtpm->dev,
+					      ibmvtpm->rtce_dma_handle)) {
+				kfree(ibmvtpm->rtce_buf);
+				ibmvtpm->rtce_buf = NULL;
+				dev_err(ibmvtpm->dev, "Failed to dma map rtce buffer\n");
+			}
+
+			return;
+		case VTPM_GET_VERSION_RES:
+			ibmvtpm->vtpm_version = crq->data;
+			return;
+		case VTPM_TPM_COMMAND_RES:
+			ibmvtpm->crq_res.valid = crq->valid;
+			ibmvtpm->crq_res.msg = crq->msg;
+			ibmvtpm->crq_res.len = crq->len;
+			ibmvtpm->crq_res.data = crq->data;
+			wake_up_interruptible(&wq);
+			return;
+		default:
+			return;
+		}
+	}
+	return;
+}
+
+/**
+ * ibmvtpm_interrupt -	Interrupt handler
+ * @irq:		irq number to handle
+ * @vtpm_instance:	vtpm that received interrupt
+ *
+ * Returns:
+ *	IRQ_HANDLED
+ **/
+static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance)
+{
+	struct ibmvtpm_dev *ibmvtpm = (struct ibmvtpm_dev *) vtpm_instance;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ibmvtpm->lock, flags);
+	vio_disable_interrupts(ibmvtpm->vdev);
+	tasklet_schedule(&ibmvtpm->tasklet);
+	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * ibmvtpm_tasklet - Interrupt handler tasklet
+ * @data:	ibm vtpm device struct
+ *
+ * Returns:
+ *	Nothing
+ **/
+static void ibmvtpm_tasklet(void *data)
+{
+	struct ibmvtpm_dev *ibmvtpm = data;
+	struct ibmvtpm_crq *crq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ibmvtpm->lock, flags);
+	while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) {
+		ibmvtpm_crq_process(crq, ibmvtpm);
+		crq->valid = 0;
+		wmb();
+	}
+
+	vio_enable_interrupts(ibmvtpm->vdev);
+	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+}
+
+/**
+ * tpm_ibmvtpm_probe - ibm vtpm initialize entry point
+ * @vio_dev:	vio device struct
+ * @id:		vio device id struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
+				   const struct vio_device_id *id)
+{
+	struct ibmvtpm_dev *ibmvtpm;
+	struct device *dev = &vio_dev->dev;
+	struct ibmvtpm_crq_queue *crq_q;
+	struct tpm_chip *chip;
+	int rc = -ENOMEM, rc1;
+
+	chip = tpm_register_hardware(dev, &tpm_ibmvtpm);
+	if (!chip) {
+		dev_err(dev, "tpm_register_hardware failed\n");
+		return -ENODEV;
+	}
+
+	ibmvtpm = kzalloc(sizeof(struct ibmvtpm_dev), GFP_KERNEL);
+	if (!ibmvtpm) {
+		dev_err(dev, "kzalloc for ibmvtpm failed\n");
+		goto cleanup;
+	}
+
+	crq_q = &ibmvtpm->crq_queue;
+	crq_q->crq_addr = (struct ibmvtpm_crq *)get_zeroed_page(GFP_KERNEL);
+	if (!crq_q->crq_addr) {
+		dev_err(dev, "Unable to allocate memory for crq_addr\n");
+		goto cleanup;
+	}
+
+	crq_q->num_entry = CRQ_RES_BUF_SIZE / sizeof(*crq_q->crq_addr);
+	ibmvtpm->crq_dma_handle = dma_map_single(dev, crq_q->crq_addr,
+						 CRQ_RES_BUF_SIZE,
+						 DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(dev, ibmvtpm->crq_dma_handle)) {
+		dev_err(dev, "dma mapping failed\n");
+		goto cleanup;
+	}
+
+	rc = plpar_hcall_norets(H_REG_CRQ, vio_dev->unit_address,
+				ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
+	if (rc == H_RESOURCE)
+		rc = ibmvtpm_reset_crq(ibmvtpm);
+
+	if (rc) {
+		dev_err(dev, "Unable to register CRQ rc=%d\n", rc);
+		goto reg_crq_cleanup;
+	}
+
+	tasklet_init(&ibmvtpm->tasklet, (void *)ibmvtpm_tasklet,
+		     (unsigned long)ibmvtpm);
+
+	rc = request_irq(vio_dev->irq, ibmvtpm_interrupt, 0,
+			 tpm_ibmvtpm_driver_name, ibmvtpm);
+	if (rc) {
+		dev_err(dev, "Error %d register irq 0x%x\n", rc, vio_dev->irq);
+		goto init_irq_cleanup;
+	}
+
+	rc = vio_enable_interrupts(vio_dev);
+	if (rc) {
+		dev_err(dev, "Error %d enabling interrupts\n", rc);
+		goto init_irq_cleanup;
+	}
+
+	crq_q->index = 0;
+
+	ibmvtpm->dev = dev;
+	ibmvtpm->vdev = vio_dev;
+	chip->vendor.data = (void *)ibmvtpm;
+
+	spin_lock_init(&ibmvtpm->lock);
+	spin_lock_init(&ibmvtpm->rtce_lock);
+
+	rc = ibmvtpm_crq_send_init(ibmvtpm);
+	if (rc)
+		goto init_irq_cleanup;
+
+	rc = ibmvtpm_crq_get_version(ibmvtpm);
+	if (rc)
+		goto init_irq_cleanup;
+
+	rc = ibmvtpm_crq_get_rtce_size(ibmvtpm);
+	if (rc)
+		goto init_irq_cleanup;
+
+	return rc;
+init_irq_cleanup:
+	tasklet_kill(&ibmvtpm->tasklet);
+	do {
+		rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address);
+	} while (rc1 == H_BUSY || H_IS_LONG_BUSY(rc1));
+reg_crq_cleanup:
+	dma_unmap_single(dev, ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE,
+			 DMA_BIDIRECTIONAL);
+cleanup:
+	if (ibmvtpm) {
+		if (crq_q->crq_addr)
+			free_page((unsigned long)crq_q->crq_addr);
+		kfree(ibmvtpm);
+	}
+
+	tpm_remove_hardware(dev);
+
+	return rc;
+}
+
+static struct vio_driver ibmvtpm_driver = {
+	.id_table	 = tpm_ibmvtpm_device_table,
+	.probe		 = tpm_ibmvtpm_probe,
+	.remove		 = tpm_ibmvtpm_remove,
+	.get_desired_dma = tpm_ibmvtpm_get_desired_dma,
+	.name		 = tpm_ibmvtpm_driver_name,
+	.pm		 = &tpm_ibmvtpm_pm_ops,
+};
+
+/**
+ * ibmvtpm_module_init - Initialize ibm vtpm module
+ *
+ * Return value:
+ *	0 -Success
+ *	Non-zero - Failure
+ */
+static int __init ibmvtpm_module_init(void)
+{
+	return vio_register_driver(&ibmvtpm_driver);
+}
+
+/**
+ * ibmvtpm_module_exit - Teardown ibm vtpm module
+ *
+ * Return value:
+ *	Nothing
+ */
+static void __exit ibmvtpm_module_exit(void)
+{
+	vio_unregister_driver(&ibmvtpm_driver);
+}
+
+module_init(ibmvtpm_module_init);
+module_exit(ibmvtpm_module_exit);
+
+MODULE_AUTHOR("adlai@us.ibm.com");
+MODULE_DESCRIPTION("IBM vTPM Driver");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h
new file mode 100644
index 0000000..4296eb4
--- /dev/null
+++ b/drivers/char/tpm/tpm_ibmvtpm.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 IBM Corporation
+ *
+ * Author: Ashley Lai <adlai@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * 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.
+ *
+ */
+
+#ifndef __TPM_IBMVTPM_H__
+#define __TPM_IBMVTPM_H__
+
+/* vTPM Message Format 1 */
+struct ibmvtpm_crq {
+	u8 valid;
+	u8 msg;
+	u16 len;
+	u32 data;
+	u64 reserved;
+} __attribute__((packed, aligned(8)));
+
+struct ibmvtpm_crq_queue {
+	struct ibmvtpm_crq *crq_addr;
+	u32 index;
+	u32 num_entry;
+};
+
+struct ibmvtpm_dev {
+	struct device *dev;
+	struct vio_dev *vdev;
+	struct ibmvtpm_crq_queue crq_queue;
+	dma_addr_t crq_dma_handle;
+	spinlock_t lock;
+	struct tasklet_struct tasklet;
+	u32 rtce_size;
+	void __iomem *rtce_buf;
+	dma_addr_t rtce_dma_handle;
+	spinlock_t rtce_lock;
+	struct ibmvtpm_crq crq_res;
+	u32 vtpm_version;
+};
+
+#define CRQ_RES_BUF_SIZE	PAGE_SIZE
+
+/* Initialize CRQ */
+#define INIT_CRQ_CMD		0xC001000000000000LL /* Init cmd */
+#define INIT_CRQ_COMP_CMD	0xC002000000000000LL /* Init complete cmd */
+#define INIT_CRQ_RES		0x01	/* Init respond */
+#define INIT_CRQ_COMP_RES	0x02	/* Init complete respond */
+#define VALID_INIT_CRQ		0xC0	/* Valid command for init crq */
+
+/* vTPM CRQ response is the message type | 0x80 */
+#define VTPM_MSG_RES		0x80
+#define IBMVTPM_VALID_CMD	0x80
+
+/* vTPM CRQ message types */
+#define VTPM_GET_VERSION			0x01
+#define VTPM_GET_VERSION_RES			(0x01 | VTPM_MSG_RES)
+
+#define VTPM_TPM_COMMAND			0x02
+#define VTPM_TPM_COMMAND_RES			(0x02 | VTPM_MSG_RES)
+
+#define VTPM_GET_RTCE_BUFFER_SIZE		0x03
+#define VTPM_GET_RTCE_BUFFER_SIZE_RES		(0x03 | VTPM_MSG_RES)
+
+#define VTPM_PREPARE_TO_SUSPEND			0x04
+#define VTPM_PREPARE_TO_SUSPEND_RES		(0x04 | VTPM_MSG_RES)
+
+#endif
diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c
new file mode 100644
index 0000000..98ba2bd
--- /dev/null
+++ b/drivers/char/tpm/tpm_of.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 IBM Corporation
+ *
+ * Author: Ashley Lai <adlai@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Read the event log created by the firmware on PPC64
+ *
+ * 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; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include "tpm.h"
+#include "tpm_eventlog.h"
+
+int read_log(struct tpm_bios_log *log)
+{
+	struct device_node *np;
+	const u32 *sizep;
+	const __be64 *basep;
+
+	if (log->bios_event_log != NULL) {
+		pr_err("%s: ERROR - Eventlog already initialized\n", __func__);
+		return -EFAULT;
+	}
+
+	np = of_find_node_by_name(NULL, "ibm,vtpm");
+	if (!np) {
+		pr_err("%s: ERROR - IBMVTPM not supported\n", __func__);
+		return -ENODEV;
+	}
+
+	sizep = of_get_property(np, "linux,sml-size", NULL);
+	if (sizep == NULL) {
+		pr_err("%s: ERROR - SML size not found\n", __func__);
+		goto cleanup_eio;
+	}
+	if (*sizep == 0) {
+		pr_err("%s: ERROR - event log area empty\n", __func__);
+		goto cleanup_eio;
+	}
+
+	basep = of_get_property(np, "linux,sml-base", NULL);
+	if (basep == NULL) {
+		pr_err(KERN_ERR "%s: ERROR - SML not found\n", __func__);
+		goto cleanup_eio;
+	}
+
+	of_node_put(np);
+	log->bios_event_log = kmalloc(*sizep, GFP_KERNEL);
+	if (!log->bios_event_log) {
+		pr_err("%s: ERROR - Not enough memory for BIOS measurements\n",
+		       __func__);
+		return -ENOMEM;
+	}
+
+	log->bios_event_log_end = log->bios_event_log + *sizep;
+
+	memcpy(log->bios_event_log, __va(be64_to_cpup(basep)), *sizep);
+
+	return 0;
+
+cleanup_eio:
+	of_node_put(np);
+	return -EIO;
+}
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
new file mode 100644
index 0000000..440fa1c
--- /dev/null
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -0,0 +1,460 @@
+#include <linux/acpi.h>
+#include <acpi/acpi_drivers.h>
+#include "tpm.h"
+
+static const u8 tpm_ppi_uuid[] = {
+	0xA6, 0xFA, 0xDD, 0x3D,
+	0x1B, 0x36,
+	0xB4, 0x4E,
+	0xA4, 0x24,
+	0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53
+};
+static char *tpm_device_name = "TPM";
+
+#define TPM_PPI_REVISION_ID	1
+#define TPM_PPI_FN_VERSION	1
+#define TPM_PPI_FN_SUBREQ	2
+#define TPM_PPI_FN_GETREQ	3
+#define TPM_PPI_FN_GETACT	4
+#define TPM_PPI_FN_GETRSP	5
+#define TPM_PPI_FN_SUBREQ2	7
+#define TPM_PPI_FN_GETOPR	8
+#define PPI_TPM_REQ_MAX		22
+#define PPI_VS_REQ_START	128
+#define PPI_VS_REQ_END		255
+#define PPI_VERSION_LEN		3
+
+static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
+				void **return_value)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+	if (strstr(buffer.pointer, context) != NULL) {
+		*return_value = handle;
+		kfree(buffer.pointer);
+		return AE_CTRL_TERMINATE;
+	}
+	return AE_OK;
+}
+
+static inline void ppi_assign_params(union acpi_object params[4],
+				     u64 function_num)
+{
+	params[0].type = ACPI_TYPE_BUFFER;
+	params[0].buffer.length = sizeof(tpm_ppi_uuid);
+	params[0].buffer.pointer = (char *)tpm_ppi_uuid;
+	params[1].type = ACPI_TYPE_INTEGER;
+	params[1].integer.value = TPM_PPI_REVISION_ID;
+	params[2].type = ACPI_TYPE_INTEGER;
+	params[2].integer.value = function_num;
+	params[3].type = ACPI_TYPE_PACKAGE;
+	params[3].package.count = 0;
+	params[3].package.elements = NULL;
+}
+
+ssize_t tpm_show_ppi_version(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	union acpi_object *obj;
+
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_VERSION);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					 ACPI_TYPE_STRING);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	obj = (union acpi_object *)output.pointer;
+	status = scnprintf(buf, PAGE_SIZE, "%s\n", obj->string.pointer);
+	kfree(output.pointer);
+	return status;
+}
+
+ssize_t tpm_show_ppi_request(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	union acpi_object *ret_obj;
+
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_GETREQ);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_PACKAGE);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	/*
+	 * output.pointer should be of package type, including two integers.
+	 * The first is function return code, 0 means success and 1 means
+	 * error. The second is pending TPM operation requested by the OS, 0
+	 * means none and >0 means operation value.
+	 */
+	ret_obj = ((union acpi_object *)output.pointer)->package.elements;
+	if (ret_obj->type == ACPI_TYPE_INTEGER) {
+		if (ret_obj->integer.value) {
+			status = -EFAULT;
+			goto cleanup;
+		}
+		ret_obj++;
+		if (ret_obj->type == ACPI_TYPE_INTEGER)
+			status = scnprintf(buf, PAGE_SIZE, "%llu\n",
+					   ret_obj->integer.value);
+		else
+			status = -EINVAL;
+	} else {
+		status = -EINVAL;
+	}
+cleanup:
+	kfree(output.pointer);
+	return status;
+}
+
+ssize_t tpm_store_ppi_request(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	char version[PPI_VERSION_LEN + 1];
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	union acpi_object obj;
+	u32 req;
+	u64 ret;
+
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_VERSION);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_STRING);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	strncpy(version,
+		((union acpi_object *)output.pointer)->string.pointer,
+		PPI_VERSION_LEN);
+	kfree(output.pointer);
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;
+	/*
+	 * the function to submit TPM operation request to pre-os environment
+	 * is updated with function index from SUBREQ to SUBREQ2 since PPI
+	 * version 1.1
+	 */
+	if (strcmp(version, "1.1") == -1)
+		params[2].integer.value = TPM_PPI_FN_SUBREQ;
+	else
+		params[2].integer.value = TPM_PPI_FN_SUBREQ2;
+	/*
+	 * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS
+	 * accept buffer/string/integer type, but some BIOS accept buffer/
+	 * 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.
+	 */
+	if (strcmp(version, "1.2") == -1) {
+		params[3].type = ACPI_TYPE_BUFFER;
+		params[3].buffer.length = sizeof(req);
+		sscanf(buf, "%d", &req);
+		params[3].buffer.pointer = (char *)&req;
+	} else {
+		params[3].package.count = 1;
+		obj.type = ACPI_TYPE_INTEGER;
+		sscanf(buf, "%llu", &obj.integer.value);
+		params[3].package.elements = &obj;
+	}
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_INTEGER);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	ret = ((union acpi_object *)output.pointer)->integer.value;
+	if (ret == 0)
+		status = (acpi_status)count;
+	else if (ret == 1)
+		status = -EPERM;
+	else
+		status = -EFAULT;
+	kfree(output.pointer);
+	return status;
+}
+
+ssize_t tpm_show_ppi_transition_action(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	char version[PPI_VERSION_LEN + 1];
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	u32 ret;
+	char *info[] = {
+		"None",
+		"Shutdown",
+		"Reboot",
+		"OS Vendor-specific",
+		"Error",
+	};
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_VERSION);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_STRING);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	strncpy(version,
+		((union acpi_object *)output.pointer)->string.pointer,
+		PPI_VERSION_LEN);
+	/*
+	 * PPI spec defines params[3].type as empty package, but some platforms
+	 * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
+	 * compatibility, define params[3].type as buffer, if PPI version < 1.2
+	 */
+	if (strcmp(version, "1.2") == -1) {
+		params[3].type = ACPI_TYPE_BUFFER;
+		params[3].buffer.length =  0;
+		params[3].buffer.pointer = NULL;
+	}
+	params[2].integer.value = TPM_PPI_FN_GETACT;
+	kfree(output.pointer);
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_INTEGER);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	ret = ((union acpi_object *)output.pointer)->integer.value;
+	if (ret < ARRAY_SIZE(info) - 1)
+		status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, info[ret]);
+	else
+		status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret,
+				   info[ARRAY_SIZE(info)-1]);
+	kfree(output.pointer);
+	return status;
+}
+
+ssize_t tpm_show_ppi_response(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	union acpi_object *ret_obj;
+	u64 req;
+
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_GETRSP);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_PACKAGE);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	/*
+	 * parameter output.pointer should be of package type, including
+	 * 3 integers. The first means function return code, the second means
+	 * most recent TPM operation request, and the last means response to
+	 * the most recent TPM operation request. Only if the first is 0, and
+	 * the second integer is not 0, the response makes sense.
+	 */
+	ret_obj = ((union acpi_object *)output.pointer)->package.elements;
+	if (ret_obj->type != ACPI_TYPE_INTEGER) {
+		status = -EINVAL;
+		goto cleanup;
+	}
+	if (ret_obj->integer.value) {
+		status = -EFAULT;
+		goto cleanup;
+	}
+	ret_obj++;
+	if (ret_obj->type != ACPI_TYPE_INTEGER) {
+		status = -EINVAL;
+		goto cleanup;
+	}
+	if (ret_obj->integer.value) {
+		req = ret_obj->integer.value;
+		ret_obj++;
+		if (ret_obj->type != ACPI_TYPE_INTEGER) {
+			status = -EINVAL;
+			goto cleanup;
+		}
+		if (ret_obj->integer.value == 0)
+			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
+					   "0: Success");
+		else if (ret_obj->integer.value == 0xFFFFFFF0)
+			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
+					   "0xFFFFFFF0: User Abort");
+		else if (ret_obj->integer.value == 0xFFFFFFF1)
+			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
+					   "0xFFFFFFF1: BIOS Failure");
+		else if (ret_obj->integer.value >= 1 &&
+			 ret_obj->integer.value <= 0x00000FFF)
+			status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
+					   req, ret_obj->integer.value,
+					   "Corresponding TPM error");
+		else
+			status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
+					   req, ret_obj->integer.value,
+					   "Error");
+	} else {
+		status = scnprintf(buf, PAGE_SIZE, "%llu: %s\n",
+				   ret_obj->integer.value, "No Recent Request");
+	}
+cleanup:
+	kfree(output.pointer);
+	return status;
+}
+
+static ssize_t show_ppi_operations(char *buf, u32 start, u32 end)
+{
+	char *str = buf;
+	char version[PPI_VERSION_LEN];
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	union acpi_object obj;
+	int i;
+	u32 ret;
+	char *info[] = {
+		"Not implemented",
+		"BIOS only",
+		"Blocked for OS by BIOS",
+		"User required",
+		"User not required",
+	};
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_VERSION);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					 ACPI_TYPE_STRING);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+
+	strncpy(version,
+		((union acpi_object *)output.pointer)->string.pointer,
+		PPI_VERSION_LEN);
+	kfree(output.pointer);
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;
+	if (strcmp(version, "1.2") == -1)
+		return -EPERM;
+
+	params[2].integer.value = TPM_PPI_FN_GETOPR;
+	params[3].package.count = 1;
+	obj.type = ACPI_TYPE_INTEGER;
+	params[3].package.elements = &obj;
+	for (i = start; i <= end; i++) {
+		obj.integer.value = i;
+		status = acpi_evaluate_object_typed(handle, "_DSM",
+			 &input, &output, ACPI_TYPE_INTEGER);
+		if (ACPI_FAILURE(status))
+			return -ENOMEM;
+
+		ret = ((union acpi_object *)output.pointer)->integer.value;
+		if (ret > 0 && ret < ARRAY_SIZE(info))
+			str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n",
+					 i, ret, info[ret]);
+		kfree(output.pointer);
+		output.length = ACPI_ALLOCATE_BUFFER;
+		output.pointer = NULL;
+	}
+	return str - buf;
+}
+
+ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return show_ppi_operations(buf, 0, PPI_TPM_REQ_MAX);
+}
+
+ssize_t tpm_show_ppi_vs_operations(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	return show_ppi_operations(buf, PPI_VS_REQ_START, PPI_VS_REQ_END);
+}
+
+static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
+static DEVICE_ATTR(request, S_IRUGO | S_IWUSR | S_IWGRP,
+		   tpm_show_ppi_request, tpm_store_ppi_request);
+static DEVICE_ATTR(transition_action, S_IRUGO,
+		   tpm_show_ppi_transition_action, NULL);
+static DEVICE_ATTR(response, S_IRUGO, tpm_show_ppi_response, NULL);
+static DEVICE_ATTR(tcg_operations, S_IRUGO, tpm_show_ppi_tcg_operations, NULL);
+static DEVICE_ATTR(vs_operations, S_IRUGO, tpm_show_ppi_vs_operations, NULL);
+
+static struct attribute *ppi_attrs[] = {
+	&dev_attr_version.attr,
+	&dev_attr_request.attr,
+	&dev_attr_transition_action.attr,
+	&dev_attr_response.attr,
+	&dev_attr_tcg_operations.attr,
+	&dev_attr_vs_operations.attr, NULL,
+};
+static struct attribute_group ppi_attr_grp = {
+	.attrs = ppi_attrs
+};
+
+ssize_t sys_add_ppi(struct kobject *parent)
+{
+	struct kobject *ppi;
+	ppi = kobject_create_and_add("ppi", parent);
+	if (sysfs_create_group(ppi, &ppi_attr_grp))
+		return -EFAULT;
+	else
+		return 0;
+}
+EXPORT_SYMBOL_GPL(sys_add_ppi);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index c4be351..6bdf267 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -705,6 +705,7 @@ out_err:
 	return rc;
 }
 
+#if defined(CONFIG_PNP) || defined(CONFIG_PM_SLEEP)
 static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
 {
 	u32 intmask;
@@ -725,7 +726,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
 	iowrite32(intmask,
 		  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
 }
-
+#endif
 
 #ifdef CONFIG_PNP
 static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index fdc718a..fcb627f 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -32,6 +32,7 @@
 extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
 extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
 extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
+extern int tpm_get_random(u32 chip_num, u8 *data, size_t max);
 #else
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
 	return -ENODEV;
@@ -42,5 +43,8 @@ static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
 static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) {
 	return -ENODEV;
 }
+static inline int tpm_get_random(u32 chip_num, u8 *data, size_t max) {
+	return -ENODEV;
+}
 #endif
 #endif
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index b9c1219..809ccf1 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -11,6 +11,7 @@ config IMA
 	select CRYPTO_SHA1
 	select TCG_TPM if HAS_IOMEM && !UML
 	select TCG_TIS if TCG_TPM && X86
+	select TCG_IBMVTPM if TCG_TPM && PPC64
 	help
 	  The Trusted Computing Group(TCG) runtime Integrity
 	  Measurement Architecture(IMA) maintains a list of hash
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 2d5d041..3f163d0 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -369,38 +369,6 @@ static int trusted_tpm_send(const u32 chip_num, unsigned char *cmd,
 }
 
 /*
- * get a random value from TPM
- */
-static int tpm_get_random(struct tpm_buf *tb, unsigned char *buf, uint32_t len)
-{
-	int ret;
-
-	INIT_BUF(tb);
-	store16(tb, TPM_TAG_RQU_COMMAND);
-	store32(tb, TPM_GETRANDOM_SIZE);
-	store32(tb, TPM_ORD_GETRANDOM);
-	store32(tb, len);
-	ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data);
-	if (!ret)
-		memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len);
-	return ret;
-}
-
-static int my_get_random(unsigned char *buf, int len)
-{
-	struct tpm_buf *tb;
-	int ret;
-
-	tb = kmalloc(sizeof *tb, GFP_KERNEL);
-	if (!tb)
-		return -ENOMEM;
-	ret = tpm_get_random(tb, buf, len);
-
-	kfree(tb);
-	return ret;
-}
-
-/*
  * Lock a trusted key, by extending a selected PCR.
  *
  * Prevents a trusted key that is sealed to PCRs from being accessed.
@@ -413,8 +381,8 @@ static int pcrlock(const int pcrnum)
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	ret = my_get_random(hash, SHA1_DIGEST_SIZE);
-	if (ret < 0)
+	ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE);
+	if (ret != SHA1_DIGEST_SIZE)
 		return ret;
 	return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0;
 }
@@ -429,8 +397,8 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
 	unsigned char ononce[TPM_NONCE_SIZE];
 	int ret;
 
-	ret = tpm_get_random(tb, ononce, TPM_NONCE_SIZE);
-	if (ret < 0)
+	ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE);
+	if (ret != TPM_NONCE_SIZE)
 		return ret;
 
 	INIT_BUF(tb);
@@ -524,8 +492,8 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
 	if (ret < 0)
 		goto out;
 
-	ret = tpm_get_random(tb, td->nonceodd, TPM_NONCE_SIZE);
-	if (ret < 0)
+	ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE);
+	if (ret != TPM_NONCE_SIZE)
 		goto out;
 	ordinal = htonl(TPM_ORD_SEAL);
 	datsize = htonl(datalen);
@@ -634,8 +602,8 @@ static int tpm_unseal(struct tpm_buf *tb,
 
 	ordinal = htonl(TPM_ORD_UNSEAL);
 	keyhndl = htonl(SRKHANDLE);
-	ret = tpm_get_random(tb, nonceodd, TPM_NONCE_SIZE);
-	if (ret < 0) {
+	ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE);
+	if (ret != TPM_NONCE_SIZE) {
 		pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
 		return ret;
 	}
@@ -935,6 +903,7 @@ static int trusted_instantiate(struct key *key, const void *data,
 	char *datablob;
 	int ret = 0;
 	int key_cmd;
+	size_t key_len;
 
 	if (datalen <= 0 || datalen > 32767 || !data)
 		return -EINVAL;
@@ -974,8 +943,9 @@ static int trusted_instantiate(struct key *key, const void *data,
 			pr_info("trusted_key: key_unseal failed (%d)\n", ret);
 		break;
 	case Opt_new:
-		ret = my_get_random(payload->key, payload->key_len);
-		if (ret < 0) {
+		key_len = payload->key_len;
+		ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len);
+		if (ret != key_len) {
 			pr_info("trusted_key: key_create failed (%d)\n", ret);
 			goto out;
 		}


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-22 21:52 [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes Kent Yoder
@ 2012-08-22 23:42 ` Jeff Garzik
  2012-08-23 20:32 ` James Morris
  1 sibling, 0 replies; 14+ messages in thread
From: Jeff Garzik @ 2012-08-22 23:42 UTC (permalink / raw)
  To: Kent Yoder, James Morris
  Cc: linux-kernel, linux-security-module, tpmdd-devel, adlai,
	xiaoyan.zhang, jj, peter.huewe

On 08/22/2012 05:52 PM, Kent Yoder wrote:
>    Hi James,
>
> The following changes since commit 51b743fe87d7fb3dba7a2ff4a1fe23bb65dc2245:
>
>    Merge tag 'v3.6-rc2' into next (2012-08-17 20:42:30 +1000)
>
> are available in the git repository at:
>
>    git://github.com/shpedoikal/linux.git v3.6-rc2-tpmdd
>
> New stuff since my last pull request are Jesper's error checking of the
> acpi_os_map_memory call, Ashley's vTPM driver for PPC64, my enabling the
> vTPM driver when IMA is selected on PPC64 and Xiaoyan's addition of
> Physical Presence Interface.
>
> Thanks,
> Kent
>
> Ashley Lai (3):
>        drivers/char/tpm: Add new device driver to support IBM vTPM
>        PPC64: Add support for instantiating SML from Open Firmware
>        drivers/char/tpm: Add securityfs support for event log
>
> Jesper Juhl (1):
>        tpm: Do not dereference NULL pointer if acpi_os_map_memory() fails.
>
> Kent Yoder (6):
>        tpm: modularize event log collection
>        tpm: Move tpm_get_random api into the TPM device driver
>        hw_random: add support for the TPM chip as a hardware RNG source
>        tpm: fix double write race and tpm_release free issue
>        tpm: compile out unused code in the PNP and PM cases
>        ima: enable the IBM vTPM as the default TPM in the PPC64 case
>
> Peter Huewe (1):
>        char/tpm: Add new driver for Infineon I2C TIS TPM
>
> Xiaoyan Zhang (2):
>        Documentation: sysfs for Physical Presence Interface
>        driver: add PPI support in tpm driver

+1 for tpm-rng




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-22 21:52 [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes Kent Yoder
  2012-08-22 23:42 ` Jeff Garzik
@ 2012-08-23 20:32 ` James Morris
  2012-08-24  7:27   ` Peter.Huewe
  2012-08-24  8:32   ` Peter.Huewe
  1 sibling, 2 replies; 14+ messages in thread
From: James Morris @ 2012-08-23 20:32 UTC (permalink / raw)
  To: Kent Yoder
  Cc: linux-kernel, linux-security-module, tpmdd-devel, adlai,
	xiaoyan.zhang, jj, peter.huewe

On Wed, 22 Aug 2012, Kent Yoder wrote:

>   Hi James,
> 
> The following changes since commit 51b743fe87d7fb3dba7a2ff4a1fe23bb65dc2245:
> 
>   Merge tag 'v3.6-rc2' into next (2012-08-17 20:42:30 +1000)
> 
> are available in the git repository at:
> 
>   git://github.com/shpedoikal/linux.git v3.6-rc2-tpmdd

I'm getting this error when building i2c as a module
WARNING: "__i2c_transfer" [drivers/char/tpm/tpm_i2c_infineon.ko] undefined!



> 
> New stuff since my last pull request are Jesper's error checking of the
> acpi_os_map_memory call, Ashley's vTPM driver for PPC64, my enabling the
> vTPM driver when IMA is selected on PPC64 and Xiaoyan's addition of
> Physical Presence Interface.
> 
> Thanks,
> Kent
> 
> Ashley Lai (3):
>       drivers/char/tpm: Add new device driver to support IBM vTPM
>       PPC64: Add support for instantiating SML from Open Firmware
>       drivers/char/tpm: Add securityfs support for event log
> 
> Jesper Juhl (1):
>       tpm: Do not dereference NULL pointer if acpi_os_map_memory() fails.
> 
> Kent Yoder (6):
>       tpm: modularize event log collection
>       tpm: Move tpm_get_random api into the TPM device driver
>       hw_random: add support for the TPM chip as a hardware RNG source
>       tpm: fix double write race and tpm_release free issue
>       tpm: compile out unused code in the PNP and PM cases
>       ima: enable the IBM vTPM as the default TPM in the PPC64 case
> 
> Peter Huewe (1):
>       char/tpm: Add new driver for Infineon I2C TIS TPM
> 
> Xiaoyan Zhang (2):
>       Documentation: sysfs for Physical Presence Interface
>       driver: add PPI support in tpm driver
> 
>  Documentation/ABI/testing/sysfs-driver-ppi      |   70 +++
>  arch/powerpc/kernel/prom_init.c                 |   62 ++
>  drivers/char/hw_random/Kconfig                  |   13 +
>  drivers/char/hw_random/Makefile                 |    1 +
>  drivers/char/hw_random/tpm-rng.c                |   50 ++
>  drivers/char/tpm/Kconfig                        |   19 +
>  drivers/char/tpm/Makefile                       |    8 +
>  drivers/char/tpm/tpm.c                          |   70 ++-
>  drivers/char/tpm/tpm.h                          |   35 +-
>  drivers/char/tpm/tpm_acpi.c                     |  109 ++++
>  drivers/char/tpm/{tpm_bios.c => tpm_eventlog.c} |  147 +-----
>  drivers/char/tpm/tpm_eventlog.h                 |   86 +++
>  drivers/char/tpm/tpm_i2c_infineon.c             |  695 +++++++++++++++++++++
>  drivers/char/tpm/tpm_ibmvtpm.c                  |  749 +++++++++++++++++++++++
>  drivers/char/tpm/tpm_ibmvtpm.h                  |   77 +++
>  drivers/char/tpm/tpm_of.c                       |   73 +++
>  drivers/char/tpm/tpm_ppi.c                      |  460 ++++++++++++++
>  drivers/char/tpm/tpm_tis.c                      |    3 +-
>  include/linux/tpm.h                             |    4 +
>  security/integrity/ima/Kconfig                  |    1 +
>  security/keys/trusted.c                         |   54 +--
>  21 files changed, 2586 insertions(+), 200 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-driver-ppi
>  create mode 100644 drivers/char/hw_random/tpm-rng.c
>  create mode 100644 drivers/char/tpm/tpm_acpi.c
>  rename drivers/char/tpm/{tpm_bios.c => tpm_eventlog.c} (75%)
>  create mode 100644 drivers/char/tpm/tpm_eventlog.h
>  create mode 100644 drivers/char/tpm/tpm_i2c_infineon.c
>  create mode 100644 drivers/char/tpm/tpm_ibmvtpm.c
>  create mode 100644 drivers/char/tpm/tpm_ibmvtpm.h
>  create mode 100644 drivers/char/tpm/tpm_of.c
>  create mode 100644 drivers/char/tpm/tpm_ppi.c
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-ppi b/Documentation/ABI/testing/sysfs-driver-ppi
> new file mode 100644
> index 0000000..97a003e
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-driver-ppi
> @@ -0,0 +1,70 @@
> +What:		/sys/devices/pnp0/<bus-num>/ppi/
> +Date:		August 2012
> +Kernel Version:	3.6
> +Contact:	xiaoyan.zhang@intel.com
> +Description:
> +		This folder includes the attributes related with PPI (Physical
> +		Presence Interface). Only if TPM is supported by BIOS, this
> +		folder makes sence. The folder path can be got by command
> +		'find /sys/ -name 'pcrs''. For the detail information of PPI,
> +		please refer to the PPI specification from
> +		http://www.trustedcomputinggroup.org/
> +
> +What:		/sys/devices/pnp0/<bus-num>/ppi/version
> +Date:		August 2012
> +Contact:	xiaoyan.zhang@intel.com
> +Description:
> +		This attribute shows the version of the PPI supported by the
> +		platform.
> +		This file is readonly.
> +
> +What:		/sys/devices/pnp0/<bus-num>/ppi/request
> +Date:		August 2012
> +Contact:	xiaoyan.zhang@intel.com
> +Description:
> +		This attribute shows the request for an operation to be
> +		executed in the pre-OS environment. It is the only input from
> +		the OS to the pre-OS environment. The request should be an
> +		integer value range from 1 to 160, and 0 means no request.
> +		This file can be read and written.
> +
> +What:		/sys/devices/pnp0/00:<bus-num>/ppi/response
> +Date:		August 2012
> +Contact:	xiaoyan.zhang@intel.com
> +Description:
> +		This attribute shows the response to the most recent operation
> +		request it acted upon. The format is "<request> <response num>
> +		: <response description>".
> +		This file is readonly.
> +
> +What:		/sys/devices/pnp0/<bus-num>/ppi/transition_action
> +Date:		August 2012
> +Contact:	xiaoyan.zhang@intel.com
> +Description:
> +		This attribute shows the platform-specific action that should
> +		take place in order to transition to the BIOS for execution of
> +		a requested operation. The format is "<action num>: <action
> +		description>".
> +		This file is readonly.
> +
> +What:		/sys/devices/pnp0/<bus-num>/ppi/tcg_operations
> +Date:		August 2012
> +Contact:	xiaoyan.zhang@intel.com
> +Description:
> +		This attribute shows whether it is allowed to request an
> +		operation to be executed in the pre-OS environment by the BIOS
> +		for the requests defined by TCG, i.e. requests from 1 to 22.
> +		The format is "<request> <status num>: <status description>".
> +		This attribute is only supported by PPI version 1.2+.
> +		This file is readonly.
> +
> +What:		/sys/devices/pnp0/<bus-num>/ppi/vs_operations
> +Date:		August 2012
> +Contact:	xiaoyan.zhang@intel.com
> +Description:
> +		This attribute shows whether it is allowed to request an
> +		operation to be executed in the pre-OS environment by the BIOS
> +		for the verdor specific requests, i.e. requests from 128 to
> +		255. The format is same with tcg_operations. This attribute
> +		is also only supported by PPI version 1.2+.
> +		This file is readonly.
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index 0794a30..e144498 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -1624,6 +1624,63 @@ static void __init prom_instantiate_rtas(void)
>  
>  #ifdef CONFIG_PPC64
>  /*
> + * Allocate room for and instantiate Stored Measurement Log (SML)
> + */
> +static void __init prom_instantiate_sml(void)
> +{
> +	phandle ibmvtpm_node;
> +	ihandle ibmvtpm_inst;
> +	u32 entry = 0, size = 0;
> +	u64 base;
> +
> +	prom_debug("prom_instantiate_sml: start...\n");
> +
> +	ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/ibm,vtpm"));
> +	prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
> +	if (!PHANDLE_VALID(ibmvtpm_node))
> +		return;
> +
> +	ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/ibm,vtpm"));
> +	if (!IHANDLE_VALID(ibmvtpm_inst)) {
> +		prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
> +		return;
> +	}
> +
> +	if (call_prom_ret("call-method", 2, 2, &size,
> +			  ADDR("sml-get-handover-size"),
> +			  ibmvtpm_inst) != 0 || size == 0) {
> +		prom_printf("SML get handover size failed\n");
> +		return;
> +	}
> +
> +	base = alloc_down(size, PAGE_SIZE, 0);
> +	if (base == 0)
> +		prom_panic("Could not allocate memory for sml\n");
> +
> +	prom_printf("instantiating sml at 0x%x...", base);
> +
> +	if (call_prom_ret("call-method", 4, 2, &entry,
> +			  ADDR("sml-handover"),
> +			  ibmvtpm_inst, size, base) != 0 || entry == 0) {
> +		prom_printf("SML handover failed\n");
> +		return;
> +	}
> +	prom_printf(" done\n");
> +
> +	reserve_mem(base, size);
> +
> +	prom_setprop(ibmvtpm_node, "/ibm,vtpm", "linux,sml-base",
> +		     &base, sizeof(base));
> +	prom_setprop(ibmvtpm_node, "/ibm,vtpm", "linux,sml-size",
> +		     &size, sizeof(size));
> +
> +	prom_debug("sml base     = 0x%x\n", base);
> +	prom_debug("sml size     = 0x%x\n", (long)size);
> +
> +	prom_debug("prom_instantiate_sml: end...\n");
> +}
> +
> +/*
>   * Allocate room for and initialize TCE tables
>   */
>  static void __init prom_initialize_tce_table(void)
> @@ -2916,6 +2973,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
>  		prom_instantiate_opal();
>  #endif
>  
> +#ifdef CONFIG_PPC64
> +	/* instantiate sml */
> +	prom_instantiate_sml();
> +#endif
> +
>  	/*
>  	 * On non-powermacs, put all CPUs in spin-loops.
>  	 *
> diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
> index 7c0d391..fbd9b2b 100644
> --- a/drivers/char/hw_random/Kconfig
> +++ b/drivers/char/hw_random/Kconfig
> @@ -289,3 +289,16 @@ config HW_RANDOM_EXYNOS
>  	  module will be called exynos-rng.
>  
>  	  If unsure, say Y.
> +
> +config HW_RANDOM_TPM
> +	tristate "TPM HW Random Number Generator support"
> +	depends on HW_RANDOM && TCG_TPM
> +	default HW_RANDOM
> +	---help---
> +	  This driver provides kernel-side support for the Random Number
> +	  Generator in the Trusted Platform Module
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called tpm-rng.
> +
> +	  If unsure, say Y.
> diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
> index 39a757c..1fd7eec 100644
> --- a/drivers/char/hw_random/Makefile
> +++ b/drivers/char/hw_random/Makefile
> @@ -25,3 +25,4 @@ obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
>  obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
>  obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
>  obj-$(CONFIG_HW_RANDOM_EXYNOS)	+= exynos-rng.o
> +obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
> diff --git a/drivers/char/hw_random/tpm-rng.c b/drivers/char/hw_random/tpm-rng.c
> new file mode 100644
> index 0000000..d6d4482
> --- /dev/null
> +++ b/drivers/char/hw_random/tpm-rng.c
> @@ -0,0 +1,50 @@
> +/*
> + * Copyright (C) 2012 Kent Yoder IBM Corporation
> + *
> + * HWRNG interfaces to pull RNG data from a TPM
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
> + */
> +
> +#include <linux/module.h>
> +#include <linux/hw_random.h>
> +#include <linux/tpm.h>
> +
> +#define MODULE_NAME "tpm-rng"
> +
> +static int tpm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
> +{
> +	return tpm_get_random(TPM_ANY_NUM, data, max);
> +}
> +
> +static struct hwrng tpm_rng = {
> +	.name = MODULE_NAME,
> +	.read = tpm_rng_read,
> +};
> +
> +static int __init rng_init(void)
> +{
> +	return hwrng_register(&tpm_rng);
> +}
> +module_init(rng_init);
> +
> +static void __exit rng_exit(void)
> +{
> +	hwrng_unregister(&tpm_rng);
> +}
> +module_exit(rng_exit);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Kent Yoder <key@linux.vnet.ibm.com>");
> +MODULE_DESCRIPTION("RNG driver for TPM devices");
> diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
> index a048199..915875e 100644
> --- a/drivers/char/tpm/Kconfig
> +++ b/drivers/char/tpm/Kconfig
> @@ -33,6 +33,17 @@ config TCG_TIS
>  	  from within Linux.  To compile this driver as a module, choose
>  	  M here; the module will be called tpm_tis.
>  
> +config TCG_TIS_I2C_INFINEON
> +	tristate "TPM Interface Specification 1.2 Interface (I2C - Infineon)"
> +	depends on I2C
> +	---help---
> +	  If you have a TPM security chip that is compliant with the
> +	  TCG TIS 1.2 TPM specification and Infineon's I2C Protocol Stack
> +	  Specification 0.20 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_tis_i2c_infineon.
> +
>  config TCG_NSC
>  	tristate "National Semiconductor TPM Interface"
>  	depends on X86
> @@ -62,4 +73,12 @@ config TCG_INFINEON
>  	  Further information on this driver and the supported hardware
>  	  can be found at http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ 
>  
> +config TCG_IBMVTPM
> +	tristate "IBM VTPM Interface"
> +	depends on PPC64
> +	---help---
> +	  If you have IBM virtual TPM (VTPM) support 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_ibmvtpm.
> +
>  endif # TCG_TPM
> diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
> index ea3a1e0..5b3fc8b 100644
> --- a/drivers/char/tpm/Makefile
> +++ b/drivers/char/tpm/Makefile
> @@ -4,8 +4,16 @@
>  obj-$(CONFIG_TCG_TPM) += tpm.o
>  ifdef CONFIG_ACPI
>  	obj-$(CONFIG_TCG_TPM) += tpm_bios.o
> +	tpm_bios-objs += tpm_eventlog.o tpm_acpi.o tpm_ppi.o
> +else
> +ifdef CONFIG_TCG_IBMVTPM
> +	obj-$(CONFIG_TCG_TPM) += tpm_bios.o
> +	tpm_bios-objs += tpm_eventlog.o tpm_of.o
> +endif
>  endif
>  obj-$(CONFIG_TCG_TIS) += tpm_tis.o
> +obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
>  obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
>  obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
>  obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
> +obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
> diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
> index 817f0ee..39526c0 100644
> --- a/drivers/char/tpm/tpm.c
> +++ b/drivers/char/tpm/tpm.c
> @@ -30,12 +30,7 @@
>  #include <linux/freezer.h>
>  
>  #include "tpm.h"
> -
> -enum tpm_const {
> -	TPM_MINOR = 224,	/* officially assigned */
> -	TPM_BUFSIZE = 4096,
> -	TPM_NUM_DEVICES = 256,
> -};
> +#include "tpm_eventlog.h"
>  
>  enum tpm_duration {
>  	TPM_SHORT = 0,
> @@ -482,6 +477,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
>  #define TPM_INTERNAL_RESULT_SIZE 200
>  #define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
>  #define TPM_ORD_GET_CAP cpu_to_be32(101)
> +#define TPM_ORD_GET_RANDOM cpu_to_be32(70)
>  
>  static const struct tpm_input_header tpm_getcap_header = {
>  	.tag = TPM_TAG_RQU_COMMAND,
> @@ -1175,7 +1171,7 @@ int tpm_release(struct inode *inode, struct file *file)
>  	flush_work_sync(&chip->work);
>  	file->private_data = NULL;
>  	atomic_set(&chip->data_pending, 0);
> -	kfree(chip->data_buffer);
> +	kzfree(chip->data_buffer);
>  	clear_bit(0, &chip->is_open);
>  	put_device(chip->dev);
>  	return 0;
> @@ -1227,7 +1223,6 @@ ssize_t tpm_read(struct file *file, char __user *buf,
>  	del_singleshot_timer_sync(&chip->user_read_timer);
>  	flush_work_sync(&chip->work);
>  	ret_size = atomic_read(&chip->data_pending);
> -	atomic_set(&chip->data_pending, 0);
>  	if (ret_size > 0) {	/* relay data */
>  		ssize_t orig_ret_size = ret_size;
>  		if (size < ret_size)
> @@ -1242,6 +1237,8 @@ ssize_t tpm_read(struct file *file, char __user *buf,
>  		mutex_unlock(&chip->buffer_mutex);
>  	}
>  
> +	atomic_set(&chip->data_pending, 0);
> +
>  	return ret_size;
>  }
>  EXPORT_SYMBOL_GPL(tpm_read);
> @@ -1326,6 +1323,58 @@ int tpm_pm_resume(struct device *dev)
>  }
>  EXPORT_SYMBOL_GPL(tpm_pm_resume);
>  
> +#define TPM_GETRANDOM_RESULT_SIZE	18
> +static struct tpm_input_header tpm_getrandom_header = {
> +	.tag = TPM_TAG_RQU_COMMAND,
> +	.length = cpu_to_be32(14),
> +	.ordinal = TPM_ORD_GET_RANDOM
> +};
> +
> +/**
> + * tpm_get_random() - Get random bytes from the tpm's RNG
> + * @chip_num: A specific chip number for the request or TPM_ANY_NUM
> + * @out: destination buffer for the random bytes
> + * @max: the max number of bytes to write to @out
> + *
> + * Returns < 0 on error and the number of bytes read on success
> + */
> +int tpm_get_random(u32 chip_num, u8 *out, size_t max)
> +{
> +	struct tpm_chip *chip;
> +	struct tpm_cmd_t tpm_cmd;
> +	u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
> +	int err, total = 0, retries = 5;
> +	u8 *dest = out;
> +
> +	chip = tpm_chip_find_get(chip_num);
> +	if (chip == NULL)
> +		return -ENODEV;
> +
> +	if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
> +		return -EINVAL;
> +
> +	do {
> +		tpm_cmd.header.in = tpm_getrandom_header;
> +		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
> +
> +		err = transmit_cmd(chip, &tpm_cmd,
> +				   TPM_GETRANDOM_RESULT_SIZE + num_bytes,
> +				   "attempting get random");
> +		if (err)
> +			break;
> +
> +		recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
> +		memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
> +
> +		dest += recd;
> +		total += recd;
> +		num_bytes -= recd;
> +	} while (retries-- && total < max);
> +
> +	return total ? total : -EIO;
> +}
> +EXPORT_SYMBOL_GPL(tpm_get_random);
> +
>  /* In case vendor provided release function, call it too.*/
>  
>  void tpm_dev_vendor_release(struct tpm_chip *chip)
> @@ -1427,6 +1476,11 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
>  		goto put_device;
>  	}
>  
> +	if (sys_add_ppi(&dev->kobj)) {
> +		misc_deregister(&chip->vendor.miscdev);
> +		goto put_device;
> +	}
> +
>  	chip->bios_dir = tpm_bios_log_setup(devname);
>  
>  	/* Make chip available */
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 917f727..02c266a 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -28,6 +28,12 @@
>  #include <linux/io.h>
>  #include <linux/tpm.h>
>  
> +enum tpm_const {
> +	TPM_MINOR = 224,	/* officially assigned */
> +	TPM_BUFSIZE = 4096,
> +	TPM_NUM_DEVICES = 256,
> +};
> +
>  enum tpm_timeout {
>  	TPM_TIMEOUT = 5,	/* msecs */
>  };
> @@ -94,6 +100,7 @@ struct tpm_vendor_specific {
>  	bool timeout_adjusted;
>  	unsigned long duration[3]; /* jiffies */
>  	bool duration_adjusted;
> +	void *data;
>  
>  	wait_queue_head_t read_queue;
>  	wait_queue_head_t int_queue;
> @@ -269,6 +276,21 @@ struct tpm_pcrextend_in {
>  	u8	hash[TPM_DIGEST_SIZE];
>  }__attribute__((packed));
>  
> +/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
> + * bytes, but 128 is still a relatively large number of random bytes and
> + * anything much bigger causes users of struct tpm_cmd_t to start getting
> + * compiler warnings about stack frame size. */
> +#define TPM_MAX_RNG_DATA	128
> +
> +struct tpm_getrandom_out {
> +	__be32 rng_data_len;
> +	u8     rng_data[TPM_MAX_RNG_DATA];
> +}__attribute__((packed));
> +
> +struct tpm_getrandom_in {
> +	__be32 num_bytes;
> +}__attribute__((packed));
> +
>  typedef union {
>  	struct	tpm_getcap_params_out getcap_out;
>  	struct	tpm_readpubek_params_out readpubek_out;
> @@ -277,6 +299,8 @@ typedef union {
>  	struct	tpm_pcrread_in	pcrread_in;
>  	struct	tpm_pcrread_out	pcrread_out;
>  	struct	tpm_pcrextend_in pcrextend_in;
> +	struct	tpm_getrandom_in getrandom_in;
> +	struct	tpm_getrandom_out getrandom_out;
>  } tpm_cmd_params;
>  
>  struct tpm_cmd_t {
> @@ -303,15 +327,12 @@ extern int tpm_pm_suspend(struct device *);
>  extern int tpm_pm_resume(struct device *);
>  extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
>  			     wait_queue_head_t *);
> +
>  #ifdef CONFIG_ACPI
> -extern struct dentry ** tpm_bios_log_setup(char *);
> -extern void tpm_bios_log_teardown(struct dentry **);
> +extern ssize_t sys_add_ppi(struct kobject *parent);
>  #else
> -static inline struct dentry ** tpm_bios_log_setup(char *name)
> -{
> -	return NULL;
> -}
> -static inline void tpm_bios_log_teardown(struct dentry **dir)
> +static inline ssize_t sys_add_ppi(struct kobject *parent)
>  {
> +	return 0;
>  }
>  #endif
> diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_acpi.c
> new file mode 100644
> index 0000000..fe3fa94
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_acpi.c
> @@ -0,0 +1,109 @@
> +/*
> + * Copyright (C) 2005 IBM Corporation
> + *
> + * Authors:
> + *	Seiji Munetoh <munetoh@jp.ibm.com>
> + *	Stefan Berger <stefanb@us.ibm.com>
> + *	Reiner Sailer <sailer@watson.ibm.com>
> + *	Kylene Hall <kjhall@us.ibm.com>
> + *
> + * Maintained by: <tpmdd-devel@lists.sourceforge.net>
> + *
> + * Access to the eventlog extended by the TCG BIOS of PC platform
> + *
> + * 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; either version
> + * 2 of the License, or (at your option) any later version.
> + *
> + */
> +
> +#include <linux/seq_file.h>
> +#include <linux/fs.h>
> +#include <linux/security.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <acpi/acpi.h>
> +
> +#include "tpm.h"
> +#include "tpm_eventlog.h"
> +
> +struct acpi_tcpa {
> +	struct acpi_table_header hdr;
> +	u16 platform_class;
> +	union {
> +		struct client_hdr {
> +			u32 log_max_len __attribute__ ((packed));
> +			u64 log_start_addr __attribute__ ((packed));
> +		} client;
> +		struct server_hdr {
> +			u16 reserved;
> +			u64 log_max_len __attribute__ ((packed));
> +			u64 log_start_addr __attribute__ ((packed));
> +		} server;
> +	};
> +};
> +
> +/* read binary bios log */
> +int read_log(struct tpm_bios_log *log)
> +{
> +	struct acpi_tcpa *buff;
> +	acpi_status status;
> +	struct acpi_table_header *virt;
> +	u64 len, start;
> +
> +	if (log->bios_event_log != NULL) {
> +		printk(KERN_ERR
> +		       "%s: ERROR - Eventlog already initialized\n",
> +		       __func__);
> +		return -EFAULT;
> +	}
> +
> +	/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
> +	status = acpi_get_table(ACPI_SIG_TCPA, 1,
> +				(struct acpi_table_header **)&buff);
> +
> +	if (ACPI_FAILURE(status)) {
> +		printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
> +		       __func__);
> +		return -EIO;
> +	}
> +
> +	switch(buff->platform_class) {
> +	case BIOS_SERVER:
> +		len = buff->server.log_max_len;
> +		start = buff->server.log_start_addr;
> +		break;
> +	case BIOS_CLIENT:
> +	default:
> +		len = buff->client.log_max_len;
> +		start = buff->client.log_start_addr;
> +		break;
> +	}
> +	if (!len) {
> +		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
> +		return -EIO;
> +	}
> +
> +	/* malloc EventLog space */
> +	log->bios_event_log = kmalloc(len, GFP_KERNEL);
> +	if (!log->bios_event_log) {
> +		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
> +			__func__);
> +		return -ENOMEM;
> +	}
> +
> +	log->bios_event_log_end = log->bios_event_log + len;
> +
> +	virt = acpi_os_map_memory(start, len);
> +	if (!virt) {
> +		kfree(log->bios_event_log);
> +		printk("%s: ERROR - Unable to map memory\n", __func__);
> +		return -EIO;
> +	}
> +
> +	memcpy(log->bios_event_log, virt, len);
> +
> +	acpi_os_unmap_memory(virt, len);
> +	return 0;
> +}
> diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_eventlog.c
> similarity index 75%
> rename from drivers/char/tpm/tpm_bios.c
> rename to drivers/char/tpm/tpm_eventlog.c
> index 0636520..84ddc55 100644
> --- a/drivers/char/tpm/tpm_bios.c
> +++ b/drivers/char/tpm/tpm_eventlog.c
> @@ -1,7 +1,8 @@
>  /*
> - * Copyright (C) 2005 IBM Corporation
> + * Copyright (C) 2005, 2012 IBM Corporation
>   *
>   * Authors:
> + *	Kent Yoder <key@linux.vnet.ibm.com>
>   *	Seiji Munetoh <munetoh@jp.ibm.com>
>   *	Stefan Berger <stefanb@us.ibm.com>
>   *	Reiner Sailer <sailer@watson.ibm.com>
> @@ -9,7 +10,7 @@
>   *
>   * Maintained by: <tpmdd-devel@lists.sourceforge.net>
>   *
> - * Access to the eventlog extended by the TCG BIOS of PC platform
> + * Access to the eventlog created by a system's firmware / BIOS
>   *
>   * This program is free software; you can redistribute it and/or
>   * modify it under the terms of the GNU General Public License
> @@ -23,67 +24,10 @@
>  #include <linux/security.h>
>  #include <linux/module.h>
>  #include <linux/slab.h>
> -#include <acpi/acpi.h>
> -#include "tpm.h"
> -
> -#define TCG_EVENT_NAME_LEN_MAX	255
> -#define MAX_TEXT_EVENT		1000	/* Max event string length */
> -#define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
> -
> -enum bios_platform_class {
> -	BIOS_CLIENT = 0x00,
> -	BIOS_SERVER = 0x01,
> -};
> -
> -struct tpm_bios_log {
> -	void *bios_event_log;
> -	void *bios_event_log_end;
> -};
> -
> -struct acpi_tcpa {
> -	struct acpi_table_header hdr;
> -	u16 platform_class;
> -	union {
> -		struct client_hdr {
> -			u32 log_max_len __attribute__ ((packed));
> -			u64 log_start_addr __attribute__ ((packed));
> -		} client;
> -		struct server_hdr {
> -			u16 reserved;
> -			u64 log_max_len __attribute__ ((packed));
> -			u64 log_start_addr __attribute__ ((packed));
> -		} server;
> -	};
> -};
>  
> -struct tcpa_event {
> -	u32 pcr_index;
> -	u32 event_type;
> -	u8 pcr_value[20];	/* SHA1 */
> -	u32 event_size;
> -	u8 event_data[0];
> -};
> +#include "tpm.h"
> +#include "tpm_eventlog.h"
>  
> -enum tcpa_event_types {
> -	PREBOOT = 0,
> -	POST_CODE,
> -	UNUSED,
> -	NO_ACTION,
> -	SEPARATOR,
> -	ACTION,
> -	EVENT_TAG,
> -	SCRTM_CONTENTS,
> -	SCRTM_VERSION,
> -	CPU_MICROCODE,
> -	PLATFORM_CONFIG_FLAGS,
> -	TABLE_OF_DEVICES,
> -	COMPACT_HASH,
> -	IPL,
> -	IPL_PARTITION_DATA,
> -	NONHOST_CODE,
> -	NONHOST_CONFIG,
> -	NONHOST_INFO,
> -};
>  
>  static const char* tcpa_event_type_strings[] = {
>  	"PREBOOT",
> @@ -106,28 +50,6 @@ static const char* tcpa_event_type_strings[] = {
>  	"Non-Host Info"
>  };
>  
> -struct tcpa_pc_event {
> -	u32 event_id;
> -	u32 event_size;
> -	u8 event_data[0];
> -};
> -
> -enum tcpa_pc_event_ids {
> -	SMBIOS = 1,
> -	BIS_CERT,
> -	POST_BIOS_ROM,
> -	ESCD,
> -	CMOS,
> -	NVRAM,
> -	OPTION_ROM_EXEC,
> -	OPTION_ROM_CONFIG,
> -	OPTION_ROM_MICROCODE = 10,
> -	S_CRTM_VERSION,
> -	S_CRTM_CONTENTS,
> -	POST_CONTENTS,
> -	HOST_TABLE_OF_DEVICES,
> -};
> -
>  static const char* tcpa_pc_event_id_strings[] = {
>  	"",
>  	"SMBIOS",
> @@ -358,65 +280,6 @@ static const struct seq_operations tpm_binary_b_measurments_seqops = {
>  	.show = tpm_binary_bios_measurements_show,
>  };
>  
> -/* read binary bios log */
> -static int read_log(struct tpm_bios_log *log)
> -{
> -	struct acpi_tcpa *buff;
> -	acpi_status status;
> -	struct acpi_table_header *virt;
> -	u64 len, start;
> -
> -	if (log->bios_event_log != NULL) {
> -		printk(KERN_ERR
> -		       "%s: ERROR - Eventlog already initialized\n",
> -		       __func__);
> -		return -EFAULT;
> -	}
> -
> -	/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
> -	status = acpi_get_table(ACPI_SIG_TCPA, 1,
> -				(struct acpi_table_header **)&buff);
> -
> -	if (ACPI_FAILURE(status)) {
> -		printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
> -		       __func__);
> -		return -EIO;
> -	}
> -
> -	switch(buff->platform_class) {
> -	case BIOS_SERVER:
> -		len = buff->server.log_max_len;
> -		start = buff->server.log_start_addr;
> -		break;
> -	case BIOS_CLIENT:
> -	default:
> -		len = buff->client.log_max_len;
> -		start = buff->client.log_start_addr;
> -		break;
> -	}
> -	if (!len) {
> -		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
> -		return -EIO;
> -	}
> -
> -	/* malloc EventLog space */
> -	log->bios_event_log = kmalloc(len, GFP_KERNEL);
> -	if (!log->bios_event_log) {
> -		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
> -			__func__);
> -		return -ENOMEM;
> -	}
> -
> -	log->bios_event_log_end = log->bios_event_log + len;
> -
> -	virt = acpi_os_map_memory(start, len);
> -
> -	memcpy(log->bios_event_log, virt, len);
> -
> -	acpi_os_unmap_memory(virt, len);
> -	return 0;
> -}
> -
>  static int tpm_ascii_bios_measurements_open(struct inode *inode,
>  					    struct file *file)
>  {
> diff --git a/drivers/char/tpm/tpm_eventlog.h b/drivers/char/tpm/tpm_eventlog.h
> new file mode 100644
> index 0000000..e7da086
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_eventlog.h
> @@ -0,0 +1,86 @@
> +
> +#ifndef __TPM_EVENTLOG_H__
> +#define __TPM_EVENTLOG_H__
> +
> +#define TCG_EVENT_NAME_LEN_MAX	255
> +#define MAX_TEXT_EVENT		1000	/* Max event string length */
> +#define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
> +
> +enum bios_platform_class {
> +	BIOS_CLIENT = 0x00,
> +	BIOS_SERVER = 0x01,
> +};
> +
> +struct tpm_bios_log {
> +	void *bios_event_log;
> +	void *bios_event_log_end;
> +};
> +
> +struct tcpa_event {
> +	u32 pcr_index;
> +	u32 event_type;
> +	u8 pcr_value[20];	/* SHA1 */
> +	u32 event_size;
> +	u8 event_data[0];
> +};
> +
> +enum tcpa_event_types {
> +	PREBOOT = 0,
> +	POST_CODE,
> +	UNUSED,
> +	NO_ACTION,
> +	SEPARATOR,
> +	ACTION,
> +	EVENT_TAG,
> +	SCRTM_CONTENTS,
> +	SCRTM_VERSION,
> +	CPU_MICROCODE,
> +	PLATFORM_CONFIG_FLAGS,
> +	TABLE_OF_DEVICES,
> +	COMPACT_HASH,
> +	IPL,
> +	IPL_PARTITION_DATA,
> +	NONHOST_CODE,
> +	NONHOST_CONFIG,
> +	NONHOST_INFO,
> +};
> +
> +struct tcpa_pc_event {
> +	u32 event_id;
> +	u32 event_size;
> +	u8 event_data[0];
> +};
> +
> +enum tcpa_pc_event_ids {
> +	SMBIOS = 1,
> +	BIS_CERT,
> +	POST_BIOS_ROM,
> +	ESCD,
> +	CMOS,
> +	NVRAM,
> +	OPTION_ROM_EXEC,
> +	OPTION_ROM_CONFIG,
> +	OPTION_ROM_MICROCODE = 10,
> +	S_CRTM_VERSION,
> +	S_CRTM_CONTENTS,
> +	POST_CONTENTS,
> +	HOST_TABLE_OF_DEVICES,
> +};
> +
> +int read_log(struct tpm_bios_log *log);
> +
> +#if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \
> +	defined(CONFIG_ACPI)
> +extern struct dentry **tpm_bios_log_setup(char *);
> +extern void tpm_bios_log_teardown(struct dentry **);
> +#else
> +static inline struct dentry **tpm_bios_log_setup(char *name)
> +{
> +	return NULL;
> +}
> +static inline void tpm_bios_log_teardown(struct dentry **dir)
> +{
> +}
> +#endif
> +
> +#endif
> diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
> new file mode 100644
> index 0000000..5a831ae
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_i2c_infineon.c
> @@ -0,0 +1,695 @@
> +/*
> + * Copyright (C) 2012 Infineon Technologies
> + *
> + * Authors:
> + * Peter Huewe <peter.huewe@infineon.com>
> + *
> + * Device driver for TCG/TCPA TPM (trusted platform module).
> + * Specifications at www.trustedcomputinggroup.org
> + *
> + * This device driver implements the TPM interface as defined in
> + * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
> + * Infineon I2C Protocol Stack Specification v0.20.
> + *
> + * It is based on the original tpm_tis device driver from Leendert van
> + * Dorn and Kyleen Hall.
> + *
> + * 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/init.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/wait.h>
> +#include "tpm.h"
> +
> +/* max. buffer size supported by our TPM */
> +#define TPM_BUFSIZE 1260
> +
> +/* max. number of iterations after I2C NAK */
> +#define MAX_COUNT 3
> +
> +#define SLEEP_DURATION_LOW 55
> +#define SLEEP_DURATION_HI 65
> +
> +/* max. number of iterations after I2C NAK for 'long' commands
> + * we need this especially for sending TPM_READY, since the cleanup after the
> + * transtion to the ready state may take some time, but it is unpredictable
> + * how long it will take.
> + */
> +#define MAX_COUNT_LONG 50
> +
> +#define SLEEP_DURATION_LONG_LOW 200
> +#define SLEEP_DURATION_LONG_HI 220
> +
> +/* After sending TPM_READY to 'reset' the TPM we have to sleep even longer */
> +#define SLEEP_DURATION_RESET_LOW 2400
> +#define SLEEP_DURATION_RESET_HI 2600
> +
> +/* we want to use usleep_range instead of msleep for the 5ms TPM_TIMEOUT */
> +#define TPM_TIMEOUT_US_LOW (TPM_TIMEOUT * 1000)
> +#define TPM_TIMEOUT_US_HI  (TPM_TIMEOUT_US_LOW + 2000)
> +
> +/* expected value for DIDVID register */
> +#define TPM_TIS_I2C_DID_VID 0x000b15d1L
> +
> +/* Structure to store I2C TPM specific stuff */
> +struct tpm_inf_dev {
> +	struct i2c_client *client;
> +	u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */
> +	struct tpm_chip *chip;
> +};
> +
> +static struct tpm_inf_dev tpm_dev;
> +static struct i2c_driver tpm_tis_i2c_driver;
> +
> +/*
> + * iic_tpm_read() - read from TPM register
> + * @addr: register address to read from
> + * @buffer: provided by caller
> + * @len: number of bytes to read
> + *
> + * Read len bytes from TPM register and put them into
> + * buffer (little-endian format, i.e. first byte is put into buffer[0]).
> + *
> + * NOTE: TPM is big-endian for multi-byte values. Multi-byte
> + * values have to be swapped.
> + *
> + * NOTE: We can't unfortunately use the combined read/write functions
> + * provided by the i2c core as the TPM currently does not support the
> + * repeated start condition and due to it's special requirements.
> + * The i2c_smbus* functions do not work for this chip.
> + *
> + * Return -EIO on error, 0 on success.
> + */
> +static int iic_tpm_read(u8 addr, u8 *buffer, size_t len)
> +{
> +
> +	struct i2c_msg msg1 = { tpm_dev.client->addr, 0, 1, &addr };
> +	struct i2c_msg msg2 = { tpm_dev.client->addr, I2C_M_RD, len, buffer };
> +
> +	int rc;
> +	int count;
> +
> +	/* Lock the adapter for the duration of the whole sequence. */
> +	if (!tpm_dev.client->adapter->algo->master_xfer)
> +		return -EOPNOTSUPP;
> +	i2c_lock_adapter(tpm_dev.client->adapter);
> +
> +	for (count = 0; count < MAX_COUNT; count++) {
> +		rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
> +		if (rc > 0)
> +			break;	/* break here to skip sleep */
> +
> +		usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
> +	}
> +
> +	if (rc <= 0)
> +		goto out;
> +
> +	/* After the TPM has successfully received the register address it needs
> +	 * some time, thus we're sleeping here again, before retrieving the data
> +	 */
> +	for (count = 0; count < MAX_COUNT; count++) {
> +		usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
> +		rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1);
> +		if (rc > 0)
> +			break;
> +
> +	}
> +
> +out:
> +	i2c_unlock_adapter(tpm_dev.client->adapter);
> +	if (rc <= 0)
> +		return -EIO;
> +
> +	return 0;
> +}
> +
> +static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len,
> +				 unsigned int sleep_low,
> +				 unsigned int sleep_hi, u8 max_count)
> +{
> +	int rc = -EIO;
> +	int count;
> +
> +	struct i2c_msg msg1 = { tpm_dev.client->addr, 0, len + 1, tpm_dev.buf };
> +
> +	if (len > TPM_BUFSIZE)
> +		return -EINVAL;
> +
> +	if (!tpm_dev.client->adapter->algo->master_xfer)
> +		return -EOPNOTSUPP;
> +	i2c_lock_adapter(tpm_dev.client->adapter);
> +
> +	/* prepend the 'register address' to the buffer */
> +	tpm_dev.buf[0] = addr;
> +	memcpy(&(tpm_dev.buf[1]), buffer, len);
> +
> +	/*
> +	 * NOTE: We have to use these special mechanisms here and unfortunately
> +	 * cannot rely on the standard behavior of i2c_transfer.
> +	 */
> +	for (count = 0; count < max_count; count++) {
> +		rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
> +		if (rc > 0)
> +			break;
> +
> +		usleep_range(sleep_low, sleep_hi);
> +	}
> +
> +	i2c_unlock_adapter(tpm_dev.client->adapter);
> +	if (rc <= 0)
> +		return -EIO;
> +
> +	return 0;
> +}
> +
> +/*
> + * iic_tpm_write() - write to TPM register
> + * @addr: register address to write to
> + * @buffer: containing data to be written
> + * @len: number of bytes to write
> + *
> + * Write len bytes from provided buffer to TPM register (little
> + * endian format, i.e. buffer[0] is written as first byte).
> + *
> + * NOTE: TPM is big-endian for multi-byte values. Multi-byte
> + * values have to be swapped.
> + *
> + * NOTE: use this function instead of the iic_tpm_write_generic function.
> + *
> + * Return -EIO on error, 0 on success
> + */
> +static int iic_tpm_write(u8 addr, u8 *buffer, size_t len)
> +{
> +	return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LOW,
> +				     SLEEP_DURATION_HI, MAX_COUNT);
> +}
> +
> +/*
> + * This function is needed especially for the cleanup situation after
> + * sending TPM_READY
> + * */
> +static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len)
> +{
> +	return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG_LOW,
> +				     SLEEP_DURATION_LONG_HI, MAX_COUNT_LONG);
> +}
> +
> +enum tis_access {
> +	TPM_ACCESS_VALID = 0x80,
> +	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
> +	TPM_ACCESS_REQUEST_PENDING = 0x04,
> +	TPM_ACCESS_REQUEST_USE = 0x02,
> +};
> +
> +enum tis_status {
> +	TPM_STS_VALID = 0x80,
> +	TPM_STS_COMMAND_READY = 0x40,
> +	TPM_STS_GO = 0x20,
> +	TPM_STS_DATA_AVAIL = 0x10,
> +	TPM_STS_DATA_EXPECT = 0x08,
> +};
> +
> +enum tis_defaults {
> +	TIS_SHORT_TIMEOUT = 750,	/* ms */
> +	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
> +};
> +
> +#define	TPM_ACCESS(l)			(0x0000 | ((l) << 4))
> +#define	TPM_STS(l)			(0x0001 | ((l) << 4))
> +#define	TPM_DATA_FIFO(l)		(0x0005 | ((l) << 4))
> +#define	TPM_DID_VID(l)			(0x0006 | ((l) << 4))
> +
> +static int check_locality(struct tpm_chip *chip, int loc)
> +{
> +	u8 buf;
> +	int rc;
> +
> +	rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1);
> +	if (rc < 0)
> +		return rc;
> +
> +	if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
> +	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
> +		chip->vendor.locality = loc;
> +		return loc;
> +	}
> +
> +	return -EIO;
> +}
> +
> +/* implementation similar to tpm_tis */
> +static void release_locality(struct tpm_chip *chip, int loc, int force)
> +{
> +	u8 buf;
> +	if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0)
> +		return;
> +
> +	if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
> +	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) {
> +		buf = TPM_ACCESS_ACTIVE_LOCALITY;
> +		iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
> +	}
> +}
> +
> +static int request_locality(struct tpm_chip *chip, int loc)
> +{
> +	unsigned long stop;
> +	u8 buf = TPM_ACCESS_REQUEST_USE;
> +
> +	if (check_locality(chip, loc) >= 0)
> +		return loc;
> +
> +	iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
> +
> +	/* wait for burstcount */
> +	stop = jiffies + chip->vendor.timeout_a;
> +	do {
> +		if (check_locality(chip, loc) >= 0)
> +			return loc;
> +		usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
> +	} while (time_before(jiffies, stop));
> +
> +	return -ETIME;
> +}
> +
> +static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
> +{
> +	/* NOTE: since I2C read may fail, return 0 in this case --> time-out */
> +	u8 buf;
> +	if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0)
> +		return 0;
> +	else
> +		return buf;
> +}
> +
> +static void tpm_tis_i2c_ready(struct tpm_chip *chip)
> +{
> +	/* this causes the current command to be aborted */
> +	u8 buf = TPM_STS_COMMAND_READY;
> +	iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1);
> +}
> +
> +static ssize_t get_burstcount(struct tpm_chip *chip)
> +{
> +	unsigned long stop;
> +	ssize_t burstcnt;
> +	u8 buf[3];
> +
> +	/* wait for burstcount */
> +	/* which timeout value, spec has 2 answers (c & d) */
> +	stop = jiffies + chip->vendor.timeout_d;
> +	do {
> +		/* Note: STS is little endian */
> +		if (iic_tpm_read(TPM_STS(chip->vendor.locality)+1, buf, 3) < 0)
> +			burstcnt = 0;
> +		else
> +			burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
> +
> +		if (burstcnt)
> +			return burstcnt;
> +
> +		usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
> +	} while (time_before(jiffies, stop));
> +	return -EBUSY;
> +}
> +
> +static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
> +			 int *status)
> +{
> +	unsigned long stop;
> +
> +	/* check current status */
> +	*status = tpm_tis_i2c_status(chip);
> +	if ((*status & mask) == mask)
> +		return 0;
> +
> +	stop = jiffies + timeout;
> +	do {
> +		/* since we just checked the status, give the TPM some time */
> +		usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
> +		*status = tpm_tis_i2c_status(chip);
> +		if ((*status & mask) == mask)
> +			return 0;
> +
> +	} while (time_before(jiffies, stop));
> +
> +	return -ETIME;
> +}
> +
> +static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
> +{
> +	size_t size = 0;
> +	ssize_t burstcnt;
> +	u8 retries = 0;
> +	int rc;
> +
> +	while (size < count) {
> +		burstcnt = get_burstcount(chip);
> +
> +		/* burstcnt < 0 = TPM is busy */
> +		if (burstcnt < 0)
> +			return burstcnt;
> +
> +		/* limit received data to max. left */
> +		if (burstcnt > (count - size))
> +			burstcnt = count - size;
> +
> +		rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality),
> +				  &(buf[size]), burstcnt);
> +		if (rc == 0)
> +			size += burstcnt;
> +		else if (rc < 0)
> +			retries++;
> +
> +		/* avoid endless loop in case of broken HW */
> +		if (retries > MAX_COUNT_LONG)
> +			return -EIO;
> +
> +	}
> +	return size;
> +}
> +
> +static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
> +{
> +	int size = 0;
> +	int expected, status;
> +
> +	if (count < TPM_HEADER_SIZE) {
> +		size = -EIO;
> +		goto out;
> +	}
> +
> +	/* read first 10 bytes, including tag, paramsize, and result */
> +	size = recv_data(chip, buf, TPM_HEADER_SIZE);
> +	if (size < TPM_HEADER_SIZE) {
> +		dev_err(chip->dev, "Unable to read header\n");
> +		goto out;
> +	}
> +
> +	expected = be32_to_cpu(*(__be32 *)(buf + 2));
> +	if ((size_t) expected > count) {
> +		size = -EIO;
> +		goto out;
> +	}
> +
> +	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
> +			  expected - TPM_HEADER_SIZE);
> +	if (size < expected) {
> +		dev_err(chip->dev, "Unable to read remainder of result\n");
> +		size = -ETIME;
> +		goto out;
> +	}
> +
> +	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
> +	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
> +		dev_err(chip->dev, "Error left over data\n");
> +		size = -EIO;
> +		goto out;
> +	}
> +
> +out:
> +	tpm_tis_i2c_ready(chip);
> +	/* The TPM needs some time to clean up here,
> +	 * so we sleep rather than keeping the bus busy
> +	 */
> +	usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
> +	release_locality(chip, chip->vendor.locality, 0);
> +	return size;
> +}
> +
> +static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
> +{
> +	int rc, status;
> +	ssize_t burstcnt;
> +	size_t count = 0;
> +	u8 retries = 0;
> +	u8 sts = TPM_STS_GO;
> +
> +	if (len > TPM_BUFSIZE)
> +		return -E2BIG;	/* command is too long for our tpm, sorry */
> +
> +	if (request_locality(chip, 0) < 0)
> +		return -EBUSY;
> +
> +	status = tpm_tis_i2c_status(chip);
> +	if ((status & TPM_STS_COMMAND_READY) == 0) {
> +		tpm_tis_i2c_ready(chip);
> +		if (wait_for_stat
> +		    (chip, TPM_STS_COMMAND_READY,
> +		     chip->vendor.timeout_b, &status) < 0) {
> +			rc = -ETIME;
> +			goto out_err;
> +		}
> +	}
> +
> +	while (count < len - 1) {
> +		burstcnt = get_burstcount(chip);
> +
> +		/* burstcnt < 0 = TPM is busy */
> +		if (burstcnt < 0)
> +			return burstcnt;
> +
> +		if (burstcnt > (len - 1 - count))
> +			burstcnt = len - 1 - count;
> +
> +		rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality),
> +				   &(buf[count]), burstcnt);
> +		if (rc == 0)
> +			count += burstcnt;
> +		else if (rc < 0)
> +			retries++;
> +
> +		/* avoid endless loop in case of broken HW */
> +		if (retries > MAX_COUNT_LONG) {
> +			rc = -EIO;
> +			goto out_err;
> +		}
> +
> +		wait_for_stat(chip, TPM_STS_VALID,
> +			      chip->vendor.timeout_c, &status);
> +
> +		if ((status & TPM_STS_DATA_EXPECT) == 0) {
> +			rc = -EIO;
> +			goto out_err;
> +		}
> +
> +	}
> +
> +	/* write last byte */
> +	iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1);
> +	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
> +	if ((status & TPM_STS_DATA_EXPECT) != 0) {
> +		rc = -EIO;
> +		goto out_err;
> +	}
> +
> +	/* go and do it */
> +	iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1);
> +
> +	return len;
> +out_err:
> +	tpm_tis_i2c_ready(chip);
> +	/* The TPM needs some time to clean up here,
> +	 * so we sleep rather than keeping the bus busy
> +	 */
> +	usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
> +	release_locality(chip, chip->vendor.locality, 0);
> +	return rc;
> +}
> +
> +static const struct file_operations tis_ops = {
> +	.owner = THIS_MODULE,
> +	.llseek = no_llseek,
> +	.open = tpm_open,
> +	.read = tpm_read,
> +	.write = tpm_write,
> +	.release = tpm_release,
> +};
> +
> +static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
> +static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
> +static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
> +static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
> +static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
> +static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
> +static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
> +static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
> +static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
> +static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
> +
> +static struct attribute *tis_attrs[] = {
> +	&dev_attr_pubek.attr,
> +	&dev_attr_pcrs.attr,
> +	&dev_attr_enabled.attr,
> +	&dev_attr_active.attr,
> +	&dev_attr_owned.attr,
> +	&dev_attr_temp_deactivated.attr,
> +	&dev_attr_caps.attr,
> +	&dev_attr_cancel.attr,
> +	&dev_attr_durations.attr,
> +	&dev_attr_timeouts.attr,
> +	NULL,
> +};
> +
> +static struct attribute_group tis_attr_grp = {
> +	.attrs = tis_attrs
> +};
> +
> +static struct tpm_vendor_specific tpm_tis_i2c = {
> +	.status = tpm_tis_i2c_status,
> +	.recv = tpm_tis_i2c_recv,
> +	.send = tpm_tis_i2c_send,
> +	.cancel = tpm_tis_i2c_ready,
> +	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> +	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> +	.req_canceled = TPM_STS_COMMAND_READY,
> +	.attr_group = &tis_attr_grp,
> +	.miscdev.fops = &tis_ops,
> +};
> +
> +static int __devinit tpm_tis_i2c_init(struct device *dev)
> +{
> +	u32 vendor;
> +	int rc = 0;
> +	struct tpm_chip *chip;
> +
> +	chip = tpm_register_hardware(dev, &tpm_tis_i2c);
> +	if (!chip) {
> +		rc = -ENODEV;
> +		goto out_err;
> +	}
> +
> +	/* Disable interrupts */
> +	chip->vendor.irq = 0;
> +
> +	/* Default timeouts */
> +	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
> +	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +
> +	if (request_locality(chip, 0) != 0) {
> +		rc = -ENODEV;
> +		goto out_vendor;
> +	}
> +
> +	/* read four bytes from DID_VID register */
> +	if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) {
> +		rc = -EIO;
> +		goto out_release;
> +	}
> +
> +	/* create DID_VID register value, after swapping to little-endian */
> +	vendor = be32_to_cpu((__be32) vendor);
> +
> +	if (vendor != TPM_TIS_I2C_DID_VID) {
> +		rc = -ENODEV;
> +		goto out_release;
> +	}
> +
> +	dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16);
> +
> +	INIT_LIST_HEAD(&chip->vendor.list);
> +	tpm_dev.chip = chip;
> +
> +	tpm_get_timeouts(chip);
> +	tpm_do_selftest(chip);
> +
> +	return 0;
> +
> +out_release:
> +	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;
> +	dev_set_drvdata(chip->dev, chip);
> +out_err:
> +	return rc;
> +}
> +
> +static const struct i2c_device_id tpm_tis_i2c_table[] = {
> +	{"tpm_i2c_infineon", 0},
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
> +static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
> +
> +static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
> +			     const struct i2c_device_id *id)
> +{
> +	int rc;
> +	if (tpm_dev.client != NULL)
> +		return -EBUSY;	/* We only support one client */
> +
> +	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
> +		dev_err(&client->dev,
> +			"no algorithms associated to the i2c bus\n");
> +		return -ENODEV;
> +	}
> +
> +	client->driver = &tpm_tis_i2c_driver;
> +	tpm_dev.client = client;
> +	rc = tpm_tis_i2c_init(&client->dev);
> +	if (rc != 0) {
> +		client->driver = NULL;
> +		tpm_dev.client = NULL;
> +		rc = -ENODEV;
> +	}
> +	return rc;
> +}
> +
> +static int __devexit tpm_tis_i2c_remove(struct i2c_client *client)
> +{
> +	struct tpm_chip *chip = tpm_dev.chip;
> +	release_locality(chip, chip->vendor.locality, 1);
> +
> +	/* 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;
> +	dev_set_drvdata(chip->dev, chip);
> +
> +	return 0;
> +}
> +
> +static struct i2c_driver tpm_tis_i2c_driver = {
> +
> +	.id_table = tpm_tis_i2c_table,
> +	.probe = tpm_tis_i2c_probe,
> +	.remove = tpm_tis_i2c_remove,
> +	.driver = {
> +		   .name = "tpm_i2c_infineon",
> +		   .owner = THIS_MODULE,
> +		   .pm = &tpm_tis_i2c_ops,
> +		   },
> +};
> +
> +module_i2c_driver(tpm_tis_i2c_driver);
> +MODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>");
> +MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver");
> +MODULE_VERSION("2.1.5");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
> new file mode 100644
> index 0000000..efc4ab3
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_ibmvtpm.c
> @@ -0,0 +1,749 @@
> +/*
> + * Copyright (C) 2012 IBM Corporation
> + *
> + * Author: Ashley Lai <adlai@us.ibm.com>
> + *
> + * Maintained by: <tpmdd-devel@lists.sourceforge.net>
> + *
> + * Device driver for TCG/TCPA TPM (trusted platform module).
> + * Specifications at www.trustedcomputinggroup.org
> + *
> + * 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/dma-mapping.h>
> +#include <linux/dmapool.h>
> +#include <linux/slab.h>
> +#include <asm/vio.h>
> +#include <asm/irq.h>
> +#include <linux/types.h>
> +#include <linux/list.h>
> +#include <linux/spinlock.h>
> +#include <linux/interrupt.h>
> +#include <linux/wait.h>
> +#include <asm/prom.h>
> +
> +#include "tpm.h"
> +#include "tpm_ibmvtpm.h"
> +
> +static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm";
> +
> +static struct vio_device_id tpm_ibmvtpm_device_table[] __devinitdata = {
> +	{ "IBM,vtpm", "IBM,vtpm"},
> +	{ "", "" }
> +};
> +MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table);
> +
> +DECLARE_WAIT_QUEUE_HEAD(wq);
> +
> +/**
> + * ibmvtpm_send_crq - Send a CRQ request
> + * @vdev:	vio device struct
> + * @w1:		first word
> + * @w2:		second word
> + *
> + * Return value:
> + *	0 -Sucess
> + *	Non-zero - Failure
> + */
> +static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2)
> +{
> +	return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2);
> +}
> +
> +/**
> + * ibmvtpm_get_data - Retrieve ibm vtpm data
> + * @dev:	device struct
> + *
> + * Return value:
> + *	vtpm device struct
> + */
> +static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
> +{
> +	struct tpm_chip *chip = dev_get_drvdata(dev);
> +	if (chip)
> +		return (struct ibmvtpm_dev *)chip->vendor.data;
> +	return NULL;
> +}
> +
> +/**
> + * tpm_ibmvtpm_recv - Receive data after send
> + * @chip:	tpm chip struct
> + * @buf:	buffer to read
> + * count:	size of buffer
> + *
> + * Return value:
> + *	Number of bytes read
> + */
> +static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
> +{
> +	struct ibmvtpm_dev *ibmvtpm;
> +	u16 len;
> +
> +	ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
> +
> +	if (!ibmvtpm->rtce_buf) {
> +		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
> +		return 0;
> +	}
> +
> +	wait_event_interruptible(wq, ibmvtpm->crq_res.len != 0);
> +
> +	if (count < ibmvtpm->crq_res.len) {
> +		dev_err(ibmvtpm->dev,
> +			"Invalid size in recv: count=%ld, crq_size=%d\n",
> +			count, ibmvtpm->crq_res.len);
> +		return -EIO;
> +	}
> +
> +	spin_lock(&ibmvtpm->rtce_lock);
> +	memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, ibmvtpm->crq_res.len);
> +	memset(ibmvtpm->rtce_buf, 0, ibmvtpm->crq_res.len);
> +	ibmvtpm->crq_res.valid = 0;
> +	ibmvtpm->crq_res.msg = 0;
> +	len = ibmvtpm->crq_res.len;
> +	ibmvtpm->crq_res.len = 0;
> +	spin_unlock(&ibmvtpm->rtce_lock);
> +	return len;
> +}
> +
> +/**
> + * tpm_ibmvtpm_send - Send tpm request
> + * @chip:	tpm chip struct
> + * @buf:	buffer contains data to send
> + * count:	size of buffer
> + *
> + * Return value:
> + *	Number of bytes sent
> + */
> +static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
> +{
> +	struct ibmvtpm_dev *ibmvtpm;
> +	struct ibmvtpm_crq crq;
> +	u64 *word = (u64 *) &crq;
> +	int rc;
> +
> +	ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
> +
> +	if (!ibmvtpm->rtce_buf) {
> +		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
> +		return 0;
> +	}
> +
> +	if (count > ibmvtpm->rtce_size) {
> +		dev_err(ibmvtpm->dev,
> +			"Invalid size in send: count=%ld, rtce_size=%d\n",
> +			count, ibmvtpm->rtce_size);
> +		return -EIO;
> +	}
> +
> +	spin_lock(&ibmvtpm->rtce_lock);
> +	memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
> +	crq.valid = (u8)IBMVTPM_VALID_CMD;
> +	crq.msg = (u8)VTPM_TPM_COMMAND;
> +	crq.len = (u16)count;
> +	crq.data = ibmvtpm->rtce_dma_handle;
> +
> +	rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]);
> +	if (rc != H_SUCCESS) {
> +		dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
> +		rc = 0;
> +	} else
> +		rc = count;
> +
> +	spin_unlock(&ibmvtpm->rtce_lock);
> +	return rc;
> +}
> +
> +static void tpm_ibmvtpm_cancel(struct tpm_chip *chip)
> +{
> +	return;
> +}
> +
> +static u8 tpm_ibmvtpm_status(struct tpm_chip *chip)
> +{
> +	return 0;
> +}
> +
> +/**
> + * ibmvtpm_crq_get_rtce_size - Send a CRQ request to get rtce size
> + * @ibmvtpm:	vtpm device struct
> + *
> + * Return value:
> + *	0 - Success
> + *	Non-zero - Failure
> + */
> +static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
> +{
> +	struct ibmvtpm_crq crq;
> +	u64 *buf = (u64 *) &crq;
> +	int rc;
> +
> +	crq.valid = (u8)IBMVTPM_VALID_CMD;
> +	crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;
> +
> +	rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
> +	if (rc != H_SUCCESS)
> +		dev_err(ibmvtpm->dev,
> +			"ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
> +
> +	return rc;
> +}
> +
> +/**
> + * ibmvtpm_crq_get_version - Send a CRQ request to get vtpm version
> + *			   - Note that this is vtpm version and not tpm version
> + * @ibmvtpm:	vtpm device struct
> + *
> + * Return value:
> + *	0 - Success
> + *	Non-zero - Failure
> + */
> +static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
> +{
> +	struct ibmvtpm_crq crq;
> +	u64 *buf = (u64 *) &crq;
> +	int rc;
> +
> +	crq.valid = (u8)IBMVTPM_VALID_CMD;
> +	crq.msg = (u8)VTPM_GET_VERSION;
> +
> +	rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
> +	if (rc != H_SUCCESS)
> +		dev_err(ibmvtpm->dev,
> +			"ibmvtpm_crq_get_version failed rc=%d\n", rc);
> +
> +	return rc;
> +}
> +
> +/**
> + * ibmvtpm_crq_send_init_complete - Send a CRQ initialize complete message
> + * @ibmvtpm:	vtpm device struct
> + *
> + * Return value:
> + *	0 - Success
> + *	Non-zero - Failure
> + */
> +static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
> +{
> +	int rc;
> +
> +	rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_COMP_CMD, 0);
> +	if (rc != H_SUCCESS)
> +		dev_err(ibmvtpm->dev,
> +			"ibmvtpm_crq_send_init_complete failed rc=%d\n", rc);
> +
> +	return rc;
> +}
> +
> +/**
> + * ibmvtpm_crq_send_init - Send a CRQ initialize message
> + * @ibmvtpm:	vtpm device struct
> + *
> + * Return value:
> + *	0 - Success
> + *	Non-zero - Failure
> + */
> +static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
> +{
> +	int rc;
> +
> +	rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_CMD, 0);
> +	if (rc != H_SUCCESS)
> +		dev_err(ibmvtpm->dev,
> +			"ibmvtpm_crq_send_init failed rc=%d\n", rc);
> +
> +	return rc;
> +}
> +
> +/**
> + * tpm_ibmvtpm_remove - ibm vtpm remove entry point
> + * @vdev:	vio device struct
> + *
> + * Return value:
> + *	0
> + */
> +static int __devexit tpm_ibmvtpm_remove(struct vio_dev *vdev)
> +{
> +	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
> +	int rc = 0;
> +
> +	free_irq(vdev->irq, ibmvtpm);
> +	tasklet_kill(&ibmvtpm->tasklet);
> +
> +	do {
> +		if (rc)
> +			msleep(100);
> +		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
> +	} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
> +
> +	dma_unmap_single(ibmvtpm->dev, ibmvtpm->crq_dma_handle,
> +			 CRQ_RES_BUF_SIZE, DMA_BIDIRECTIONAL);
> +	free_page((unsigned long)ibmvtpm->crq_queue.crq_addr);
> +
> +	if (ibmvtpm->rtce_buf) {
> +		dma_unmap_single(ibmvtpm->dev, ibmvtpm->rtce_dma_handle,
> +				 ibmvtpm->rtce_size, DMA_BIDIRECTIONAL);
> +		kfree(ibmvtpm->rtce_buf);
> +	}
> +
> +	tpm_remove_hardware(ibmvtpm->dev);
> +
> +	kfree(ibmvtpm);
> +
> +	return 0;
> +}
> +
> +/**
> + * tpm_ibmvtpm_get_desired_dma - Get DMA size needed by this driver
> + * @vdev:	vio device struct
> + *
> + * Return value:
> + *	Number of bytes the driver needs to DMA map
> + */
> +static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
> +{
> +	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
> +	return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size;
> +}
> +
> +/**
> + * tpm_ibmvtpm_suspend - Suspend
> + * @dev:	device struct
> + *
> + * Return value:
> + *	0
> + */
> +static int tpm_ibmvtpm_suspend(struct device *dev)
> +{
> +	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
> +	struct ibmvtpm_crq crq;
> +	u64 *buf = (u64 *) &crq;
> +	int rc = 0;
> +
> +	crq.valid = (u8)IBMVTPM_VALID_CMD;
> +	crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;
> +
> +	rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
> +	if (rc != H_SUCCESS)
> +		dev_err(ibmvtpm->dev,
> +			"tpm_ibmvtpm_suspend failed rc=%d\n", rc);
> +
> +	return rc;
> +}
> +
> +/**
> + * ibmvtpm_reset_crq - Reset CRQ
> + * @ibmvtpm:	ibm vtpm struct
> + *
> + * Return value:
> + *	0 - Success
> + *	Non-zero - Failure
> + */
> +static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
> +{
> +	int rc = 0;
> +
> +	do {
> +		if (rc)
> +			msleep(100);
> +		rc = plpar_hcall_norets(H_FREE_CRQ,
> +					ibmvtpm->vdev->unit_address);
> +	} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
> +
> +	memset(ibmvtpm->crq_queue.crq_addr, 0, CRQ_RES_BUF_SIZE);
> +	ibmvtpm->crq_queue.index = 0;
> +
> +	return plpar_hcall_norets(H_REG_CRQ, ibmvtpm->vdev->unit_address,
> +				  ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
> +}
> +
> +/**
> + * tpm_ibmvtpm_resume - Resume from suspend
> + * @dev:	device struct
> + *
> + * Return value:
> + *	0
> + */
> +static int tpm_ibmvtpm_resume(struct device *dev)
> +{
> +	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
> +	unsigned long flags;
> +	int rc = 0;
> +
> +	do {
> +		if (rc)
> +			msleep(100);
> +		rc = plpar_hcall_norets(H_ENABLE_CRQ,
> +					ibmvtpm->vdev->unit_address);
> +	} while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
> +
> +	if (rc) {
> +		dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
> +		return rc;
> +	}
> +
> +	spin_lock_irqsave(&ibmvtpm->lock, flags);
> +	vio_disable_interrupts(ibmvtpm->vdev);
> +	tasklet_schedule(&ibmvtpm->tasklet);
> +	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
> +
> +	rc = ibmvtpm_crq_send_init(ibmvtpm);
> +	if (rc)
> +		dev_err(dev, "Error send_init rc=%d\n", rc);
> +
> +	return rc;
> +}
> +
> +static const struct file_operations ibmvtpm_ops = {
> +	.owner = THIS_MODULE,
> +	.llseek = no_llseek,
> +	.open = tpm_open,
> +	.read = tpm_read,
> +	.write = tpm_write,
> +	.release = tpm_release,
> +};
> +
> +static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
> +static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
> +static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
> +static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
> +static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
> +static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
> +		   NULL);
> +static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
> +static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
> +static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
> +static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
> +
> +static struct attribute *ibmvtpm_attrs[] = {
> +	&dev_attr_pubek.attr,
> +	&dev_attr_pcrs.attr,
> +	&dev_attr_enabled.attr,
> +	&dev_attr_active.attr,
> +	&dev_attr_owned.attr,
> +	&dev_attr_temp_deactivated.attr,
> +	&dev_attr_caps.attr,
> +	&dev_attr_cancel.attr,
> +	&dev_attr_durations.attr,
> +	&dev_attr_timeouts.attr, NULL,
> +};
> +
> +static struct attribute_group ibmvtpm_attr_grp = { .attrs = ibmvtpm_attrs };
> +
> +static const struct tpm_vendor_specific tpm_ibmvtpm = {
> +	.recv = tpm_ibmvtpm_recv,
> +	.send = tpm_ibmvtpm_send,
> +	.cancel = tpm_ibmvtpm_cancel,
> +	.status = tpm_ibmvtpm_status,
> +	.req_complete_mask = 0,
> +	.req_complete_val = 0,
> +	.req_canceled = 0,
> +	.attr_group = &ibmvtpm_attr_grp,
> +	.miscdev = { .fops = &ibmvtpm_ops, },
> +};
> +
> +static const struct dev_pm_ops tpm_ibmvtpm_pm_ops = {
> +	.suspend = tpm_ibmvtpm_suspend,
> +	.resume = tpm_ibmvtpm_resume,
> +};
> +
> +/**
> + * ibmvtpm_crq_get_next - Get next responded crq
> + * @ibmvtpm	vtpm device struct
> + *
> + * Return value:
> + *	vtpm crq pointer
> + */
> +static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm)
> +{
> +	struct ibmvtpm_crq_queue *crq_q = &ibmvtpm->crq_queue;
> +	struct ibmvtpm_crq *crq = &crq_q->crq_addr[crq_q->index];
> +
> +	if (crq->valid & VTPM_MSG_RES) {
> +		if (++crq_q->index == crq_q->num_entry)
> +			crq_q->index = 0;
> +		rmb();
> +	} else
> +		crq = NULL;
> +	return crq;
> +}
> +
> +/**
> + * ibmvtpm_crq_process - Process responded crq
> + * @crq		crq to be processed
> + * @ibmvtpm	vtpm device struct
> + *
> + * Return value:
> + *	Nothing
> + */
> +static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
> +				struct ibmvtpm_dev *ibmvtpm)
> +{
> +	int rc = 0;
> +
> +	switch (crq->valid) {
> +	case VALID_INIT_CRQ:
> +		switch (crq->msg) {
> +		case INIT_CRQ_RES:
> +			dev_info(ibmvtpm->dev, "CRQ initialized\n");
> +			rc = ibmvtpm_crq_send_init_complete(ibmvtpm);
> +			if (rc)
> +				dev_err(ibmvtpm->dev, "Unable to send CRQ init complete rc=%d\n", rc);
> +			return;
> +		case INIT_CRQ_COMP_RES:
> +			dev_info(ibmvtpm->dev,
> +				 "CRQ initialization completed\n");
> +			return;
> +		default:
> +			dev_err(ibmvtpm->dev, "Unknown crq message type: %d\n", crq->msg);
> +			return;
> +		}
> +		return;
> +	case IBMVTPM_VALID_CMD:
> +		switch (crq->msg) {
> +		case VTPM_GET_RTCE_BUFFER_SIZE_RES:
> +			if (crq->len <= 0) {
> +				dev_err(ibmvtpm->dev, "Invalid rtce size\n");
> +				return;
> +			}
> +			ibmvtpm->rtce_size = crq->len;
> +			ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size,
> +						    GFP_KERNEL);
> +			if (!ibmvtpm->rtce_buf) {
> +				dev_err(ibmvtpm->dev, "Failed to allocate memory for rtce buffer\n");
> +				return;
> +			}
> +
> +			ibmvtpm->rtce_dma_handle = dma_map_single(ibmvtpm->dev,
> +				ibmvtpm->rtce_buf, ibmvtpm->rtce_size,
> +				DMA_BIDIRECTIONAL);
> +
> +			if (dma_mapping_error(ibmvtpm->dev,
> +					      ibmvtpm->rtce_dma_handle)) {
> +				kfree(ibmvtpm->rtce_buf);
> +				ibmvtpm->rtce_buf = NULL;
> +				dev_err(ibmvtpm->dev, "Failed to dma map rtce buffer\n");
> +			}
> +
> +			return;
> +		case VTPM_GET_VERSION_RES:
> +			ibmvtpm->vtpm_version = crq->data;
> +			return;
> +		case VTPM_TPM_COMMAND_RES:
> +			ibmvtpm->crq_res.valid = crq->valid;
> +			ibmvtpm->crq_res.msg = crq->msg;
> +			ibmvtpm->crq_res.len = crq->len;
> +			ibmvtpm->crq_res.data = crq->data;
> +			wake_up_interruptible(&wq);
> +			return;
> +		default:
> +			return;
> +		}
> +	}
> +	return;
> +}
> +
> +/**
> + * ibmvtpm_interrupt -	Interrupt handler
> + * @irq:		irq number to handle
> + * @vtpm_instance:	vtpm that received interrupt
> + *
> + * Returns:
> + *	IRQ_HANDLED
> + **/
> +static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance)
> +{
> +	struct ibmvtpm_dev *ibmvtpm = (struct ibmvtpm_dev *) vtpm_instance;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&ibmvtpm->lock, flags);
> +	vio_disable_interrupts(ibmvtpm->vdev);
> +	tasklet_schedule(&ibmvtpm->tasklet);
> +	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + * ibmvtpm_tasklet - Interrupt handler tasklet
> + * @data:	ibm vtpm device struct
> + *
> + * Returns:
> + *	Nothing
> + **/
> +static void ibmvtpm_tasklet(void *data)
> +{
> +	struct ibmvtpm_dev *ibmvtpm = data;
> +	struct ibmvtpm_crq *crq;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&ibmvtpm->lock, flags);
> +	while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) {
> +		ibmvtpm_crq_process(crq, ibmvtpm);
> +		crq->valid = 0;
> +		wmb();
> +	}
> +
> +	vio_enable_interrupts(ibmvtpm->vdev);
> +	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
> +}
> +
> +/**
> + * tpm_ibmvtpm_probe - ibm vtpm initialize entry point
> + * @vio_dev:	vio device struct
> + * @id:		vio device id struct
> + *
> + * Return value:
> + *	0 - Success
> + *	Non-zero - Failure
> + */
> +static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
> +				   const struct vio_device_id *id)
> +{
> +	struct ibmvtpm_dev *ibmvtpm;
> +	struct device *dev = &vio_dev->dev;
> +	struct ibmvtpm_crq_queue *crq_q;
> +	struct tpm_chip *chip;
> +	int rc = -ENOMEM, rc1;
> +
> +	chip = tpm_register_hardware(dev, &tpm_ibmvtpm);
> +	if (!chip) {
> +		dev_err(dev, "tpm_register_hardware failed\n");
> +		return -ENODEV;
> +	}
> +
> +	ibmvtpm = kzalloc(sizeof(struct ibmvtpm_dev), GFP_KERNEL);
> +	if (!ibmvtpm) {
> +		dev_err(dev, "kzalloc for ibmvtpm failed\n");
> +		goto cleanup;
> +	}
> +
> +	crq_q = &ibmvtpm->crq_queue;
> +	crq_q->crq_addr = (struct ibmvtpm_crq *)get_zeroed_page(GFP_KERNEL);
> +	if (!crq_q->crq_addr) {
> +		dev_err(dev, "Unable to allocate memory for crq_addr\n");
> +		goto cleanup;
> +	}
> +
> +	crq_q->num_entry = CRQ_RES_BUF_SIZE / sizeof(*crq_q->crq_addr);
> +	ibmvtpm->crq_dma_handle = dma_map_single(dev, crq_q->crq_addr,
> +						 CRQ_RES_BUF_SIZE,
> +						 DMA_BIDIRECTIONAL);
> +
> +	if (dma_mapping_error(dev, ibmvtpm->crq_dma_handle)) {
> +		dev_err(dev, "dma mapping failed\n");
> +		goto cleanup;
> +	}
> +
> +	rc = plpar_hcall_norets(H_REG_CRQ, vio_dev->unit_address,
> +				ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
> +	if (rc == H_RESOURCE)
> +		rc = ibmvtpm_reset_crq(ibmvtpm);
> +
> +	if (rc) {
> +		dev_err(dev, "Unable to register CRQ rc=%d\n", rc);
> +		goto reg_crq_cleanup;
> +	}
> +
> +	tasklet_init(&ibmvtpm->tasklet, (void *)ibmvtpm_tasklet,
> +		     (unsigned long)ibmvtpm);
> +
> +	rc = request_irq(vio_dev->irq, ibmvtpm_interrupt, 0,
> +			 tpm_ibmvtpm_driver_name, ibmvtpm);
> +	if (rc) {
> +		dev_err(dev, "Error %d register irq 0x%x\n", rc, vio_dev->irq);
> +		goto init_irq_cleanup;
> +	}
> +
> +	rc = vio_enable_interrupts(vio_dev);
> +	if (rc) {
> +		dev_err(dev, "Error %d enabling interrupts\n", rc);
> +		goto init_irq_cleanup;
> +	}
> +
> +	crq_q->index = 0;
> +
> +	ibmvtpm->dev = dev;
> +	ibmvtpm->vdev = vio_dev;
> +	chip->vendor.data = (void *)ibmvtpm;
> +
> +	spin_lock_init(&ibmvtpm->lock);
> +	spin_lock_init(&ibmvtpm->rtce_lock);
> +
> +	rc = ibmvtpm_crq_send_init(ibmvtpm);
> +	if (rc)
> +		goto init_irq_cleanup;
> +
> +	rc = ibmvtpm_crq_get_version(ibmvtpm);
> +	if (rc)
> +		goto init_irq_cleanup;
> +
> +	rc = ibmvtpm_crq_get_rtce_size(ibmvtpm);
> +	if (rc)
> +		goto init_irq_cleanup;
> +
> +	return rc;
> +init_irq_cleanup:
> +	tasklet_kill(&ibmvtpm->tasklet);
> +	do {
> +		rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address);
> +	} while (rc1 == H_BUSY || H_IS_LONG_BUSY(rc1));
> +reg_crq_cleanup:
> +	dma_unmap_single(dev, ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE,
> +			 DMA_BIDIRECTIONAL);
> +cleanup:
> +	if (ibmvtpm) {
> +		if (crq_q->crq_addr)
> +			free_page((unsigned long)crq_q->crq_addr);
> +		kfree(ibmvtpm);
> +	}
> +
> +	tpm_remove_hardware(dev);
> +
> +	return rc;
> +}
> +
> +static struct vio_driver ibmvtpm_driver = {
> +	.id_table	 = tpm_ibmvtpm_device_table,
> +	.probe		 = tpm_ibmvtpm_probe,
> +	.remove		 = tpm_ibmvtpm_remove,
> +	.get_desired_dma = tpm_ibmvtpm_get_desired_dma,
> +	.name		 = tpm_ibmvtpm_driver_name,
> +	.pm		 = &tpm_ibmvtpm_pm_ops,
> +};
> +
> +/**
> + * ibmvtpm_module_init - Initialize ibm vtpm module
> + *
> + * Return value:
> + *	0 -Success
> + *	Non-zero - Failure
> + */
> +static int __init ibmvtpm_module_init(void)
> +{
> +	return vio_register_driver(&ibmvtpm_driver);
> +}
> +
> +/**
> + * ibmvtpm_module_exit - Teardown ibm vtpm module
> + *
> + * Return value:
> + *	Nothing
> + */
> +static void __exit ibmvtpm_module_exit(void)
> +{
> +	vio_unregister_driver(&ibmvtpm_driver);
> +}
> +
> +module_init(ibmvtpm_module_init);
> +module_exit(ibmvtpm_module_exit);
> +
> +MODULE_AUTHOR("adlai@us.ibm.com");
> +MODULE_DESCRIPTION("IBM vTPM Driver");
> +MODULE_VERSION("1.0");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h
> new file mode 100644
> index 0000000..4296eb4
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_ibmvtpm.h
> @@ -0,0 +1,77 @@
> +/*
> + * Copyright (C) 2012 IBM Corporation
> + *
> + * Author: Ashley Lai <adlai@us.ibm.com>
> + *
> + * Maintained by: <tpmdd-devel@lists.sourceforge.net>
> + *
> + * Device driver for TCG/TCPA TPM (trusted platform module).
> + * Specifications at www.trustedcomputinggroup.org
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef __TPM_IBMVTPM_H__
> +#define __TPM_IBMVTPM_H__
> +
> +/* vTPM Message Format 1 */
> +struct ibmvtpm_crq {
> +	u8 valid;
> +	u8 msg;
> +	u16 len;
> +	u32 data;
> +	u64 reserved;
> +} __attribute__((packed, aligned(8)));
> +
> +struct ibmvtpm_crq_queue {
> +	struct ibmvtpm_crq *crq_addr;
> +	u32 index;
> +	u32 num_entry;
> +};
> +
> +struct ibmvtpm_dev {
> +	struct device *dev;
> +	struct vio_dev *vdev;
> +	struct ibmvtpm_crq_queue crq_queue;
> +	dma_addr_t crq_dma_handle;
> +	spinlock_t lock;
> +	struct tasklet_struct tasklet;
> +	u32 rtce_size;
> +	void __iomem *rtce_buf;
> +	dma_addr_t rtce_dma_handle;
> +	spinlock_t rtce_lock;
> +	struct ibmvtpm_crq crq_res;
> +	u32 vtpm_version;
> +};
> +
> +#define CRQ_RES_BUF_SIZE	PAGE_SIZE
> +
> +/* Initialize CRQ */
> +#define INIT_CRQ_CMD		0xC001000000000000LL /* Init cmd */
> +#define INIT_CRQ_COMP_CMD	0xC002000000000000LL /* Init complete cmd */
> +#define INIT_CRQ_RES		0x01	/* Init respond */
> +#define INIT_CRQ_COMP_RES	0x02	/* Init complete respond */
> +#define VALID_INIT_CRQ		0xC0	/* Valid command for init crq */
> +
> +/* vTPM CRQ response is the message type | 0x80 */
> +#define VTPM_MSG_RES		0x80
> +#define IBMVTPM_VALID_CMD	0x80
> +
> +/* vTPM CRQ message types */
> +#define VTPM_GET_VERSION			0x01
> +#define VTPM_GET_VERSION_RES			(0x01 | VTPM_MSG_RES)
> +
> +#define VTPM_TPM_COMMAND			0x02
> +#define VTPM_TPM_COMMAND_RES			(0x02 | VTPM_MSG_RES)
> +
> +#define VTPM_GET_RTCE_BUFFER_SIZE		0x03
> +#define VTPM_GET_RTCE_BUFFER_SIZE_RES		(0x03 | VTPM_MSG_RES)
> +
> +#define VTPM_PREPARE_TO_SUSPEND			0x04
> +#define VTPM_PREPARE_TO_SUSPEND_RES		(0x04 | VTPM_MSG_RES)
> +
> +#endif
> diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c
> new file mode 100644
> index 0000000..98ba2bd
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_of.c
> @@ -0,0 +1,73 @@
> +/*
> + * Copyright 2012 IBM Corporation
> + *
> + * Author: Ashley Lai <adlai@us.ibm.com>
> + *
> + * Maintained by: <tpmdd-devel@lists.sourceforge.net>
> + *
> + * Read the event log created by the firmware on PPC64
> + *
> + * 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; either version
> + * 2 of the License, or (at your option) any later version.
> + *
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/of.h>
> +
> +#include "tpm.h"
> +#include "tpm_eventlog.h"
> +
> +int read_log(struct tpm_bios_log *log)
> +{
> +	struct device_node *np;
> +	const u32 *sizep;
> +	const __be64 *basep;
> +
> +	if (log->bios_event_log != NULL) {
> +		pr_err("%s: ERROR - Eventlog already initialized\n", __func__);
> +		return -EFAULT;
> +	}
> +
> +	np = of_find_node_by_name(NULL, "ibm,vtpm");
> +	if (!np) {
> +		pr_err("%s: ERROR - IBMVTPM not supported\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	sizep = of_get_property(np, "linux,sml-size", NULL);
> +	if (sizep == NULL) {
> +		pr_err("%s: ERROR - SML size not found\n", __func__);
> +		goto cleanup_eio;
> +	}
> +	if (*sizep == 0) {
> +		pr_err("%s: ERROR - event log area empty\n", __func__);
> +		goto cleanup_eio;
> +	}
> +
> +	basep = of_get_property(np, "linux,sml-base", NULL);
> +	if (basep == NULL) {
> +		pr_err(KERN_ERR "%s: ERROR - SML not found\n", __func__);
> +		goto cleanup_eio;
> +	}
> +
> +	of_node_put(np);
> +	log->bios_event_log = kmalloc(*sizep, GFP_KERNEL);
> +	if (!log->bios_event_log) {
> +		pr_err("%s: ERROR - Not enough memory for BIOS measurements\n",
> +		       __func__);
> +		return -ENOMEM;
> +	}
> +
> +	log->bios_event_log_end = log->bios_event_log + *sizep;
> +
> +	memcpy(log->bios_event_log, __va(be64_to_cpup(basep)), *sizep);
> +
> +	return 0;
> +
> +cleanup_eio:
> +	of_node_put(np);
> +	return -EIO;
> +}
> diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
> new file mode 100644
> index 0000000..440fa1c
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_ppi.c
> @@ -0,0 +1,460 @@
> +#include <linux/acpi.h>
> +#include <acpi/acpi_drivers.h>
> +#include "tpm.h"
> +
> +static const u8 tpm_ppi_uuid[] = {
> +	0xA6, 0xFA, 0xDD, 0x3D,
> +	0x1B, 0x36,
> +	0xB4, 0x4E,
> +	0xA4, 0x24,
> +	0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53
> +};
> +static char *tpm_device_name = "TPM";
> +
> +#define TPM_PPI_REVISION_ID	1
> +#define TPM_PPI_FN_VERSION	1
> +#define TPM_PPI_FN_SUBREQ	2
> +#define TPM_PPI_FN_GETREQ	3
> +#define TPM_PPI_FN_GETACT	4
> +#define TPM_PPI_FN_GETRSP	5
> +#define TPM_PPI_FN_SUBREQ2	7
> +#define TPM_PPI_FN_GETOPR	8
> +#define PPI_TPM_REQ_MAX		22
> +#define PPI_VS_REQ_START	128
> +#define PPI_VS_REQ_END		255
> +#define PPI_VERSION_LEN		3
> +
> +static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
> +				void **return_value)
> +{
> +	acpi_status status;
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
> +	if (strstr(buffer.pointer, context) != NULL) {
> +		*return_value = handle;
> +		kfree(buffer.pointer);
> +		return AE_CTRL_TERMINATE;
> +	}
> +	return AE_OK;
> +}
> +
> +static inline void ppi_assign_params(union acpi_object params[4],
> +				     u64 function_num)
> +{
> +	params[0].type = ACPI_TYPE_BUFFER;
> +	params[0].buffer.length = sizeof(tpm_ppi_uuid);
> +	params[0].buffer.pointer = (char *)tpm_ppi_uuid;
> +	params[1].type = ACPI_TYPE_INTEGER;
> +	params[1].integer.value = TPM_PPI_REVISION_ID;
> +	params[2].type = ACPI_TYPE_INTEGER;
> +	params[2].integer.value = function_num;
> +	params[3].type = ACPI_TYPE_PACKAGE;
> +	params[3].package.count = 0;
> +	params[3].package.elements = NULL;
> +}
> +
> +ssize_t tpm_show_ppi_version(struct device *dev, struct device_attribute *attr,
> +			     char *buf)
> +{
> +	acpi_handle handle;
> +	acpi_status status;
> +	struct acpi_object_list input;
> +	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object params[4];
> +	union acpi_object *obj;
> +
> +	input.count = 4;
> +	ppi_assign_params(params, TPM_PPI_FN_VERSION);
> +	input.pointer = params;
> +	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
> +				     ACPI_UINT32_MAX, ppi_callback, NULL,
> +				     tpm_device_name, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -ENXIO;
> +
> +	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
> +					 ACPI_TYPE_STRING);
> +	if (ACPI_FAILURE(status))
> +		return -ENOMEM;
> +	obj = (union acpi_object *)output.pointer;
> +	status = scnprintf(buf, PAGE_SIZE, "%s\n", obj->string.pointer);
> +	kfree(output.pointer);
> +	return status;
> +}
> +
> +ssize_t tpm_show_ppi_request(struct device *dev,
> +			     struct device_attribute *attr,
> +			     char *buf)
> +{
> +	acpi_handle handle;
> +	acpi_status status;
> +	struct acpi_object_list input;
> +	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object params[4];
> +	union acpi_object *ret_obj;
> +
> +	input.count = 4;
> +	ppi_assign_params(params, TPM_PPI_FN_GETREQ);
> +	input.pointer = params;
> +	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
> +				     ACPI_UINT32_MAX, ppi_callback, NULL,
> +				     tpm_device_name, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -ENXIO;
> +
> +	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
> +					    ACPI_TYPE_PACKAGE);
> +	if (ACPI_FAILURE(status))
> +		return -ENOMEM;
> +	/*
> +	 * output.pointer should be of package type, including two integers.
> +	 * The first is function return code, 0 means success and 1 means
> +	 * error. The second is pending TPM operation requested by the OS, 0
> +	 * means none and >0 means operation value.
> +	 */
> +	ret_obj = ((union acpi_object *)output.pointer)->package.elements;
> +	if (ret_obj->type == ACPI_TYPE_INTEGER) {
> +		if (ret_obj->integer.value) {
> +			status = -EFAULT;
> +			goto cleanup;
> +		}
> +		ret_obj++;
> +		if (ret_obj->type == ACPI_TYPE_INTEGER)
> +			status = scnprintf(buf, PAGE_SIZE, "%llu\n",
> +					   ret_obj->integer.value);
> +		else
> +			status = -EINVAL;
> +	} else {
> +		status = -EINVAL;
> +	}
> +cleanup:
> +	kfree(output.pointer);
> +	return status;
> +}
> +
> +ssize_t tpm_store_ppi_request(struct device *dev,
> +			      struct device_attribute *attr,
> +			      const char *buf, size_t count)
> +{
> +	char version[PPI_VERSION_LEN + 1];
> +	acpi_handle handle;
> +	acpi_status status;
> +	struct acpi_object_list input;
> +	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object params[4];
> +	union acpi_object obj;
> +	u32 req;
> +	u64 ret;
> +
> +	input.count = 4;
> +	ppi_assign_params(params, TPM_PPI_FN_VERSION);
> +	input.pointer = params;
> +	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
> +				     ACPI_UINT32_MAX, ppi_callback, NULL,
> +				     tpm_device_name, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -ENXIO;
> +
> +	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
> +					    ACPI_TYPE_STRING);
> +	if (ACPI_FAILURE(status))
> +		return -ENOMEM;
> +	strncpy(version,
> +		((union acpi_object *)output.pointer)->string.pointer,
> +		PPI_VERSION_LEN);
> +	kfree(output.pointer);
> +	output.length = ACPI_ALLOCATE_BUFFER;
> +	output.pointer = NULL;
> +	/*
> +	 * the function to submit TPM operation request to pre-os environment
> +	 * is updated with function index from SUBREQ to SUBREQ2 since PPI
> +	 * version 1.1
> +	 */
> +	if (strcmp(version, "1.1") == -1)
> +		params[2].integer.value = TPM_PPI_FN_SUBREQ;
> +	else
> +		params[2].integer.value = TPM_PPI_FN_SUBREQ2;
> +	/*
> +	 * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS
> +	 * accept buffer/string/integer type, but some BIOS accept buffer/
> +	 * 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.
> +	 */
> +	if (strcmp(version, "1.2") == -1) {
> +		params[3].type = ACPI_TYPE_BUFFER;
> +		params[3].buffer.length = sizeof(req);
> +		sscanf(buf, "%d", &req);
> +		params[3].buffer.pointer = (char *)&req;
> +	} else {
> +		params[3].package.count = 1;
> +		obj.type = ACPI_TYPE_INTEGER;
> +		sscanf(buf, "%llu", &obj.integer.value);
> +		params[3].package.elements = &obj;
> +	}
> +
> +	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
> +					    ACPI_TYPE_INTEGER);
> +	if (ACPI_FAILURE(status))
> +		return -ENOMEM;
> +	ret = ((union acpi_object *)output.pointer)->integer.value;
> +	if (ret == 0)
> +		status = (acpi_status)count;
> +	else if (ret == 1)
> +		status = -EPERM;
> +	else
> +		status = -EFAULT;
> +	kfree(output.pointer);
> +	return status;
> +}
> +
> +ssize_t tpm_show_ppi_transition_action(struct device *dev,
> +				       struct device_attribute *attr,
> +				       char *buf)
> +{
> +	char version[PPI_VERSION_LEN + 1];
> +	acpi_handle handle;
> +	acpi_status status;
> +	struct acpi_object_list input;
> +	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object params[4];
> +	u32 ret;
> +	char *info[] = {
> +		"None",
> +		"Shutdown",
> +		"Reboot",
> +		"OS Vendor-specific",
> +		"Error",
> +	};
> +	input.count = 4;
> +	ppi_assign_params(params, TPM_PPI_FN_VERSION);
> +	input.pointer = params;
> +	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
> +				     ACPI_UINT32_MAX, ppi_callback, NULL,
> +				     tpm_device_name, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -ENXIO;
> +
> +	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
> +					    ACPI_TYPE_STRING);
> +	if (ACPI_FAILURE(status))
> +		return -ENOMEM;
> +	strncpy(version,
> +		((union acpi_object *)output.pointer)->string.pointer,
> +		PPI_VERSION_LEN);
> +	/*
> +	 * PPI spec defines params[3].type as empty package, but some platforms
> +	 * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
> +	 * compatibility, define params[3].type as buffer, if PPI version < 1.2
> +	 */
> +	if (strcmp(version, "1.2") == -1) {
> +		params[3].type = ACPI_TYPE_BUFFER;
> +		params[3].buffer.length =  0;
> +		params[3].buffer.pointer = NULL;
> +	}
> +	params[2].integer.value = TPM_PPI_FN_GETACT;
> +	kfree(output.pointer);
> +	output.length = ACPI_ALLOCATE_BUFFER;
> +	output.pointer = NULL;
> +	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
> +					    ACPI_TYPE_INTEGER);
> +	if (ACPI_FAILURE(status))
> +		return -ENOMEM;
> +	ret = ((union acpi_object *)output.pointer)->integer.value;
> +	if (ret < ARRAY_SIZE(info) - 1)
> +		status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, info[ret]);
> +	else
> +		status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret,
> +				   info[ARRAY_SIZE(info)-1]);
> +	kfree(output.pointer);
> +	return status;
> +}
> +
> +ssize_t tpm_show_ppi_response(struct device *dev,
> +			      struct device_attribute *attr,
> +			      char *buf)
> +{
> +	acpi_handle handle;
> +	acpi_status status;
> +	struct acpi_object_list input;
> +	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object params[4];
> +	union acpi_object *ret_obj;
> +	u64 req;
> +
> +	input.count = 4;
> +	ppi_assign_params(params, TPM_PPI_FN_GETRSP);
> +	input.pointer = params;
> +	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
> +				     ACPI_UINT32_MAX, ppi_callback, NULL,
> +				     tpm_device_name, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -ENXIO;
> +
> +	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
> +					    ACPI_TYPE_PACKAGE);
> +	if (ACPI_FAILURE(status))
> +		return -ENOMEM;
> +	/*
> +	 * parameter output.pointer should be of package type, including
> +	 * 3 integers. The first means function return code, the second means
> +	 * most recent TPM operation request, and the last means response to
> +	 * the most recent TPM operation request. Only if the first is 0, and
> +	 * the second integer is not 0, the response makes sense.
> +	 */
> +	ret_obj = ((union acpi_object *)output.pointer)->package.elements;
> +	if (ret_obj->type != ACPI_TYPE_INTEGER) {
> +		status = -EINVAL;
> +		goto cleanup;
> +	}
> +	if (ret_obj->integer.value) {
> +		status = -EFAULT;
> +		goto cleanup;
> +	}
> +	ret_obj++;
> +	if (ret_obj->type != ACPI_TYPE_INTEGER) {
> +		status = -EINVAL;
> +		goto cleanup;
> +	}
> +	if (ret_obj->integer.value) {
> +		req = ret_obj->integer.value;
> +		ret_obj++;
> +		if (ret_obj->type != ACPI_TYPE_INTEGER) {
> +			status = -EINVAL;
> +			goto cleanup;
> +		}
> +		if (ret_obj->integer.value == 0)
> +			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
> +					   "0: Success");
> +		else if (ret_obj->integer.value == 0xFFFFFFF0)
> +			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
> +					   "0xFFFFFFF0: User Abort");
> +		else if (ret_obj->integer.value == 0xFFFFFFF1)
> +			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
> +					   "0xFFFFFFF1: BIOS Failure");
> +		else if (ret_obj->integer.value >= 1 &&
> +			 ret_obj->integer.value <= 0x00000FFF)
> +			status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
> +					   req, ret_obj->integer.value,
> +					   "Corresponding TPM error");
> +		else
> +			status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
> +					   req, ret_obj->integer.value,
> +					   "Error");
> +	} else {
> +		status = scnprintf(buf, PAGE_SIZE, "%llu: %s\n",
> +				   ret_obj->integer.value, "No Recent Request");
> +	}
> +cleanup:
> +	kfree(output.pointer);
> +	return status;
> +}
> +
> +static ssize_t show_ppi_operations(char *buf, u32 start, u32 end)
> +{
> +	char *str = buf;
> +	char version[PPI_VERSION_LEN];
> +	acpi_handle handle;
> +	acpi_status status;
> +	struct acpi_object_list input;
> +	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object params[4];
> +	union acpi_object obj;
> +	int i;
> +	u32 ret;
> +	char *info[] = {
> +		"Not implemented",
> +		"BIOS only",
> +		"Blocked for OS by BIOS",
> +		"User required",
> +		"User not required",
> +	};
> +	input.count = 4;
> +	ppi_assign_params(params, TPM_PPI_FN_VERSION);
> +	input.pointer = params;
> +	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
> +				     ACPI_UINT32_MAX, ppi_callback, NULL,
> +				     tpm_device_name, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -ENXIO;
> +
> +	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
> +					 ACPI_TYPE_STRING);
> +	if (ACPI_FAILURE(status))
> +		return -ENOMEM;
> +
> +	strncpy(version,
> +		((union acpi_object *)output.pointer)->string.pointer,
> +		PPI_VERSION_LEN);
> +	kfree(output.pointer);
> +	output.length = ACPI_ALLOCATE_BUFFER;
> +	output.pointer = NULL;
> +	if (strcmp(version, "1.2") == -1)
> +		return -EPERM;
> +
> +	params[2].integer.value = TPM_PPI_FN_GETOPR;
> +	params[3].package.count = 1;
> +	obj.type = ACPI_TYPE_INTEGER;
> +	params[3].package.elements = &obj;
> +	for (i = start; i <= end; i++) {
> +		obj.integer.value = i;
> +		status = acpi_evaluate_object_typed(handle, "_DSM",
> +			 &input, &output, ACPI_TYPE_INTEGER);
> +		if (ACPI_FAILURE(status))
> +			return -ENOMEM;
> +
> +		ret = ((union acpi_object *)output.pointer)->integer.value;
> +		if (ret > 0 && ret < ARRAY_SIZE(info))
> +			str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n",
> +					 i, ret, info[ret]);
> +		kfree(output.pointer);
> +		output.length = ACPI_ALLOCATE_BUFFER;
> +		output.pointer = NULL;
> +	}
> +	return str - buf;
> +}
> +
> +ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
> +				   struct device_attribute *attr, char *buf)
> +{
> +	return show_ppi_operations(buf, 0, PPI_TPM_REQ_MAX);
> +}
> +
> +ssize_t tpm_show_ppi_vs_operations(struct device *dev,
> +				  struct device_attribute *attr, char *buf)
> +{
> +	return show_ppi_operations(buf, PPI_VS_REQ_START, PPI_VS_REQ_END);
> +}
> +
> +static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
> +static DEVICE_ATTR(request, S_IRUGO | S_IWUSR | S_IWGRP,
> +		   tpm_show_ppi_request, tpm_store_ppi_request);
> +static DEVICE_ATTR(transition_action, S_IRUGO,
> +		   tpm_show_ppi_transition_action, NULL);
> +static DEVICE_ATTR(response, S_IRUGO, tpm_show_ppi_response, NULL);
> +static DEVICE_ATTR(tcg_operations, S_IRUGO, tpm_show_ppi_tcg_operations, NULL);
> +static DEVICE_ATTR(vs_operations, S_IRUGO, tpm_show_ppi_vs_operations, NULL);
> +
> +static struct attribute *ppi_attrs[] = {
> +	&dev_attr_version.attr,
> +	&dev_attr_request.attr,
> +	&dev_attr_transition_action.attr,
> +	&dev_attr_response.attr,
> +	&dev_attr_tcg_operations.attr,
> +	&dev_attr_vs_operations.attr, NULL,
> +};
> +static struct attribute_group ppi_attr_grp = {
> +	.attrs = ppi_attrs
> +};
> +
> +ssize_t sys_add_ppi(struct kobject *parent)
> +{
> +	struct kobject *ppi;
> +	ppi = kobject_create_and_add("ppi", parent);
> +	if (sysfs_create_group(ppi, &ppi_attr_grp))
> +		return -EFAULT;
> +	else
> +		return 0;
> +}
> +EXPORT_SYMBOL_GPL(sys_add_ppi);
> +
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> index c4be351..6bdf267 100644
> --- a/drivers/char/tpm/tpm_tis.c
> +++ b/drivers/char/tpm/tpm_tis.c
> @@ -705,6 +705,7 @@ out_err:
>  	return rc;
>  }
>  
> +#if defined(CONFIG_PNP) || defined(CONFIG_PM_SLEEP)
>  static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
>  {
>  	u32 intmask;
> @@ -725,7 +726,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
>  	iowrite32(intmask,
>  		  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
>  }
> -
> +#endif
>  
>  #ifdef CONFIG_PNP
>  static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
> diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> index fdc718a..fcb627f 100644
> --- a/include/linux/tpm.h
> +++ b/include/linux/tpm.h
> @@ -32,6 +32,7 @@
>  extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
>  extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
>  extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
> +extern int tpm_get_random(u32 chip_num, u8 *data, size_t max);
>  #else
>  static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
>  	return -ENODEV;
> @@ -42,5 +43,8 @@ static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
>  static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) {
>  	return -ENODEV;
>  }
> +static inline int tpm_get_random(u32 chip_num, u8 *data, size_t max) {
> +	return -ENODEV;
> +}
>  #endif
>  #endif
> diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> index b9c1219..809ccf1 100644
> --- a/security/integrity/ima/Kconfig
> +++ b/security/integrity/ima/Kconfig
> @@ -11,6 +11,7 @@ config IMA
>  	select CRYPTO_SHA1
>  	select TCG_TPM if HAS_IOMEM && !UML
>  	select TCG_TIS if TCG_TPM && X86
> +	select TCG_IBMVTPM if TCG_TPM && PPC64
>  	help
>  	  The Trusted Computing Group(TCG) runtime Integrity
>  	  Measurement Architecture(IMA) maintains a list of hash
> diff --git a/security/keys/trusted.c b/security/keys/trusted.c
> index 2d5d041..3f163d0 100644
> --- a/security/keys/trusted.c
> +++ b/security/keys/trusted.c
> @@ -369,38 +369,6 @@ static int trusted_tpm_send(const u32 chip_num, unsigned char *cmd,
>  }
>  
>  /*
> - * get a random value from TPM
> - */
> -static int tpm_get_random(struct tpm_buf *tb, unsigned char *buf, uint32_t len)
> -{
> -	int ret;
> -
> -	INIT_BUF(tb);
> -	store16(tb, TPM_TAG_RQU_COMMAND);
> -	store32(tb, TPM_GETRANDOM_SIZE);
> -	store32(tb, TPM_ORD_GETRANDOM);
> -	store32(tb, len);
> -	ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data);
> -	if (!ret)
> -		memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len);
> -	return ret;
> -}
> -
> -static int my_get_random(unsigned char *buf, int len)
> -{
> -	struct tpm_buf *tb;
> -	int ret;
> -
> -	tb = kmalloc(sizeof *tb, GFP_KERNEL);
> -	if (!tb)
> -		return -ENOMEM;
> -	ret = tpm_get_random(tb, buf, len);
> -
> -	kfree(tb);
> -	return ret;
> -}
> -
> -/*
>   * Lock a trusted key, by extending a selected PCR.
>   *
>   * Prevents a trusted key that is sealed to PCRs from being accessed.
> @@ -413,8 +381,8 @@ static int pcrlock(const int pcrnum)
>  
>  	if (!capable(CAP_SYS_ADMIN))
>  		return -EPERM;
> -	ret = my_get_random(hash, SHA1_DIGEST_SIZE);
> -	if (ret < 0)
> +	ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE);
> +	if (ret != SHA1_DIGEST_SIZE)
>  		return ret;
>  	return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0;
>  }
> @@ -429,8 +397,8 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
>  	unsigned char ononce[TPM_NONCE_SIZE];
>  	int ret;
>  
> -	ret = tpm_get_random(tb, ononce, TPM_NONCE_SIZE);
> -	if (ret < 0)
> +	ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE);
> +	if (ret != TPM_NONCE_SIZE)
>  		return ret;
>  
>  	INIT_BUF(tb);
> @@ -524,8 +492,8 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
>  	if (ret < 0)
>  		goto out;
>  
> -	ret = tpm_get_random(tb, td->nonceodd, TPM_NONCE_SIZE);
> -	if (ret < 0)
> +	ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE);
> +	if (ret != TPM_NONCE_SIZE)
>  		goto out;
>  	ordinal = htonl(TPM_ORD_SEAL);
>  	datsize = htonl(datalen);
> @@ -634,8 +602,8 @@ static int tpm_unseal(struct tpm_buf *tb,
>  
>  	ordinal = htonl(TPM_ORD_UNSEAL);
>  	keyhndl = htonl(SRKHANDLE);
> -	ret = tpm_get_random(tb, nonceodd, TPM_NONCE_SIZE);
> -	if (ret < 0) {
> +	ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE);
> +	if (ret != TPM_NONCE_SIZE) {
>  		pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
>  		return ret;
>  	}
> @@ -935,6 +903,7 @@ static int trusted_instantiate(struct key *key, const void *data,
>  	char *datablob;
>  	int ret = 0;
>  	int key_cmd;
> +	size_t key_len;
>  
>  	if (datalen <= 0 || datalen > 32767 || !data)
>  		return -EINVAL;
> @@ -974,8 +943,9 @@ static int trusted_instantiate(struct key *key, const void *data,
>  			pr_info("trusted_key: key_unseal failed (%d)\n", ret);
>  		break;
>  	case Opt_new:
> -		ret = my_get_random(payload->key, payload->key_len);
> -		if (ret < 0) {
> +		key_len = payload->key_len;
> +		ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len);
> +		if (ret != key_len) {
>  			pr_info("trusted_key: key_create failed (%d)\n", ret);
>  			goto out;
>  		}
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-23 20:32 ` James Morris
@ 2012-08-24  7:27   ` Peter.Huewe
  2012-08-24  8:32   ` Peter.Huewe
  1 sibling, 0 replies; 14+ messages in thread
From: Peter.Huewe @ 2012-08-24  7:27 UTC (permalink / raw)
  To: jmorris, key
  Cc: linux-kernel, linux-security-module, tpmdd-devel, adlai,
	xiaoyan.zhang, jj

> From: James Morris [mailto:jmorris@namei.org] 
> I'm getting this error when building i2c as a module
> WARNING: "__i2c_transfer" [drivers/char/tpm/tpm_i2c_infineon.ko] undefined!

This is unconditionally (except I2C) available in Linus' master tree.
And was introduced by b37d2a3a75cb in June by Jean Delvare.

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b37d2a3a75cb0e72e18c29336cb2095b63dabfc8

It was tested here against Linus' tree at time of submission.

Thanks,
Peter

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-23 20:32 ` James Morris
  2012-08-24  7:27   ` Peter.Huewe
@ 2012-08-24  8:32   ` Peter.Huewe
  2012-08-24 15:05     ` Kent Yoder
  1 sibling, 1 reply; 14+ messages in thread
From: Peter.Huewe @ 2012-08-24  8:32 UTC (permalink / raw)
  To: jmorris, key
  Cc: linux-kernel, linux-security-module, tpmdd-devel, adlai,
	xiaoyan.zhang, jj

>> From: James Morris [mailto:jmorris@namei.org] 
>> I'm getting this error when building i2c as a module
>> WARNING: "__i2c_transfer" [drivers/char/tpm/tpm_i2c_infineon.ko] undefined!

> This is unconditionally (except I2C) available in Linus' master tree.
> And was introduced by b37d2a3a75cb in June by Jean Delvare.

> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b37d2a3a75cb0e72e18c29336cb2095b63dabfc8

> It was tested here against Linus' tree at time of submission.

Did double check it against v3.6-rc3.
$ make ARCH=arm omap2plus_defconfig
$ make ARCH=arm menuconfig
-> deselected OMAP2_TYPICAL, which enables I2C to be builded as a module.
-> selected I2C as Module.
Build using make -> no error.

Thanks,
Peter




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-24  8:32   ` Peter.Huewe
@ 2012-08-24 15:05     ` Kent Yoder
  2012-08-24 22:02       ` James Morris
  0 siblings, 1 reply; 14+ messages in thread
From: Kent Yoder @ 2012-08-24 15:05 UTC (permalink / raw)
  To: Peter.Huewe
  Cc: jmorris, linux-kernel, linux-security-module, tpmdd-devel, adlai,
	xiaoyan.zhang, jj

On Fri, Aug 24, 2012 at 08:32:47AM +0000, Peter.Huewe@infineon.com wrote:
> >> From: James Morris [mailto:jmorris@namei.org] 
> >> I'm getting this error when building i2c as a module
> >> WARNING: "__i2c_transfer" [drivers/char/tpm/tpm_i2c_infineon.ko] undefined!
> 
> > This is unconditionally (except I2C) available in Linus' master tree.
> > And was introduced by b37d2a3a75cb in June by Jean Delvare.
> 
> > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b37d2a3a75cb0e72e18c29336cb2095b63dabfc8
> 
> > It was tested here against Linus' tree at time of submission.
> 
> Did double check it against v3.6-rc3.
> $ make ARCH=arm omap2plus_defconfig
> $ make ARCH=arm menuconfig
> -> deselected OMAP2_TYPICAL, which enables I2C to be builded as a module.
> -> selected I2C as Module.
> Build using make -> no error.

  I can't reproduce this either, James, can you send out your .config?

THanks,
Kent

> 
> Thanks,
> Peter
> 
> 
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-24 15:05     ` Kent Yoder
@ 2012-08-24 22:02       ` James Morris
  2012-08-27  7:23         ` Peter.Huewe
  0 siblings, 1 reply; 14+ messages in thread
From: James Morris @ 2012-08-24 22:02 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Peter.Huewe, linux-kernel, linux-security-module, tpmdd-devel,
	adlai, xiaoyan.zhang, jj

[-- Attachment #1: Type: TEXT/PLAIN, Size: 202 bytes --]

On Fri, 24 Aug 2012, Kent Yoder wrote:

> > Build using make -> no error.
> 
>   I can't reproduce this either, James, can you send out your .config?

See attached.

-- 
James Morris
<jmorris@namei.org>

[-- Attachment #2: Type: TEXT/plain, Size: 73956 bytes --]

#
# Automatically generated file; DO NOT EDIT.
# Linux/x86_64 3.6.0-rc2 Kernel Configuration
#
CONFIG_64BIT=y
# CONFIG_X86_32 is not set
CONFIG_X86_64=y
CONFIG_X86=y
CONFIG_INSTRUCTION_DECODER=y
CONFIG_OUTPUT_FORMAT="elf64-x86-64"
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_MMU=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_HAS_CPU_RELAX=y
CONFIG_ARCH_HAS_DEFAULT_IDLE=y
CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
CONFIG_ARCH_HAS_CPU_AUTOPROBE=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ZONE_DMA32=y
CONFIG_AUDIT_ARCH=y
CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_X86_64_SMP=y
CONFIG_X86_HT=y
CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11"
CONFIG_ARCH_CPU_PROBE_RELEASE=y
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_HAVE_IRQ_WORK=y
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_EXTABLE_SORT=y

#
# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_CROSS_COMPILE=""
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_BZIP2=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_KERNEL_LZO=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_BZIP2 is not set
# CONFIG_KERNEL_LZMA is not set
# CONFIG_KERNEL_XZ is not set
# CONFIG_KERNEL_LZO is not set
CONFIG_DEFAULT_HOSTNAME="(none)"
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_FHANDLE=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
CONFIG_AUDIT_WATCH=y
CONFIG_AUDIT_TREE=y
CONFIG_AUDIT_LOGINUID_IMMUTABLE=y
CONFIG_HAVE_GENERIC_HARDIRQS=y

#
# IRQ subsystem
#
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_PENDING_IRQ=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_SPARSE_IRQ=y
CONFIG_CLOCKSOURCE_WATCHDOG=y
CONFIG_ARCH_CLOCKSOURCE_DATA=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
CONFIG_GENERIC_CMOS_UPDATE=y

#
# Timers subsystem
#
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y

#
# RCU Subsystem
#
CONFIG_TREE_PREEMPT_RCU=y
CONFIG_PREEMPT_RCU=y
CONFIG_RCU_FANOUT=64
CONFIG_RCU_FANOUT_LEAF=16
# CONFIG_RCU_FANOUT_EXACT is not set
# CONFIG_RCU_FAST_NO_HZ is not set
CONFIG_TREE_RCU_TRACE=y
# CONFIG_RCU_BOOST is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=17
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
# CONFIG_CGROUP_FREEZER is not set
# CONFIG_CGROUP_DEVICE is not set
CONFIG_CPUSETS=y
CONFIG_PROC_PID_CPUSET=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_MEMCG_SWAP_ENABLED=y
CONFIG_MEMCG_KMEM=y
# CONFIG_CGROUP_HUGETLB is not set
# CONFIG_CGROUP_PERF is not set
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_CFS_BANDWIDTH is not set
# CONFIG_RT_GROUP_SCHED is not set
# CONFIG_BLK_CGROUP is not set
# CONFIG_CHECKPOINT_RESTORE is not set
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_MM_OWNER=y
# CONFIG_SYSFS_DEPRECATED is not set
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
CONFIG_RD_XZ=y
CONFIG_RD_LZO=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
# CONFIG_EXPERT is not set
CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_PCSPKR_PLATFORM=y
CONFIG_HAVE_PCSPKR_PLATFORM=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
# CONFIG_EMBEDDED is not set
CONFIG_HAVE_PERF_EVENTS=y

#
# Kernel Performance Events And Counters
#
CONFIG_PERF_EVENTS=y
# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_PROFILING is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_OPROFILE_NMI_TIMER=y
# CONFIG_KPROBES is not set
# CONFIG_JUMP_LABEL is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
CONFIG_HAVE_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
CONFIG_HAVE_CMPXCHG_LOCAL=y
CONFIG_HAVE_CMPXCHG_DOUBLE=y
CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y

#
# GCOV-based kernel profiling
#
# CONFIG_GCOV_KERNEL is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_BLK_DEV_BSG=y
# CONFIG_BLK_DEV_BSGLIB is not set
CONFIG_BLK_DEV_INTEGRITY=y

#
# Partition Types
#
CONFIG_PARTITION_ADVANCED=y
# CONFIG_ACORN_PARTITION is not set
# CONFIG_OSF_PARTITION is not set
# CONFIG_AMIGA_PARTITION is not set
# CONFIG_ATARI_PARTITION is not set
# CONFIG_MAC_PARTITION is not set
CONFIG_MSDOS_PARTITION=y
# CONFIG_BSD_DISKLABEL is not set
# CONFIG_MINIX_SUBPARTITION is not set
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
CONFIG_EFI_PARTITION=y
# CONFIG_SYSV68_PARTITION is not set
CONFIG_BLOCK_COMPAT=y

#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
# CONFIG_DEFAULT_DEADLINE is not set
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_PREEMPT_NOTIFIERS=y
# CONFIG_INLINE_SPIN_TRYLOCK is not set
# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
# CONFIG_INLINE_SPIN_LOCK is not set
# CONFIG_INLINE_SPIN_LOCK_BH is not set
# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
CONFIG_UNINLINE_SPIN_UNLOCK=y
# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
# CONFIG_INLINE_READ_TRYLOCK is not set
# CONFIG_INLINE_READ_LOCK is not set
# CONFIG_INLINE_READ_LOCK_BH is not set
# CONFIG_INLINE_READ_LOCK_IRQ is not set
# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
# CONFIG_INLINE_READ_UNLOCK is not set
# CONFIG_INLINE_READ_UNLOCK_BH is not set
# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
# CONFIG_INLINE_WRITE_TRYLOCK is not set
# CONFIG_INLINE_WRITE_LOCK is not set
# CONFIG_INLINE_WRITE_LOCK_BH is not set
# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
# CONFIG_INLINE_WRITE_UNLOCK is not set
# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
CONFIG_MUTEX_SPIN_ON_OWNER=y
# CONFIG_FREEZER is not set

#
# Processor type and features
#
CONFIG_ZONE_DMA=y
CONFIG_SMP=y
CONFIG_X86_MPPARSE=y
CONFIG_X86_EXTENDED_PLATFORM=y
# CONFIG_X86_VSMP is not set
CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
CONFIG_SCHED_OMIT_FRAME_POINTER=y
# CONFIG_PARAVIRT_GUEST is not set
CONFIG_NO_BOOTMEM=y
CONFIG_MEMTEST=y
CONFIG_MK8=y
# CONFIG_MPSC is not set
# CONFIG_MCORE2 is not set
# CONFIG_MATOM is not set
# CONFIG_GENERIC_CPU is not set
CONFIG_X86_INTERNODE_CACHE_SHIFT=6
CONFIG_X86_CMPXCHG=y
CONFIG_X86_L1_CACHE_SHIFT=6
CONFIG_X86_XADD=y
CONFIG_X86_WP_WORKS_OK=y
CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
CONFIG_X86_TSC=y
CONFIG_X86_CMPXCHG64=y
CONFIG_X86_CMOV=y
CONFIG_X86_MINIMUM_CPU_FAMILY=64
CONFIG_X86_DEBUGCTLMSR=y
CONFIG_CPU_SUP_INTEL=y
CONFIG_CPU_SUP_AMD=y
CONFIG_CPU_SUP_CENTAUR=y
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_DMI=y
CONFIG_GART_IOMMU=y
# CONFIG_CALGARY_IOMMU is not set
CONFIG_SWIOTLB=y
CONFIG_IOMMU_HELPER=y
# CONFIG_MAXSMP is not set
CONFIG_NR_CPUS=4
CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y
# CONFIG_IRQ_TIME_ACCOUNTING is not set
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
CONFIG_PREEMPT_COUNT=y
CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y
# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
CONFIG_X86_MCE=y
# CONFIG_X86_MCE_INTEL is not set
CONFIG_X86_MCE_AMD=y
CONFIG_X86_MCE_THRESHOLD=y
# CONFIG_X86_MCE_INJECT is not set
# CONFIG_I8K is not set
CONFIG_MICROCODE=m
# CONFIG_MICROCODE_INTEL is not set
CONFIG_MICROCODE_AMD=y
CONFIG_MICROCODE_OLD_INTERFACE=y
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_DIRECT_GBPAGES=y
CONFIG_NUMA=y
CONFIG_AMD_NUMA=y
CONFIG_X86_64_ACPI_NUMA=y
CONFIG_NODES_SPAN_OTHER_NODES=y
CONFIG_NUMA_EMU=y
CONFIG_NODES_SHIFT=3
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_PROC_KCORE_TEXT=y
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_SPARSEMEM_MANUAL=y
CONFIG_SPARSEMEM=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_COMPACTION is not set
CONFIG_MIGRATION=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_MMU_NOTIFIER=y
CONFIG_KSM=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
# CONFIG_MEMORY_FAILURE is not set
# CONFIG_TRANSPARENT_HUGEPAGE is not set
CONFIG_CROSS_MEMORY_ATTACH=y
# CONFIG_CLEANCACHE is not set
# CONFIG_FRONTSWAP is not set
# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
CONFIG_X86_RESERVE_LOW=64
CONFIG_MTRR=y
CONFIG_MTRR_SANITIZER=y
CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
CONFIG_X86_PAT=y
CONFIG_ARCH_USES_PG_UNCACHED=y
CONFIG_ARCH_RANDOM=y
CONFIG_EFI=y
# CONFIG_EFI_STUB is not set
# CONFIG_SECCOMP is not set
CONFIG_CC_STACKPROTECTOR=y
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
CONFIG_SCHED_HRTICK=y
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
CONFIG_PHYSICAL_START=0x1000000
CONFIG_RELOCATABLE=y
CONFIG_PHYSICAL_ALIGN=0x1000000
CONFIG_HOTPLUG_CPU=y
CONFIG_COMPAT_VDSO=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE=""
# CONFIG_CMDLINE_OVERRIDE is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_USE_PERCPU_NUMA_NODE_ID=y

#
# Power management and ACPI options
#
# CONFIG_SUSPEND is not set
# CONFIG_HIBERNATION is not set
# CONFIG_PM_RUNTIME is not set
CONFIG_ACPI=y
CONFIG_ACPI_PROCFS=y
CONFIG_ACPI_PROCFS_POWER=y
# CONFIG_ACPI_EC_DEBUGFS is not set
CONFIG_ACPI_PROC_EVENT=y
# CONFIG_ACPI_AC is not set
# CONFIG_ACPI_BATTERY is not set
# CONFIG_ACPI_BUTTON is not set
CONFIG_ACPI_FAN=y
CONFIG_ACPI_DOCK=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_HOTPLUG_CPU=y
# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
CONFIG_ACPI_THERMAL=y
CONFIG_ACPI_NUMA=y
# CONFIG_ACPI_CUSTOM_DSDT is not set
CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
# CONFIG_ACPI_PCI_SLOT is not set
CONFIG_X86_PM_TIMER=y
CONFIG_ACPI_CONTAINER=y
# CONFIG_ACPI_SBS is not set
# CONFIG_ACPI_HED is not set
# CONFIG_ACPI_CUSTOM_METHOD is not set
# CONFIG_ACPI_BGRT is not set
# CONFIG_ACPI_APEI is not set
# CONFIG_SFI is not set

#
# CPU Frequency scaling
#
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=m
CONFIG_CPU_FREQ_STAT=m
CONFIG_CPU_FREQ_STAT_DETAILS=y
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set

#
# x86 CPU frequency scaling drivers
#
# CONFIG_X86_PCC_CPUFREQ is not set
CONFIG_X86_ACPI_CPUFREQ=m
CONFIG_X86_POWERNOW_K8=m
# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
# CONFIG_X86_P4_CLOCKMOD is not set

#
# shared options
#
# CONFIG_X86_SPEEDSTEP_LIB is not set
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_LADDER=y
CONFIG_CPU_IDLE_GOV_MENU=y
# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
# CONFIG_INTEL_IDLE is not set

#
# Memory power savings
#
# CONFIG_I7300_IDLE is not set

#
# Bus options (PCI etc.)
#
CONFIG_PCI=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCI_CNB20LE_QUIRK is not set
CONFIG_PCIEPORTBUS=y
CONFIG_PCIEAER=y
# CONFIG_PCIE_ECRC is not set
# CONFIG_PCIEAER_INJECT is not set
CONFIG_PCIEASPM=y
# CONFIG_PCIEASPM_DEBUG is not set
CONFIG_PCIEASPM_DEFAULT=y
# CONFIG_PCIEASPM_POWERSAVE is not set
# CONFIG_PCIEASPM_PERFORMANCE is not set
CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y
# CONFIG_PCI_DEBUG is not set
CONFIG_PCI_REALLOC_ENABLE_AUTO=y
CONFIG_PCI_STUB=m
CONFIG_HT_IRQ=y
CONFIG_PCI_ATS=y
CONFIG_PCI_IOV=y
CONFIG_PCI_PRI=y
CONFIG_PCI_PASID=y
CONFIG_PCI_IOAPIC=y
CONFIG_PCI_LABEL=y
CONFIG_ISA_DMA_API=y
CONFIG_AMD_NB=y
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_RAPIDIO is not set

#
# Executable file formats / Emulations
#
CONFIG_BINFMT_ELF=y
CONFIG_COMPAT_BINFMT_ELF=y
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_IA32_EMULATION=y
CONFIG_IA32_AOUT=m
# CONFIG_X86_X32 is not set
CONFIG_COMPAT=y
CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
CONFIG_SYSVIPC_COMPAT=y
CONFIG_KEYS_COMPAT=y
CONFIG_HAVE_TEXT_POKE_SMP=y
CONFIG_X86_DEV_DMA_OPS=y
CONFIG_NET=y

#
# Networking options
#
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=m
CONFIG_XFRM=y
CONFIG_XFRM_ALGO=m
CONFIG_XFRM_USER=m
CONFIG_XFRM_SUB_POLICY=y
CONFIG_XFRM_MIGRATE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_XFRM_IPCOMP=m
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_FIB_TRIE_STATS=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_ROUTE_CLASSID=y
# CONFIG_IP_PNP is not set
CONFIG_NET_IPIP=m
CONFIG_NET_IPGRE_DEMUX=m
CONFIG_NET_IPGRE=m
CONFIG_NET_IPGRE_BROADCAST=y
CONFIG_IP_MROUTE=y
CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
# CONFIG_ARPD is not set
CONFIG_SYN_COOKIES=y
# CONFIG_NET_IPVTI is not set
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_XFRM_MODE_TRANSPORT=m
CONFIG_INET_XFRM_MODE_TUNNEL=m
CONFIG_INET_XFRM_MODE_BEET=m
CONFIG_INET_LRO=y
CONFIG_INET_DIAG=m
CONFIG_INET_TCP_DIAG=m
CONFIG_INET_UDP_DIAG=m
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_BIC=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_TCP_CONG_WESTWOOD=m
CONFIG_TCP_CONG_HTCP=m
CONFIG_TCP_CONG_HSTCP=m
CONFIG_TCP_CONG_HYBLA=m
CONFIG_TCP_CONG_VEGAS=m
CONFIG_TCP_CONG_SCALABLE=m
CONFIG_TCP_CONG_LP=m
CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_YEAH=m
CONFIG_TCP_CONG_ILLINOIS=m
CONFIG_DEFAULT_CUBIC=y
# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_TCP_MD5SIG=y
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
CONFIG_IPV6_MIP6=m
CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_INET6_XFRM_MODE_TRANSPORT=m
CONFIG_INET6_XFRM_MODE_TUNNEL=m
CONFIG_INET6_XFRM_MODE_BEET=m
CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
CONFIG_IPV6_SIT=m
CONFIG_IPV6_SIT_6RD=y
CONFIG_IPV6_NDISC_NODETYPE=y
CONFIG_IPV6_TUNNEL=m
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
CONFIG_IPV6_MROUTE=y
CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
CONFIG_IPV6_PIMSM_V2=y
CONFIG_NETLABEL=y
CONFIG_NETWORK_SECMARK=y
CONFIG_NETWORK_PHY_TIMESTAMPING=y
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
CONFIG_NETFILTER_ADVANCED=y
CONFIG_BRIDGE_NETFILTER=y

#
# Core Netfilter Configuration
#
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_ACCT=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_PROCFS=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_TIMEOUT=y
CONFIG_NF_CONNTRACK_TIMESTAMP=y
CONFIG_NF_CT_PROTO_DCCP=m
CONFIG_NF_CT_PROTO_GRE=m
CONFIG_NF_CT_PROTO_SCTP=m
CONFIG_NF_CT_PROTO_UDPLITE=m
CONFIG_NF_CONNTRACK_AMANDA=m
CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_H323=m
CONFIG_NF_CONNTRACK_IRC=m
CONFIG_NF_CONNTRACK_BROADCAST=m
CONFIG_NF_CONNTRACK_NETBIOS_NS=m
CONFIG_NF_CONNTRACK_SNMP=m
CONFIG_NF_CONNTRACK_PPTP=m
CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
CONFIG_NF_CT_NETLINK_TIMEOUT=m
# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set
# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m

#
# Xtables combined modules
#
CONFIG_NETFILTER_XT_MARK=m
CONFIG_NETFILTER_XT_CONNMARK=m
# CONFIG_NETFILTER_XT_SET is not set

#
# Xtables targets
#
CONFIG_NETFILTER_XT_TARGET_AUDIT=m
# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
# CONFIG_NETFILTER_XT_TARGET_CT is not set
# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
CONFIG_NETFILTER_XT_TARGET_HL=m
# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
CONFIG_NETFILTER_XT_TARGET_LOG=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TEE=m
# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set

#
# Xtables matches
#
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_CPU=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ECN=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
# CONFIG_NETFILTER_XT_MATCH_IPVS is not set
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_NFACCT=m
CONFIG_NETFILTER_XT_MATCH_OSF=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_RECENT=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
CONFIG_IP_SET=m
CONFIG_IP_SET_MAX=256
CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
CONFIG_IP_SET_HASH_NET=m
CONFIG_IP_SET_HASH_NETPORT=m
CONFIG_IP_SET_HASH_NETIFACE=m
CONFIG_IP_SET_LIST_SET=m
CONFIG_IP_VS=m
# CONFIG_IP_VS_IPV6 is not set
# CONFIG_IP_VS_DEBUG is not set
CONFIG_IP_VS_TAB_BITS=12

#
# IPVS transport protocol load balancing support
#
# CONFIG_IP_VS_PROTO_TCP is not set
# CONFIG_IP_VS_PROTO_UDP is not set
# CONFIG_IP_VS_PROTO_AH_ESP is not set
# CONFIG_IP_VS_PROTO_ESP is not set
# CONFIG_IP_VS_PROTO_AH is not set
# CONFIG_IP_VS_PROTO_SCTP is not set

#
# IPVS scheduler
#
# CONFIG_IP_VS_RR is not set
# CONFIG_IP_VS_WRR is not set
# CONFIG_IP_VS_LC is not set
# CONFIG_IP_VS_WLC is not set
# CONFIG_IP_VS_LBLC is not set
# CONFIG_IP_VS_LBLCR is not set
# CONFIG_IP_VS_DH is not set
# CONFIG_IP_VS_SH is not set
# CONFIG_IP_VS_SED is not set
# CONFIG_IP_VS_NQ is not set

#
# IPVS SH scheduler
#
CONFIG_IP_VS_SH_TAB_BITS=8

#
# IPVS application helper
#
# CONFIG_IP_VS_NFCT is not set

#
# IP: Netfilter Configuration
#
CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_RPFILTER=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_NETMAP=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_DCCP=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
CONFIG_NF_NAT_PROTO_SCTP=m
CONFIG_NF_NAT_FTP=m
CONFIG_NF_NAT_IRC=m
CONFIG_NF_NAT_TFTP=m
CONFIG_NF_NAT_AMANDA=m
CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_SECURITY=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m

#
# IPv6: Netfilter Configuration
#
CONFIG_NF_DEFRAG_IPV6=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RPFILTER=m
CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_SECURITY=m

#
# DECnet: Netfilter Configuration
#
# CONFIG_DECNET_NF_GRABULATOR is not set
# CONFIG_BRIDGE_NF_EBTABLES is not set
CONFIG_IP_DCCP=m
CONFIG_INET_DCCP_DIAG=m

#
# DCCP CCIDs Configuration (EXPERIMENTAL)
#
# CONFIG_IP_DCCP_CCID2_DEBUG is not set
CONFIG_IP_DCCP_CCID3=y
# CONFIG_IP_DCCP_CCID3_DEBUG is not set
CONFIG_IP_DCCP_TFRC_LIB=y

#
# DCCP Kernel Hacking
#
# CONFIG_IP_DCCP_DEBUG is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
# CONFIG_SCTP_HMAC_NONE is not set
# CONFIG_SCTP_HMAC_SHA1 is not set
CONFIG_SCTP_HMAC_MD5=y
CONFIG_RDS=m
CONFIG_RDS_TCP=m
# CONFIG_RDS_DEBUG is not set
CONFIG_TIPC=m
# CONFIG_TIPC_ADVANCED is not set
CONFIG_ATM=m
CONFIG_ATM_CLIP=m
# CONFIG_ATM_CLIP_NO_ICMP is not set
CONFIG_ATM_LANE=m
CONFIG_ATM_MPOA=m
CONFIG_ATM_BR2684=m
# CONFIG_ATM_BR2684_IPFILTER is not set
CONFIG_L2TP=m
# CONFIG_L2TP_DEBUGFS is not set
# CONFIG_L2TP_V3 is not set
CONFIG_STP=m
CONFIG_BRIDGE=m
CONFIG_BRIDGE_IGMP_SNOOPING=y
# CONFIG_NET_DSA is not set
CONFIG_VLAN_8021Q=m
# CONFIG_VLAN_8021Q_GVRP is not set
CONFIG_DECNET=m
# CONFIG_DECNET_ROUTER is not set
CONFIG_LLC=m
CONFIG_LLC2=m
CONFIG_IPX=m
# CONFIG_IPX_INTERN is not set
CONFIG_ATALK=m
CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y
CONFIG_IPDDP_DECAP=y
CONFIG_X25=m
CONFIG_LAPB=m
CONFIG_WAN_ROUTER=m
CONFIG_PHONET=m
CONFIG_IEEE802154=m
# CONFIG_IEEE802154_6LOWPAN is not set
# CONFIG_MAC802154 is not set
CONFIG_NET_SCHED=y

#
# Queueing/Scheduling
#
# CONFIG_NET_SCH_CBQ is not set
# CONFIG_NET_SCH_HTB is not set
# CONFIG_NET_SCH_HFSC is not set
# CONFIG_NET_SCH_ATM is not set
# CONFIG_NET_SCH_PRIO is not set
# CONFIG_NET_SCH_MULTIQ is not set
# CONFIG_NET_SCH_RED is not set
# CONFIG_NET_SCH_SFB is not set
# CONFIG_NET_SCH_SFQ is not set
# CONFIG_NET_SCH_TEQL is not set
# CONFIG_NET_SCH_TBF is not set
# CONFIG_NET_SCH_GRED is not set
# CONFIG_NET_SCH_DSMARK is not set
# CONFIG_NET_SCH_NETEM is not set
# CONFIG_NET_SCH_DRR is not set
# CONFIG_NET_SCH_MQPRIO is not set
# CONFIG_NET_SCH_CHOKE is not set
# CONFIG_NET_SCH_QFQ is not set
# CONFIG_NET_SCH_CODEL is not set
# CONFIG_NET_SCH_FQ_CODEL is not set
CONFIG_NET_SCH_PLUG=m

#
# Classification
#
# CONFIG_NET_CLS_BASIC is not set
# CONFIG_NET_CLS_TCINDEX is not set
# CONFIG_NET_CLS_ROUTE4 is not set
# CONFIG_NET_CLS_FW is not set
# CONFIG_NET_CLS_U32 is not set
# CONFIG_NET_CLS_RSVP is not set
# CONFIG_NET_CLS_RSVP6 is not set
# CONFIG_NET_CLS_FLOW is not set
# CONFIG_NET_CLS_CGROUP is not set
# CONFIG_NET_EMATCH is not set
# CONFIG_NET_CLS_ACT is not set
CONFIG_NET_SCH_FIFO=y
CONFIG_DCB=y
CONFIG_DNS_RESOLVER=m
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_BLA=y
CONFIG_BATMAN_ADV_DEBUG=y
CONFIG_OPENVSWITCH=m
CONFIG_RPS=y
CONFIG_RFS_ACCEL=y
CONFIG_XPS=y
CONFIG_NETPRIO_CGROUP=m
CONFIG_BQL=y
CONFIG_BPF_JIT=y

#
# Network testing
#
CONFIG_NET_PKTGEN=m
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
CONFIG_FIB_RULES=y
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
# CONFIG_CAIF is not set
CONFIG_CEPH_LIB=m
# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set
CONFIG_NFC=m
# CONFIG_NFC_NCI is not set
# CONFIG_NFC_HCI is not set
# CONFIG_NFC_LLCP is not set

#
# Near Field Communication (NFC) devices
#
# CONFIG_PN544_NFC is not set
CONFIG_HAVE_BPF_JIT=y

#
# Device Drivers
#

#
# Generic Driver Options
#
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_DEVTMPFS is not set
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_EXTRA_FIRMWARE=""
# CONFIG_DEBUG_DRIVER is not set
CONFIG_DEBUG_DEVRES=y
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_GENERIC_CPU_DEVICES is not set
# CONFIG_DMA_SHARED_BUFFER is not set
# CONFIG_CONNECTOR is not set
# CONFIG_MTD is not set
# CONFIG_PARPORT is not set
CONFIG_PNP=y
# CONFIG_PNP_DEBUG_MESSAGES is not set

#
# Protocols
#
CONFIG_PNPACPI=y
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
# CONFIG_BLK_DEV_CRYPTOLOOP is not set

#
# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
#
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_NVME is not set
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=16384
CONFIG_BLK_DEV_XIP=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
# CONFIG_VIRTIO_BLK is not set
# CONFIG_BLK_DEV_HD is not set
# CONFIG_BLK_DEV_RBD is not set

#
# Misc devices
#
# CONFIG_SENSORS_LIS3LV02D is not set
# CONFIG_AD525X_DPOT is not set
# CONFIG_IBM_ASM is not set
# CONFIG_PHANTOM is not set
# CONFIG_INTEL_MID_PTI is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
# CONFIG_APDS9802ALS is not set
# CONFIG_ISL29003 is not set
# CONFIG_ISL29020 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_SENSORS_BH1780 is not set
# CONFIG_SENSORS_BH1770 is not set
# CONFIG_SENSORS_APDS990X is not set
# CONFIG_HMC6352 is not set
# CONFIG_DS1682 is not set
# CONFIG_VMWARE_BALLOON is not set
# CONFIG_BMP085_I2C is not set
# CONFIG_PCH_PHUB is not set
# CONFIG_USB_SWITCH_FSA9480 is not set
# CONFIG_C2PORT is not set

#
# EEPROM support
#
# CONFIG_EEPROM_AT24 is not set
# CONFIG_EEPROM_LEGACY is not set
# CONFIG_EEPROM_MAX6875 is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_CB710_CORE is not set

#
# Texas Instruments shared transport line discipline
#
# CONFIG_SENSORS_LIS3_I2C is not set

#
# Altera FPGA firmware download module
#
# CONFIG_ALTERA_STAPL is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set

#
# SCSI device support
#
CONFIG_SCSI_MOD=y
CONFIG_RAID_ATTRS=y
CONFIG_SCSI=y
CONFIG_SCSI_DMA=y
CONFIG_SCSI_TGT=y
# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y

#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
# CONFIG_BLK_DEV_SR is not set
CONFIG_CHR_DEV_SG=y
# CONFIG_CHR_DEV_SCH is not set
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y

#
# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_ISCSI_BOOT_SYSFS is not set
# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_SCSI_CXGB4_ISCSI is not set
# CONFIG_SCSI_BNX2_ISCSI is not set
# CONFIG_SCSI_BNX2X_FCOE is not set
# CONFIG_BE2ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_HPSA is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_3W_SAS is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_MVSAS is not set
# CONFIG_SCSI_MVUMI is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_UFSHCD is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_VMWARE_PVSCSI is not set
# CONFIG_LIBFC is not set
# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_FCOE_FNIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_ISCI is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_PMCRAID is not set
# CONFIG_SCSI_PM8001 is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_BFA_FC is not set
# CONFIG_SCSI_VIRTIO is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_ATA_VERBOSE_ERROR=y
CONFIG_ATA_ACPI=y
CONFIG_SATA_PMP=y

#
# Controllers with non-SFF native interface
#
CONFIG_SATA_AHCI=y
# CONFIG_SATA_AHCI_PLATFORM is not set
# CONFIG_SATA_INIC162X is not set
# CONFIG_SATA_ACARD_AHCI is not set
# CONFIG_SATA_SIL24 is not set
CONFIG_ATA_SFF=y

#
# SFF controllers with custom DMA interface
#
# CONFIG_PDC_ADMA is not set
# CONFIG_SATA_QSTOR is not set
# CONFIG_SATA_SX4 is not set
CONFIG_ATA_BMDMA=y

#
# SATA SFF controllers with BMDMA
#
# CONFIG_ATA_PIIX is not set
# CONFIG_SATA_MV is not set
CONFIG_SATA_NV=m
# CONFIG_SATA_PROMISE is not set
# CONFIG_SATA_SIL is not set
# CONFIG_SATA_SIS is not set
# CONFIG_SATA_SVW is not set
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set

#
# PATA SFF controllers with BMDMA
#
# CONFIG_PATA_ALI is not set
CONFIG_PATA_AMD=m
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
# CONFIG_PATA_ATP867X is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
# CONFIG_PATA_CS5536 is not set
# CONFIG_PATA_CYPRESS is not set
# CONFIG_PATA_EFAR is not set
# CONFIG_PATA_HPT366 is not set
# CONFIG_PATA_HPT37X is not set
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
# CONFIG_PATA_IT8213 is not set
# CONFIG_PATA_IT821X is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_MARVELL is not set
# CONFIG_PATA_NETCELL is not set
# CONFIG_PATA_NINJA32 is not set
# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_OPTIDMA is not set
# CONFIG_PATA_PDC2027X is not set
# CONFIG_PATA_PDC_OLD is not set
# CONFIG_PATA_RADISYS is not set
# CONFIG_PATA_RDC is not set
# CONFIG_PATA_SC1200 is not set
# CONFIG_PATA_SCH is not set
# CONFIG_PATA_SERVERWORKS is not set
# CONFIG_PATA_SIL680 is not set
# CONFIG_PATA_SIS is not set
# CONFIG_PATA_TOSHIBA is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set

#
# PIO-only SFF controllers
#
# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_NS87410 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_RZ1000 is not set

#
# Generic fallback / legacy drivers
#
CONFIG_PATA_ACPI=m
CONFIG_ATA_GENERIC=m
# CONFIG_PATA_LEGACY is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_AUTODETECT=y
CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
# CONFIG_MD_RAID1 is not set
# CONFIG_MD_RAID10 is not set
# CONFIG_MD_RAID456 is not set
CONFIG_MD_MULTIPATH=m
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=y
CONFIG_DM_DEBUG=y
CONFIG_DM_BUFIO=m
# CONFIG_DM_CRYPT is not set
# CONFIG_DM_SNAPSHOT is not set
# CONFIG_DM_THIN_PROVISIONING is not set
# CONFIG_DM_MIRROR is not set
# CONFIG_DM_RAID is not set
# CONFIG_DM_ZERO is not set
# CONFIG_DM_MULTIPATH is not set
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
# CONFIG_DM_FLAKEY is not set
CONFIG_DM_VERITY=m
# CONFIG_TARGET_CORE is not set
# CONFIG_FUSION is not set

#
# IEEE 1394 (FireWire) support
#
# CONFIG_FIREWIRE is not set
# CONFIG_FIREWIRE_NOSY is not set
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
CONFIG_NET_CORE=y
# CONFIG_BONDING is not set
CONFIG_DUMMY=m
# CONFIG_EQUALIZER is not set
# CONFIG_NET_FC is not set
CONFIG_MII=m
CONFIG_IEEE802154_DRIVERS=m
# CONFIG_IEEE802154_FAKEHARD is not set
# CONFIG_NET_TEAM is not set
# CONFIG_MACVLAN is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
CONFIG_TUN=m
# CONFIG_VETH is not set
# CONFIG_VIRTIO_NET is not set
# CONFIG_ARCNET is not set
CONFIG_ATM_DRIVERS=y
# CONFIG_ATM_DUMMY is not set
# CONFIG_ATM_TCP is not set
# CONFIG_ATM_LANAI is not set
# CONFIG_ATM_ENI is not set
# CONFIG_ATM_FIRESTREAM is not set
# CONFIG_ATM_ZATM is not set
# CONFIG_ATM_NICSTAR is not set
# CONFIG_ATM_IDT77252 is not set
# CONFIG_ATM_AMBASSADOR is not set
# CONFIG_ATM_HORIZON is not set
# CONFIG_ATM_IA is not set
# CONFIG_ATM_FORE200E is not set
# CONFIG_ATM_HE is not set
# CONFIG_ATM_SOLOS is not set

#
# CAIF transport drivers
#
CONFIG_ETHERNET=y
CONFIG_NET_VENDOR_3COM=y
# CONFIG_VORTEX is not set
# CONFIG_TYPHOON is not set
CONFIG_NET_VENDOR_ADAPTEC=y
# CONFIG_ADAPTEC_STARFIRE is not set
CONFIG_NET_VENDOR_ALTEON=y
# CONFIG_ACENIC is not set
CONFIG_NET_VENDOR_AMD=y
# CONFIG_AMD8111_ETH is not set
# CONFIG_PCNET32 is not set
CONFIG_NET_VENDOR_ATHEROS=y
# CONFIG_ATL2 is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
# CONFIG_ATL1C is not set
CONFIG_NET_VENDOR_BROADCOM=y
# CONFIG_B44 is not set
CONFIG_BNX2=m
# CONFIG_CNIC is not set
CONFIG_TIGON3=m
# CONFIG_BNX2X is not set
CONFIG_NET_VENDOR_BROCADE=y
# CONFIG_BNA is not set
# CONFIG_NET_CALXEDA_XGMAC is not set
CONFIG_NET_VENDOR_CHELSIO=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_CHELSIO_T4 is not set
# CONFIG_CHELSIO_T4VF is not set
CONFIG_NET_VENDOR_CISCO=y
# CONFIG_ENIC is not set
# CONFIG_DNET is not set
CONFIG_NET_VENDOR_DEC=y
# CONFIG_NET_TULIP is not set
CONFIG_NET_VENDOR_DLINK=y
# CONFIG_DL2K is not set
# CONFIG_SUNDANCE is not set
CONFIG_NET_VENDOR_EMULEX=y
# CONFIG_BE2NET is not set
CONFIG_NET_VENDOR_EXAR=y
# CONFIG_S2IO is not set
# CONFIG_VXGE is not set
CONFIG_NET_VENDOR_HP=y
# CONFIG_HP100 is not set
CONFIG_NET_VENDOR_INTEL=y
# CONFIG_E100 is not set
# CONFIG_E1000 is not set
# CONFIG_E1000E is not set
# CONFIG_IGB is not set
# CONFIG_IGBVF is not set
# CONFIG_IXGB is not set
# CONFIG_IXGBE is not set
# CONFIG_IXGBEVF is not set
CONFIG_NET_VENDOR_I825XX=y
# CONFIG_ZNET is not set
# CONFIG_IP1000 is not set
# CONFIG_JME is not set
CONFIG_NET_VENDOR_MARVELL=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
CONFIG_NET_VENDOR_MELLANOX=y
# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
CONFIG_NET_VENDOR_MICREL=y
# CONFIG_KS8851_MLL is not set
# CONFIG_KSZ884X_PCI is not set
CONFIG_NET_VENDOR_MYRI=y
# CONFIG_MYRI10GE is not set
# CONFIG_FEALNX is not set
CONFIG_NET_VENDOR_NATSEMI=y
# CONFIG_NATSEMI is not set
# CONFIG_NS83820 is not set
CONFIG_NET_VENDOR_8390=y
# CONFIG_NE2K_PCI is not set
CONFIG_NET_VENDOR_NVIDIA=y
# CONFIG_FORCEDETH is not set
CONFIG_NET_VENDOR_OKI=y
# CONFIG_PCH_GBE is not set
# CONFIG_ETHOC is not set
# CONFIG_NET_PACKET_ENGINE is not set
CONFIG_NET_VENDOR_QLOGIC=y
# CONFIG_QLA3XXX is not set
# CONFIG_QLCNIC is not set
# CONFIG_QLGE is not set
# CONFIG_NETXEN_NIC is not set
CONFIG_NET_VENDOR_REALTEK=y
# CONFIG_8139CP is not set
# CONFIG_8139TOO is not set
# CONFIG_R8169 is not set
CONFIG_NET_VENDOR_RDC=y
# CONFIG_R6040 is not set
CONFIG_NET_VENDOR_SEEQ=y
# CONFIG_SEEQ8005 is not set
CONFIG_NET_VENDOR_SILAN=y
# CONFIG_SC92031 is not set
CONFIG_NET_VENDOR_SIS=y
# CONFIG_SIS900 is not set
# CONFIG_SIS190 is not set
# CONFIG_SFC is not set
CONFIG_NET_VENDOR_SMSC=y
# CONFIG_EPIC100 is not set
# CONFIG_SMSC9420 is not set
CONFIG_NET_VENDOR_STMICRO=y
# CONFIG_STMMAC_ETH is not set
CONFIG_NET_VENDOR_SUN=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NIU is not set
CONFIG_NET_VENDOR_TEHUTI=y
# CONFIG_TEHUTI is not set
CONFIG_NET_VENDOR_TI=y
# CONFIG_TLAN is not set
CONFIG_NET_VENDOR_VIA=y
# CONFIG_VIA_RHINE is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_NET_VENDOR_WIZNET=y
# CONFIG_WIZNET_W5100 is not set
# CONFIG_WIZNET_W5300 is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_NET_SB1000 is not set
CONFIG_PHYLIB=y

#
# MII PHY device drivers
#
# CONFIG_AMD_PHY is not set
# CONFIG_MARVELL_PHY is not set
# CONFIG_DAVICOM_PHY is not set
# CONFIG_QSEMI_PHY is not set
# CONFIG_LXT_PHY is not set
# CONFIG_CICADA_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
# CONFIG_BCM87XX_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
# CONFIG_NATIONAL_PHY is not set
# CONFIG_STE10XP is not set
# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_MICREL_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_WLAN is not set

#
# Enable WiMAX (Networking options) to see the WiMAX drivers
#
# CONFIG_WAN is not set
# CONFIG_VMXNET3 is not set
# CONFIG_ISDN is not set

#
# Input device support
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
CONFIG_INPUT_POLLDEV=m
# CONFIG_INPUT_SPARSEKMAP is not set
# CONFIG_INPUT_MATRIXKMAP is not set

#
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set

#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_ADP5588 is not set
# CONFIG_KEYBOARD_ADP5589 is not set
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_QT1070 is not set
# CONFIG_KEYBOARD_QT2160 is not set
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_TCA6416 is not set
# CONFIG_KEYBOARD_TCA8418 is not set
# CONFIG_KEYBOARD_LM8333 is not set
# CONFIG_KEYBOARD_MAX7359 is not set
# CONFIG_KEYBOARD_MCS is not set
# CONFIG_KEYBOARD_MPR121 is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_OPENCORES is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_OMAP4 is not set
# CONFIG_KEYBOARD_XTKBD is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_SENTELIC is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_MOUSE_SYNAPTICS_I2C is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_AD714X is not set
# CONFIG_INPUT_BMA150 is not set
CONFIG_INPUT_PCSPKR=m
# CONFIG_INPUT_MMA8450 is not set
# CONFIG_INPUT_MPU3050 is not set
# CONFIG_INPUT_ATLAS_BTNS is not set
# CONFIG_INPUT_KXTJ9 is not set
CONFIG_INPUT_UINPUT=m
# CONFIG_INPUT_PCF8574 is not set
# CONFIG_INPUT_ADXL34X is not set
# CONFIG_INPUT_CMA3000 is not set

#
# Hardware I/O ports
#
CONFIG_SERIO=y
CONFIG_SERIO_I8042=y
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PCIPS2 is not set
CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_RAW=m
# CONFIG_SERIO_ALTERA_PS2 is not set
# CONFIG_SERIO_PS2MULT is not set
# CONFIG_GAMEPORT is not set

#
# Character devices
#
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_NOZOMI is not set
# CONFIG_N_GSM is not set
# CONFIG_TRACE_SINK is not set
CONFIG_DEVKMEM=y

#
# Serial drivers
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_PNP=y
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
# CONFIG_SERIAL_8250_RSA is not set

#
# Non-8250 serial port support
#
# CONFIG_SERIAL_MFD_HSU is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_TIMBERDALE is not set
# CONFIG_SERIAL_ALTERA_JTAGUART is not set
# CONFIG_SERIAL_ALTERA_UART is not set
# CONFIG_SERIAL_PCH_UART is not set
# CONFIG_SERIAL_XILINX_PS_UART is not set
# CONFIG_VIRTIO_CONSOLE is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_MWAVE is not set
# CONFIG_RAW_DRIVER is not set
CONFIG_HPET=y
CONFIG_HPET_MMAP=y
# CONFIG_HANGCHECK_TIMER is not set
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS=y
CONFIG_TCG_TIS_I2C_INFINEON=m
CONFIG_TCG_NSC=m
CONFIG_TCG_ATMEL=m
CONFIG_TCG_INFINEON=m
# CONFIG_TELCLOCK is not set
CONFIG_DEVPORT=y
CONFIG_I2C=m
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_COMPAT=y
# CONFIG_I2C_CHARDEV is not set
# CONFIG_I2C_MUX is not set
# CONFIG_I2C_HELPER_AUTO is not set
# CONFIG_I2C_SMBUS is not set

#
# I2C Algorithms
#
CONFIG_I2C_ALGOBIT=m
# CONFIG_I2C_ALGOPCF is not set
# CONFIG_I2C_ALGOPCA is not set

#
# I2C Hardware Bus support
#

#
# PC SMBus host controller drivers
#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set

#
# ACPI drivers
#
# CONFIG_I2C_SCMI is not set

#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
# CONFIG_I2C_DESIGNWARE_PCI is not set
# CONFIG_I2C_EG20T is not set
# CONFIG_I2C_INTEL_MID is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PCA_PLATFORM is not set
# CONFIG_I2C_PXA_PCI is not set
# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_XILINX is not set

#
# External I2C/SMBus adapter drivers
#
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set

#
# Other I2C/SMBus bus drivers
#
# CONFIG_I2C_STUB is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_SPI is not set
# CONFIG_HSI is not set

#
# PPS support
#
# CONFIG_PPS is not set

#
# PPS generators support
#

#
# PTP clock support
#

#
# Enable Device Drivers -> PPS to see the PTP clock options.
#
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_POWER_AVS is not set
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
CONFIG_SSB_POSSIBLE=y

#
# Sonics Silicon Backplane
#
# CONFIG_SSB is not set
CONFIG_BCMA_POSSIBLE=y

#
# Broadcom specific AMBA
#
# CONFIG_BCMA is not set

#
# Multifunction device drivers
#
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_LM3533 is not set
# CONFIG_TPS6105X is not set
# CONFIG_TPS6507X is not set
# CONFIG_MFD_TPS65217 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_ARIZONA_I2C is not set
# CONFIG_MFD_PCF50633 is not set
# CONFIG_MFD_MC13XXX_I2C is not set
# CONFIG_ABX500_CORE is not set
# CONFIG_MFD_CS5535 is not set
# CONFIG_LPC_SCH is not set
# CONFIG_LPC_ICH is not set
# CONFIG_MFD_RDC321X is not set
# CONFIG_MFD_JANZ_CMODIO is not set
# CONFIG_MFD_VX855 is not set
# CONFIG_MFD_WL1273_CORE is not set
# CONFIG_REGULATOR is not set
# CONFIG_MEDIA_SUPPORT is not set

#
# Graphics support
#
# CONFIG_AGP is not set
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=16
# CONFIG_VGA_SWITCHEROO is not set
# CONFIG_DRM is not set
# CONFIG_STUB_POULSBO is not set
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
CONFIG_FB_BOOT_VESA_SUPPORT=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
# CONFIG_FB_FOREIGN_ENDIAN is not set
# CONFIG_FB_SYS_FOPS is not set
# CONFIG_FB_WMT_GE_ROPS is not set
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set

#
# Frame buffer hardware drivers
#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
# CONFIG_FB_ARC is not set
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
# CONFIG_FB_VGA16 is not set
CONFIG_FB_VESA=y
# CONFIG_FB_EFI is not set
# CONFIG_FB_N411 is not set
# CONFIG_FB_HGA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_I740 is not set
# CONFIG_FB_LE80578 is not set
# CONFIG_FB_MATROX is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_VIA is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
# CONFIG_FB_ARK is not set
# CONFIG_FB_PM3 is not set
# CONFIG_FB_CARMINE is not set
# CONFIG_FB_GEODE is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
# CONFIG_FB_BROADSHEET is not set
# CONFIG_FB_AUO_K190X is not set
# CONFIG_EXYNOS_VIDEO is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set

#
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
CONFIG_VGACON_SOFT_SCROLLBACK=y
CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
# CONFIG_LOGO is not set
# CONFIG_SOUND is not set

#
# HID support
#
CONFIG_HID=y
# CONFIG_HIDRAW is not set
# CONFIG_UHID is not set
CONFIG_HID_GENERIC=y

#
# Special HID drivers
#
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB_ARCH_HAS_XHCI=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
# CONFIG_RTC_DEBUG is not set

#
# RTC interfaces
#
CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
# CONFIG_RTC_DRV_TEST is not set

#
# I2C RTC drivers
#
# CONFIG_RTC_DRV_DS1307 is not set
# CONFIG_RTC_DRV_DS1374 is not set
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_DS3232 is not set
# CONFIG_RTC_DRV_MAX6900 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_ISL12022 is not set
# CONFIG_RTC_DRV_X1205 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_BQ32K is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
# CONFIG_RTC_DRV_RX8581 is not set
# CONFIG_RTC_DRV_RX8025 is not set
# CONFIG_RTC_DRV_EM3027 is not set
# CONFIG_RTC_DRV_RV3029C2 is not set

#
# SPI RTC drivers
#

#
# Platform RTC drivers
#
CONFIG_RTC_DRV_CMOS=y
# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
# CONFIG_RTC_DRV_MSM6242 is not set
# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_RP5C01 is not set
# CONFIG_RTC_DRV_V3020 is not set

#
# on-CPU RTC drivers
#
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_VFIO is not set
CONFIG_VIRTIO=m
CONFIG_VIRTIO_RING=m

#
# Virtio drivers
#
CONFIG_VIRTIO_PCI=m
CONFIG_VIRTIO_BALLOON=m
# CONFIG_VIRTIO_MMIO is not set

#
# Microsoft Hyper-V guest support
#
# CONFIG_HYPERV is not set
# CONFIG_STAGING is not set
CONFIG_X86_PLATFORM_DEVICES=y
# CONFIG_ACERHDF is not set
# CONFIG_ASUS_LAPTOP is not set
# CONFIG_DELL_WMI is not set
# CONFIG_DELL_WMI_AIO is not set
# CONFIG_FUJITSU_TABLET is not set
# CONFIG_HP_ACCEL is not set
# CONFIG_HP_WMI is not set
# CONFIG_THINKPAD_ACPI is not set
# CONFIG_SENSORS_HDAPS is not set
# CONFIG_INTEL_MENLOW is not set
CONFIG_ACPI_WMI=m
# CONFIG_TOPSTAR_LAPTOP is not set
# CONFIG_TOSHIBA_BT_RFKILL is not set
# CONFIG_ACPI_CMPC is not set
# CONFIG_INTEL_IPS is not set
# CONFIG_IBM_RTL is not set
# CONFIG_XO15_EBOOK is not set
# CONFIG_MXM_WMI is not set
# CONFIG_SAMSUNG_Q10 is not set
# CONFIG_APPLE_GMUX is not set

#
# Hardware Spinlock drivers
#
CONFIG_CLKEVT_I8253=y
CONFIG_I8253_LOCK=y
CONFIG_CLKBLD_I8253=y
CONFIG_IOMMU_API=y
CONFIG_IOMMU_SUPPORT=y
CONFIG_AMD_IOMMU=y
# CONFIG_AMD_IOMMU_STATS is not set
# CONFIG_INTEL_IOMMU is not set
# CONFIG_IRQ_REMAP is not set

#
# Remoteproc drivers (EXPERIMENTAL)
#

#
# Rpmsg drivers (EXPERIMENTAL)
#
# CONFIG_VIRT_DRIVERS is not set
# CONFIG_PM_DEVFREQ is not set
# CONFIG_EXTCON is not set
# CONFIG_MEMORY is not set
# CONFIG_IIO is not set
# CONFIG_VME_BUS is not set
# CONFIG_PWM is not set

#
# Firmware Drivers
#
CONFIG_EDD=m
# CONFIG_EDD_OFF is not set
CONFIG_FIRMWARE_MEMMAP=y
# CONFIG_EFI_VARS is not set
# CONFIG_DELL_RBU is not set
# CONFIG_DCDBAS is not set
CONFIG_DMIID=y
# CONFIG_DMI_SYSFS is not set
# CONFIG_ISCSI_IBFT_FIND is not set
# CONFIG_GOOGLE_FIRMWARE is not set

#
# File systems
#
CONFIG_DCACHE_WORD_ACCESS=y
# CONFIG_EXT2_FS is not set
CONFIG_EXT3_FS=y
CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
CONFIG_EXT4_FS=m
CONFIG_EXT4_USE_FOR_EXT23=y
CONFIG_EXT4_FS_XATTR=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXT4_DEBUG=y
CONFIG_JBD=y
CONFIG_JBD_DEBUG=y
CONFIG_JBD2=m
CONFIG_JBD2_DEBUG=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
CONFIG_JFS_FS=m
CONFIG_JFS_POSIX_ACL=y
CONFIG_JFS_SECURITY=y
CONFIG_JFS_DEBUG=y
CONFIG_JFS_STATISTICS=y
CONFIG_XFS_FS=m
CONFIG_XFS_QUOTA=y
CONFIG_XFS_POSIX_ACL=y
CONFIG_XFS_RT=y
CONFIG_XFS_DEBUG=y
CONFIG_GFS2_FS=m
# CONFIG_GFS2_FS_LOCKING_DLM is not set
CONFIG_OCFS2_FS=m
CONFIG_OCFS2_FS_O2CB=m
CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
CONFIG_OCFS2_FS_STATS=y
CONFIG_OCFS2_DEBUG_MASKLOG=y
CONFIG_OCFS2_DEBUG_FS=y
CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y
# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set
CONFIG_NILFS2_FS=m
CONFIG_FS_POSIX_ACL=y
CONFIG_EXPORTFS=y
CONFIG_FILE_LOCKING=y
CONFIG_FSNOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_PRINT_QUOTA_WARNING=y
CONFIG_QUOTA_DEBUG=y
CONFIG_QUOTA_TREE=m
CONFIG_QFMT_V1=m
CONFIG_QFMT_V2=m
CONFIG_QUOTACTL=y
CONFIG_QUOTACTL_COMPAT=y
CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
CONFIG_CUSE=m
CONFIG_GENERIC_ACL=y

#
# Caches
#
CONFIG_FSCACHE=m
CONFIG_FSCACHE_STATS=y
CONFIG_FSCACHE_HISTOGRAM=y
CONFIG_FSCACHE_DEBUG=y
# CONFIG_FSCACHE_OBJECT_LIST is not set
CONFIG_CACHEFILES=m
CONFIG_CACHEFILES_DEBUG=y
CONFIG_CACHEFILES_HISTOGRAM=y

#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_UDF_FS=m
CONFIG_UDF_NLS=y

#
# DOS/FAT/NT Filesystems
#
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_NTFS_FS=m
CONFIG_NTFS_DEBUG=y
# CONFIG_NTFS_RW is not set

#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_TMPFS_XATTR=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_CONFIGFS_FS=m
CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
CONFIG_ECRYPT_FS=m
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_LOGFS is not set
# CONFIG_CRAMFS is not set
# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_QNX6FS_FS is not set
CONFIG_ROMFS_FS=m
CONFIG_ROMFS_BACKED_BY_BLOCK=y
CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_PSTORE is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V2=m
CONFIG_NFS_V3=m
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=m
# CONFIG_NFS_SWAP is not set
CONFIG_NFS_V4_1=y
CONFIG_PNFS_FILE_LAYOUT=m
CONFIG_PNFS_BLOCK=m
CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
CONFIG_NFS_FSCACHE=y
CONFIG_NFS_USE_LEGACY_DNS=y
CONFIG_NFSD=m
CONFIG_NFSD_V2_ACL=y
CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
# CONFIG_NFSD_FAULT_INJECTION is not set
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_NFS_ACL_SUPPORT=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
CONFIG_SUNRPC_BACKCHANNEL=y
# CONFIG_SUNRPC_DEBUG is not set
CONFIG_CEPH_FS=m
CONFIG_CIFS=m
CONFIG_CIFS_STATS=y
CONFIG_CIFS_STATS2=y
CONFIG_CIFS_WEAK_PW_HASH=y
CONFIG_CIFS_UPCALL=y
CONFIG_CIFS_XATTR=y
# CONFIG_CIFS_POSIX is not set
# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_CIFS_DFS_UPCALL is not set
CONFIG_CIFS_FSCACHE=y
CONFIG_CIFS_ACL=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
# CONFIG_NLS_CODEPAGE_850 is not set
# CONFIG_NLS_CODEPAGE_852 is not set
# CONFIG_NLS_CODEPAGE_855 is not set
# CONFIG_NLS_CODEPAGE_857 is not set
# CONFIG_NLS_CODEPAGE_860 is not set
# CONFIG_NLS_CODEPAGE_861 is not set
# CONFIG_NLS_CODEPAGE_862 is not set
# CONFIG_NLS_CODEPAGE_863 is not set
# CONFIG_NLS_CODEPAGE_864 is not set
# CONFIG_NLS_CODEPAGE_865 is not set
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_936 is not set
# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_CODEPAGE_932 is not set
# CONFIG_NLS_CODEPAGE_949 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
# CONFIG_NLS_ISO8859_5 is not set
# CONFIG_NLS_ISO8859_6 is not set
# CONFIG_NLS_ISO8859_7 is not set
# CONFIG_NLS_ISO8859_9 is not set
# CONFIG_NLS_ISO8859_13 is not set
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_MAC_ROMAN is not set
# CONFIG_NLS_MAC_CELTIC is not set
# CONFIG_NLS_MAC_CENTEURO is not set
# CONFIG_NLS_MAC_CROATIAN is not set
# CONFIG_NLS_MAC_CYRILLIC is not set
# CONFIG_NLS_MAC_GAELIC is not set
# CONFIG_NLS_MAC_GREEK is not set
# CONFIG_NLS_MAC_ICELAND is not set
# CONFIG_NLS_MAC_INUIT is not set
# CONFIG_NLS_MAC_ROMANIAN is not set
# CONFIG_NLS_MAC_TURKISH is not set
CONFIG_NLS_UTF8=m
CONFIG_DLM=m
# CONFIG_DLM_DEBUG is not set

#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_PRINTK_TIME=y
CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_READABLE_ASM is not set
CONFIG_UNUSED_SYMBOLS=y
CONFIG_DEBUG_FS=y
CONFIG_HEADERS_CHECK=y
# CONFIG_DEBUG_SECTION_MISMATCH is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
# CONFIG_LOCKUP_DETECTOR is not set
# CONFIG_HARDLOCKUP_DETECTOR is not set
# CONFIG_PANIC_ON_OOPS is not set
CONFIG_PANIC_ON_OOPS_VALUE=0
# CONFIG_DETECT_HUNG_TASK is not set
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_KMEMLEAK is not set
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_PROVE_LOCKING is not set
# CONFIG_SPARSE_RCU_POINTER is not set
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_ATOMIC_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_VIRTUAL is not set
# CONFIG_DEBUG_WRITECOUNT is not set
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_TEST_LIST_SORT is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_DEBUG_CREDENTIALS is not set
CONFIG_ARCH_WANT_FRAME_POINTERS=y
CONFIG_FRAME_POINTER=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=60
# CONFIG_RCU_CPU_STALL_VERBOSE is not set
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_RCU_TRACE=y
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
# CONFIG_DEBUG_PER_CPU_MAPS is not set
# CONFIG_LKDTM is not set
# CONFIG_NOTIFIER_ERROR_INJECTION is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_TRACING_SUPPORT=y
# CONFIG_FTRACE is not set
# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
# CONFIG_BUILD_DOCSRC is not set
# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_DMA_API_DEBUG is not set
# CONFIG_ATOMIC64_SELFTEST is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_HAVE_ARCH_KMEMCHECK=y
# CONFIG_KMEMCHECK is not set
# CONFIG_TEST_KSTRTOX is not set
CONFIG_STRICT_DEVMEM=y
CONFIG_X86_VERBOSE_BOOTUP=y
CONFIG_EARLY_PRINTK=y
# CONFIG_EARLY_PRINTK_DBGP is not set
CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_X86_PTDUMP is not set
CONFIG_DEBUG_RODATA=y
# CONFIG_DEBUG_RODATA_TEST is not set
CONFIG_DEBUG_SET_MODULE_RONX=y
# CONFIG_DEBUG_NX_TEST is not set
# CONFIG_DEBUG_TLBFLUSH is not set
# CONFIG_IOMMU_DEBUG is not set
# CONFIG_IOMMU_STRESS is not set
CONFIG_HAVE_MMIOTRACE_SUPPORT=y
CONFIG_IO_DELAY_TYPE_0X80=0
CONFIG_IO_DELAY_TYPE_0XED=1
CONFIG_IO_DELAY_TYPE_UDELAY=2
CONFIG_IO_DELAY_TYPE_NONE=3
CONFIG_IO_DELAY_0X80=y
# CONFIG_IO_DELAY_0XED is not set
# CONFIG_IO_DELAY_UDELAY is not set
# CONFIG_IO_DELAY_NONE is not set
CONFIG_DEFAULT_IO_DELAY_TYPE=0
# CONFIG_DEBUG_BOOT_PARAMS is not set
# CONFIG_CPA_DEBUG is not set
CONFIG_OPTIMIZE_INLINING=y
# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
# CONFIG_DEBUG_NMI_SELFTEST is not set

#
# Security options
#
CONFIG_KEYS=y
CONFIG_TRUSTED_KEYS=y
CONFIG_ENCRYPTED_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY_DMESG_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_NETWORK_XFRM=y
CONFIG_SECURITY_PATH=y
CONFIG_LSM_MMAP_MIN_ADDR=65536
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_SECURITY_SELINUX_DEVELOP=y
CONFIG_SECURITY_SELINUX_AVC_STATS=y
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX=y
CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE=22
CONFIG_SECURITY_SMACK=y
CONFIG_SECURITY_TOMOYO=y
CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY=2048
CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG=1024
# CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER is not set
CONFIG_SECURITY_TOMOYO_POLICY_LOADER="/sbin/tomoyo-init"
CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER="/sbin/init"
CONFIG_SECURITY_APPARMOR=y
CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
CONFIG_SECURITY_YAMA=y
CONFIG_INTEGRITY=y
CONFIG_INTEGRITY_SIGNATURE=y
CONFIG_IMA=y
CONFIG_IMA_MEASURE_PCR_IDX=10
CONFIG_IMA_AUDIT=y
CONFIG_IMA_LSM_RULES=y
CONFIG_EVM=y
CONFIG_DEFAULT_SECURITY_SELINUX=y
# CONFIG_DEFAULT_SECURITY_SMACK is not set
# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
# CONFIG_DEFAULT_SECURITY_APPARMOR is not set
# CONFIG_DEFAULT_SECURITY_YAMA is not set
# CONFIG_DEFAULT_SECURITY_DAC is not set
CONFIG_DEFAULT_SECURITY="selinux"
CONFIG_CRYPTO=y

#
# Crypto core or helper
#
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_PCOMP2=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_USER is not set
CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
CONFIG_CRYPTO_GF128MUL=m
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_PCRYPT is not set
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
# CONFIG_CRYPTO_TEST is not set
CONFIG_CRYPTO_ABLK_HELPER_X86=m
CONFIG_CRYPTO_GLUE_HELPER_X86=m

#
# Authenticated Encryption with Associated Data
#
# CONFIG_CRYPTO_CCM is not set
# CONFIG_CRYPTO_GCM is not set
# CONFIG_CRYPTO_SEQIV is not set

#
# Block modes
#
CONFIG_CRYPTO_CBC=y
# CONFIG_CRYPTO_CTR is not set
# CONFIG_CRYPTO_CTS is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_LRW=m
# CONFIG_CRYPTO_PCBC is not set
CONFIG_CRYPTO_XTS=m

#
# Hash modes
#
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_VMAC is not set

#
# Digest
#
CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_CRC32C_INTEL is not set
# CONFIG_CRYPTO_GHASH is not set
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_RMD128 is not set
# CONFIG_CRYPTO_RMD160 is not set
# CONFIG_CRYPTO_RMD256 is not set
# CONFIG_CRYPTO_RMD320 is not set
CONFIG_CRYPTO_SHA1=y
# CONFIG_CRYPTO_SHA1_SSSE3 is not set
CONFIG_CRYPTO_SHA256=y
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_TGR192 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set

#
# Ciphers
#
CONFIG_CRYPTO_AES=y
# CONFIG_CRYPTO_AES_X86_64 is not set
# CONFIG_CRYPTO_AES_NI_INTEL is not set
# CONFIG_CRYPTO_ANUBIS is not set
CONFIG_CRYPTO_ARC4=m
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_BLOWFISH_X86_64 is not set
# CONFIG_CRYPTO_CAMELLIA is not set
CONFIG_CRYPTO_CAMELLIA_X86_64=m
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
CONFIG_CRYPTO_DES=m
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_SALSA20 is not set
# CONFIG_CRYPTO_SALSA20_X86_64 is not set
# CONFIG_CRYPTO_SEED is not set
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m
# CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_TWOFISH_X86_64 is not set
# CONFIG_CRYPTO_TWOFISH_X86_64_3WAY is not set
# CONFIG_CRYPTO_TWOFISH_AVX_X86_64 is not set

#
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set

#
# Random Number Generation
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_USER_API_HASH is not set
# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
# CONFIG_CRYPTO_HW is not set
CONFIG_HAVE_KVM=y
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_HAVE_KVM_EVENTFD=y
CONFIG_KVM_APIC_ARCHITECTURE=y
CONFIG_KVM_MMIO=y
CONFIG_KVM_ASYNC_PF=y
CONFIG_HAVE_KVM_MSI=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
# CONFIG_KVM_INTEL is not set
CONFIG_KVM_AMD=m
CONFIG_VHOST_NET=m
# CONFIG_BINARY_PRINTF is not set

#
# Library routines
#
CONFIG_BITREVERSE=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_FIND_FIRST_BIT=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IO=y
# CONFIG_CRC_CCITT is not set
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
# CONFIG_CRC32_SELFTEST is not set
CONFIG_CRC32_SLICEBY8=y
# CONFIG_CRC32_SLICEBY4 is not set
# CONFIG_CRC32_SARWATE is not set
# CONFIG_CRC32_BIT is not set
# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=m
# CONFIG_CRC8 is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=y
CONFIG_XZ_DEC=y
CONFIG_XZ_DEC_X86=y
CONFIG_XZ_DEC_POWERPC=y
CONFIG_XZ_DEC_IA64=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_ARMTHUMB=y
CONFIG_XZ_DEC_SPARC=y
CONFIG_XZ_DEC_BCJ=y
# CONFIG_XZ_DEC_TEST is not set
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_XZ=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_CPU_RMAP=y
CONFIG_DQL=y
CONFIG_NLATTR=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
# CONFIG_AVERAGE is not set
CONFIG_CLZ_TAB=y
# CONFIG_CORDIC is not set
# CONFIG_DDR is not set
CONFIG_MPILIB=y
CONFIG_SIGNATURE=y

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-24 22:02       ` James Morris
@ 2012-08-27  7:23         ` Peter.Huewe
  2012-08-27 16:17           ` Kent Yoder
  2012-08-27 17:19           ` James Morris
  0 siblings, 2 replies; 14+ messages in thread
From: Peter.Huewe @ 2012-08-27  7:23 UTC (permalink / raw)
  To: jmorris, key
  Cc: linux-kernel, linux-security-module, tpmdd-devel, adlai,
	xiaoyan.zhang, jj

>> > Build using make -> no error.
>>   I can't reproduce this either, James, can you send out your .config?

> See attached.

Hi James,

even with you config, I can't reproduce it here with 3.6-rc3 + mypatch.


Peter

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-27  7:23         ` Peter.Huewe
@ 2012-08-27 16:17           ` Kent Yoder
  2012-08-27 17:21             ` James Morris
  2012-08-27 17:19           ` James Morris
  1 sibling, 1 reply; 14+ messages in thread
From: Kent Yoder @ 2012-08-27 16:17 UTC (permalink / raw)
  To: Peter.Huewe
  Cc: jmorris, linux-kernel, linux-security-module, tpmdd-devel, adlai,
	xiaoyan.zhang, jj

On Mon, Aug 27, 2012 at 07:23:40AM +0000, Peter.Huewe@infineon.com wrote:
> >> > Build using make -> no error.
> >>   I can't reproduce this either, James, can you send out your .config?
> 
> > See attached.
> 
> Hi James,
> 
> even with you config, I can't reproduce it here with 3.6-rc3 + mypatch.

  Same here, against linux-security plus the pullreq patches...

Kent

> 
> 
> Peter
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-27  7:23         ` Peter.Huewe
  2012-08-27 16:17           ` Kent Yoder
@ 2012-08-27 17:19           ` James Morris
  1 sibling, 0 replies; 14+ messages in thread
From: James Morris @ 2012-08-27 17:19 UTC (permalink / raw)
  To: Peter.Huewe
  Cc: key, linux-kernel, linux-security-module, tpmdd-devel, adlai,
	xiaoyan.zhang, jj

On Mon, 27 Aug 2012, Peter.Huewe@infineon.com wrote:

> >> > Build using make -> no error.
> >>   I can't reproduce this either, James, can you send out your .config?
> 
> > See attached.
> 
> Hi James,
> 
> even with you config, I can't reproduce it here with 3.6-rc3 + mypatch.

Try against my -next branch.


> 
> 
> Peter
> 

-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-27 16:17           ` Kent Yoder
@ 2012-08-27 17:21             ` James Morris
  2012-08-27 18:02               ` Kent Yoder
  0 siblings, 1 reply; 14+ messages in thread
From: James Morris @ 2012-08-27 17:21 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Peter.Huewe, linux-kernel, linux-security-module, tpmdd-devel,
	adlai, xiaoyan.zhang, jj

On Mon, 27 Aug 2012, Kent Yoder wrote:

> On Mon, Aug 27, 2012 at 07:23:40AM +0000, Peter.Huewe@infineon.com wrote:
> > >> > Build using make -> no error.
> > >>   I can't reproduce this either, James, can you send out your .config?
> > 
> > > See attached.
> > 
> > Hi James,
> > 
> > even with you config, I can't reproduce it here with 3.6-rc3 + mypatch.
> 
>   Same here, against linux-security plus the pullreq patches...

I may have missed something, but what do you mean by pullreq patches?


-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-27 17:21             ` James Morris
@ 2012-08-27 18:02               ` Kent Yoder
  2012-08-27 20:28                 ` James Morris
  0 siblings, 1 reply; 14+ messages in thread
From: Kent Yoder @ 2012-08-27 18:02 UTC (permalink / raw)
  To: James Morris
  Cc: Peter.Huewe, linux-kernel, linux-security-module, tpmdd-devel,
	adlai, xiaoyan.zhang, jj

On Tue, Aug 28, 2012 at 03:21:51AM +1000, James Morris wrote:
> On Mon, 27 Aug 2012, Kent Yoder wrote:
> 
> > On Mon, Aug 27, 2012 at 07:23:40AM +0000, Peter.Huewe@infineon.com wrote:
> > > >> > Build using make -> no error.
> > > >>   I can't reproduce this either, James, can you send out your .config?
> > > 
> > > > See attached.
> > > 
> > > Hi James,
> > > 
> > > even with you config, I can't reproduce it here with 3.6-rc3 + mypatch.
> > 
> >   Same here, against linux-security plus the pullreq patches...
> 
> I may have missed something, but what do you mean by pullreq patches?

  Just the stuff I asked you to pull here.

Kent

> 
> 
> -- 
> James Morris
> <jmorris@namei.org>
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-27 18:02               ` Kent Yoder
@ 2012-08-27 20:28                 ` James Morris
  2012-08-27 21:58                   ` James Morris
  0 siblings, 1 reply; 14+ messages in thread
From: James Morris @ 2012-08-27 20:28 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Peter.Huewe, linux-kernel, linux-security-module, tpmdd-devel,
	adlai, xiaoyan.zhang, jj

On Mon, 27 Aug 2012, Kent Yoder wrote:

> > I may have missed something, but what do you mean by pullreq patches?
> 
>   Just the stuff I asked you to pull here.

Looks like it could be an issue with the development repo I have on my 
laptop while traveling.  Investigating...



-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes
  2012-08-27 20:28                 ` James Morris
@ 2012-08-27 21:58                   ` James Morris
  0 siblings, 0 replies; 14+ messages in thread
From: James Morris @ 2012-08-27 21:58 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Peter.Huewe, linux-kernel, linux-security-module, tpmdd-devel,
	adlai, xiaoyan.zhang, jj, hpa

On Tue, 28 Aug 2012, James Morris wrote:

> On Mon, 27 Aug 2012, Kent Yoder wrote:
> 
> > > I may have missed something, but what do you mean by pullreq patches?
> > 
> >   Just the stuff I asked you to pull here.
> 
> Looks like it could be an issue with the development repo I have on my 
> laptop while traveling.  Investigating...

Confirmed, but all is fixed now and I've pulled the patches.

Thanks.


-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-08-27 22:01 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-22 21:52 [GIT PULL] tpmdd: TPM drivers, tpm-rng and fixes Kent Yoder
2012-08-22 23:42 ` Jeff Garzik
2012-08-23 20:32 ` James Morris
2012-08-24  7:27   ` Peter.Huewe
2012-08-24  8:32   ` Peter.Huewe
2012-08-24 15:05     ` Kent Yoder
2012-08-24 22:02       ` James Morris
2012-08-27  7:23         ` Peter.Huewe
2012-08-27 16:17           ` Kent Yoder
2012-08-27 17:21             ` James Morris
2012-08-27 18:02               ` Kent Yoder
2012-08-27 20:28                 ` James Morris
2012-08-27 21:58                   ` James Morris
2012-08-27 17:19           ` James Morris

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).