* [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).