ia64/xen-unstable

changeset 7224:6bbfd6a98974

Merge (with trepidation).
author emellor@ewan
date Wed Oct 05 14:40:35 2005 +0100 (2005-10-05)
parents b4800e204757 e579bef0d237
children 8f8e42887f09
files
line diff
     1.1 --- a/Config.mk	Wed Oct 05 14:38:19 2005 +0100
     1.2 +++ b/Config.mk	Wed Oct 05 14:40:35 2005 +0100
     1.3 @@ -20,6 +20,15 @@ STRIP      = $(CROSS_COMPILE)strip
     1.4  OBJCOPY    = $(CROSS_COMPILE)objcopy
     1.5  OBJDUMP    = $(CROSS_COMPILE)objdump
     1.6  
     1.7 +# Default is to install to local 'dist' directory.
     1.8 +DISTDIR ?= $(XEN_ROOT)/dist
     1.9 +DESTDIR ?= $(DISTDIR)/install
    1.10 +
    1.11 +INSTALL      = install
    1.12 +INSTALL_DIR  = $(INSTALL) -d -m0755
    1.13 +INSTALL_DATA = $(INSTALL) -m0644
    1.14 +INSTALL_PROG = $(INSTALL) -m0755
    1.15 +
    1.16  ifeq ($(XEN_TARGET_ARCH),x86_64)
    1.17  LIBDIR = lib64
    1.18  else
    1.19 @@ -49,3 +58,5 @@ ACM_USE_SECURITY_POLICY ?= ACM_NULL_POLI
    1.20  XENSTAT_XENTOP ?= y
    1.21  
    1.22  VTPM_TOOLS ?= n
    1.23 +
    1.24 +-include $(XEN_ROOT)/.config
     2.1 --- a/Makefile	Wed Oct 05 14:38:19 2005 +0100
     2.2 +++ b/Makefile	Wed Oct 05 14:40:35 2005 +0100
     2.3 @@ -2,23 +2,12 @@
     2.4  # Grand Unified Makefile for Xen.
     2.5  #
     2.6  
     2.7 -# Default is to install to local 'dist' directory.
     2.8 -DISTDIR ?= $(CURDIR)/dist
     2.9 -DESTDIR ?= $(DISTDIR)/install
    2.10 -
    2.11 -INSTALL		:= install
    2.12 -INSTALL_DIR	:= $(INSTALL) -d -m0755
    2.13 -INSTALL_DATA	:= $(INSTALL) -m0644
    2.14 -INSTALL_PROG	:= $(INSTALL) -m0755
    2.15 -
    2.16  KERNELS ?= linux-2.6-xen0 linux-2.6-xenU
    2.17  # linux-2.4-xen0 linux-2.4-xenU netbsd-2.0-xenU
    2.18  # You may use wildcards in the above e.g. KERNELS=*2.4*
    2.19  
    2.20  XKERNELS := $(foreach kernel, $(KERNELS), $(patsubst buildconfigs/mk.%,%,$(wildcard buildconfigs/mk.$(kernel))) )
    2.21  
    2.22 -export DESTDIR
    2.23 -
    2.24  # Export target architecture overrides to Xen and Linux sub-trees.
    2.25  ifneq ($(XEN_TARGET_ARCH),)
    2.26  SUBARCH := $(subst x86_32,i386,$(XEN_TARGET_ARCH))
    2.27 @@ -28,6 +17,7 @@ endif
    2.28  # Default target must appear before any include lines
    2.29  all: dist
    2.30  
    2.31 +XEN_ROOT=$(CURDIR)
    2.32  include Config.mk
    2.33  include buildconfigs/Rules.mk
    2.34  
     3.1 --- a/buildconfigs/Rules.mk	Wed Oct 05 14:38:19 2005 +0100
     3.2 +++ b/buildconfigs/Rules.mk	Wed Oct 05 14:40:35 2005 +0100
     3.3 @@ -6,6 +6,8 @@ include Config.mk
     3.4  DISTDIR	?= $(CURDIR)/dist
     3.5  DESTDIR	?= $(DISTDIR)/install
     3.6  
     3.7 +export DESTDIR
     3.8 +
     3.9  ALLKERNELS = $(patsubst buildconfigs/mk.%,%,$(wildcard buildconfigs/mk.*))
    3.10  ALLSPARSETREES = $(patsubst %-xen-sparse,%,$(wildcard *-xen-sparse))
    3.11  
     4.1 --- a/buildconfigs/mk.linux-2.6-xen	Wed Oct 05 14:38:19 2005 +0100
     4.2 +++ b/buildconfigs/mk.linux-2.6-xen	Wed Oct 05 14:40:35 2005 +0100
     4.3 @@ -4,7 +4,7 @@ OS           = linux
     4.4  LINUX_SERIES = 2.6
     4.5  LINUX_VER    = 2.6.12
     4.6  
     4.7 -EXTRAVERSION = xen
     4.8 +EXTRAVERSION ?= xen
     4.9  
    4.10  LINUX_DIR    = $(OS)-$(LINUX_VER)-$(EXTRAVERSION)
    4.11  
     5.1 --- a/buildconfigs/mk.linux-2.6-xen0	Wed Oct 05 14:38:19 2005 +0100
     5.2 +++ b/buildconfigs/mk.linux-2.6-xen0	Wed Oct 05 14:40:35 2005 +0100
     5.3 @@ -1,51 +1,2 @@
     5.4 -
     5.5 -OS           = linux
     5.6 -
     5.7 -LINUX_SERIES = 2.6
     5.8 -LINUX_VER    = 2.6.12
     5.9 -
    5.10  EXTRAVERSION = xen0
    5.11 -
    5.12 -LINUX_DIR    = $(OS)-$(LINUX_VER)-$(EXTRAVERSION)
    5.13 -
    5.14 -include buildconfigs/Rules.mk
    5.15 -
    5.16 -.PHONY: build clean delete
    5.17 -
    5.18 -# The real action starts here!
    5.19 -build: $(LINUX_DIR)/include/linux/autoconf.h
    5.20 -	if grep "^CONFIG_MODULES=" $(LINUX_DIR)/.config ; then \
    5.21 -	    $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) modules ; \
    5.22 -	    $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_MOD_PATH=$(DESTDIR) modules_install ; \
    5.23 -	fi
    5.24 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) install
    5.25 -
    5.26 -$(LINUX_DIR)/include/linux/autoconf.h: ref-$(OS)-$(LINUX_VER)/.valid-ref
    5.27 -	rm -rf $(LINUX_DIR)
    5.28 -	cp -al $(<D) $(LINUX_DIR)
    5.29 -	# Apply arch-xen patches
    5.30 -	( cd linux-$(LINUX_SERIES)-xen-sparse ; \
    5.31 -          LINUX_ARCH=$(LINUX_ARCH) ./mkbuildtree ../$(LINUX_DIR) )
    5.32 -	# Re-use config from install dir if one exits else use default config
    5.33 -	CONFIG_VERSION=$$(sed -ne 's/^EXTRAVERSION = //p' $(LINUX_DIR)/Makefile); \
    5.34 -	[ -r $(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) ] && \
    5.35 -	  cp $(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) $(LINUX_DIR)/.config \
    5.36 -	  || cp $(LINUX_DIR)/arch/xen/configs/$(EXTRAVERSION)_defconfig_$(XEN_TARGET_ARCH) \
    5.37 -		$(LINUX_DIR)/.config
    5.38 -	# See if we need to munge config to enable PAE
    5.39 -	$(MAKE) CONFIG_FILE=$(LINUX_DIR)/.config -f buildconfigs/Rules.mk config-update-pae
    5.40 -	# Patch kernel Makefile to set EXTRAVERSION
    5.41 -	( cd $(LINUX_DIR) ; \
    5.42 -	  sed -e 's/^EXTRAVERSION.*/&$$(XENGUEST)\nXENGUEST = -$(EXTRAVERSION)/' Makefile >Mk.tmp ; \
    5.43 -	  rm -f Makefile ; mv Mk.tmp Makefile )
    5.44 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) oldconfig
    5.45 -
    5.46 -config: CONFIGMODE = menuconfig
    5.47 -config: $(LINUX_DIR)/include/linux/autoconf.h
    5.48 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) $(CONFIGMODE)
    5.49 -
    5.50 -clean::
    5.51 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean
    5.52 -
    5.53 -delete: 
    5.54 -	rm -rf tmp-$(OS)-$(LINUX_VER) $(LINUX_DIR) 
    5.55 +include buildconfigs/mk.linux-2.6-xen
     6.1 --- a/buildconfigs/mk.linux-2.6-xenU	Wed Oct 05 14:38:19 2005 +0100
     6.2 +++ b/buildconfigs/mk.linux-2.6-xenU	Wed Oct 05 14:40:35 2005 +0100
     6.3 @@ -1,51 +1,2 @@
     6.4 -
     6.5 -OS           = linux
     6.6 -
     6.7 -LINUX_SERIES = 2.6
     6.8 -LINUX_VER    = 2.6.12
     6.9 -
    6.10  EXTRAVERSION = xenU
    6.11 -
    6.12 -LINUX_DIR    = $(OS)-$(LINUX_VER)-$(EXTRAVERSION)
    6.13 -
    6.14 -include buildconfigs/Rules.mk
    6.15 -
    6.16 -.PHONY: build clean delete
    6.17 -
    6.18 -# The real action starts here!
    6.19 -build: $(LINUX_DIR)/include/linux/autoconf.h
    6.20 -	if grep "^CONFIG_MODULES=" $(LINUX_DIR)/.config ; then \
    6.21 -	    $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) modules ; \
    6.22 -	    $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_MOD_PATH=$(DESTDIR) modules_install ; \
    6.23 -	fi
    6.24 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) install
    6.25 -
    6.26 -$(LINUX_DIR)/include/linux/autoconf.h: ref-$(OS)-$(LINUX_VER)/.valid-ref
    6.27 -	rm -rf $(LINUX_DIR)
    6.28 -	cp -al $(<D) $(LINUX_DIR)
    6.29 -	# Apply arch-xen patches
    6.30 -	( cd linux-$(LINUX_SERIES)-xen-sparse ; \
    6.31 -          LINUX_ARCH=$(LINUX_ARCH) ./mkbuildtree ../$(LINUX_DIR) )
    6.32 -	# Re-use config from install dir if one exits else use default config
    6.33 -	CONFIG_VERSION=$$(sed -ne 's/^EXTRAVERSION = //p' $(LINUX_DIR)/Makefile); \
    6.34 -	[ -r $(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) ] && \
    6.35 -	  cp $(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) $(LINUX_DIR)/.config \
    6.36 -	  || cp $(LINUX_DIR)/arch/xen/configs/$(EXTRAVERSION)_defconfig_$(XEN_TARGET_ARCH) \
    6.37 -		$(LINUX_DIR)/.config
    6.38 -	# See if we need to munge config to enable PAE
    6.39 -	$(MAKE) CONFIG_FILE=$(LINUX_DIR)/.config -f buildconfigs/Rules.mk config-update-pae
    6.40 -	# Patch kernel Makefile to set EXTRAVERSION
    6.41 -	( cd $(LINUX_DIR) ; \
    6.42 -	  sed -e 's/^EXTRAVERSION.*/&$$(XENGUEST)\nXENGUEST = -$(EXTRAVERSION)/' Makefile >Mk.tmp ; \
    6.43 -	  rm -f Makefile ; mv Mk.tmp Makefile )
    6.44 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) oldconfig
    6.45 -
    6.46 -config: CONFIGMODE = menuconfig
    6.47 -config: $(LINUX_DIR)/include/linux/autoconf.h
    6.48 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) $(CONFIGMODE)
    6.49 -
    6.50 -clean::
    6.51 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean
    6.52 -
    6.53 -delete: 
    6.54 -	rm -rf tmp-$(OS)-$(LINUX_VER) $(LINUX_DIR) 
    6.55 +include buildconfigs/mk.linux-2.6-xen
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig	Wed Oct 05 14:40:35 2005 +0100
     7.3 @@ -0,0 +1,58 @@
     7.4 +#
     7.5 +# TPM device configuration
     7.6 +#
     7.7 +
     7.8 +menu "TPM devices"
     7.9 +
    7.10 +config TCG_TPM
    7.11 +	tristate "TPM Hardware Support"
    7.12 +	depends on EXPERIMENTAL && PCI
    7.13 +	---help---
    7.14 +	  If you have a TPM security chip in your system, which
    7.15 +	  implements the Trusted Computing Group's specification,
    7.16 +	  say Yes and it will be accessible from within Linux.  For
    7.17 +	  more information see <http://www.trustedcomputinggroup.org>. 
    7.18 +	  An implementation of the Trusted Software Stack (TSS), the 
    7.19 +	  userspace enablement piece of the specification, can be 
    7.20 +	  obtained at: <http://sourceforge.net/projects/trousers>.  To 
    7.21 +	  compile this driver as a module, choose M here; the module 
    7.22 +	  will be called tpm. If unsure, say N.
    7.23 +
    7.24 +config TCG_TIS
    7.25 +	tristate "TPM Interface Specification 1.2 Interface"
    7.26 +	depends on TCG_TPM
    7.27 +	---help---
    7.28 +	  If you have a TPM security chip that is compliant with the
    7.29 +	  TCG TIS 1.2 TPM specification say Yes and it will be accessible
    7.30 +	  from within Linux.  To compile this driver as a module, choose
    7.31 +	  M here; the module will be called tpm_tis.
    7.32 +
    7.33 +config TCG_NSC
    7.34 +	tristate "National Semiconductor TPM Interface"
    7.35 +	depends on TCG_TPM
    7.36 +	---help---
    7.37 +	  If you have a TPM security chip from National Semicondutor 
    7.38 +	  say Yes and it will be accessible from within Linux.  To 
    7.39 +	  compile this driver as a module, choose M here; the module 
    7.40 +	  will be called tpm_nsc.
    7.41 +
    7.42 +config TCG_ATMEL
    7.43 +	tristate "Atmel TPM Interface"
    7.44 +	depends on TCG_TPM
    7.45 +	---help---
    7.46 +	  If you have a TPM security chip from Atmel say Yes and it 
    7.47 +	  will be accessible from within Linux.  To compile this driver 
    7.48 +	  as a module, choose M here; the module will be called tpm_atmel.
    7.49 +
    7.50 +config TCG_XEN
    7.51 +	tristate "XEN TPM Interface"
    7.52 +	depends on TCG_TPM && ARCH_XEN && XEN_TPMDEV_FRONTEND
    7.53 +	---help---
    7.54 +	  If you want to make TPM support available to a Xen
    7.55 +	  user domain, say Yes and it will
    7.56 +          be accessible from within Linux. To compile this driver
    7.57 +          as a module, choose M here; the module will be called
    7.58 +          tpm_xen.
    7.59 +
    7.60 +endmenu
    7.61 +
     8.1 --- a/linux-2.6-xen-sparse/drivers/char/tpm/Makefile	Wed Oct 05 14:38:19 2005 +0100
     8.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Makefile	Wed Oct 05 14:40:35 2005 +0100
     8.3 @@ -5,8 +5,9 @@ ifeq ($(CONFIG_XEN_PHYSDEV_ACCESS),y)
     8.4  obj-$(CONFIG_TCG_TPM) += tpm.o
     8.5  obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
     8.6  obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
     8.7 -obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
     8.8 +obj-$(CONFIG_TCG_TIS) += tpm_tis.o
     8.9 +obj-$(CONFIG_TCG_XEN) += tpm_xen.o
    8.10  else
    8.11 -obj-$(CONFIG_TCG_TPM) += tpm_nopci.o
    8.12 +obj-$(CONFIG_TCG_TPM) += tpm.o
    8.13  obj-$(CONFIG_TCG_XEN) += tpm_xen.o
    8.14  endif
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c	Wed Oct 05 14:40:35 2005 +0100
     9.3 @@ -0,0 +1,657 @@
     9.4 +/*
     9.5 + * Copyright (C) 2004 IBM Corporation
     9.6 + *
     9.7 + * Authors:
     9.8 + * Leendert van Doorn <leendert@watson.ibm.com>
     9.9 + * Dave Safford <safford@watson.ibm.com>
    9.10 + * Reiner Sailer <sailer@watson.ibm.com>
    9.11 + * Kylene Hall <kjhall@us.ibm.com>
    9.12 + *
    9.13 + * Maintained by: <tpmdd_devel@lists.sourceforge.net>
    9.14 + *
    9.15 + * Device driver for TCG/TCPA TPM (trusted platform module).
    9.16 + * Specifications at www.trustedcomputinggroup.org	 
    9.17 + *
    9.18 + * This program is free software; you can redistribute it and/or
    9.19 + * modify it under the terms of the GNU General Public License as
    9.20 + * published by the Free Software Foundation, version 2 of the
    9.21 + * License.
    9.22 + * 
    9.23 + * Note, the TPM chip is not interrupt driven (only polling)
    9.24 + * and can have very long timeouts (minutes!). Hence the unusual
    9.25 + * calls to msleep.
    9.26 + *
    9.27 + */
    9.28 +
    9.29 +#include <linux/sched.h>
    9.30 +#include <linux/poll.h>
    9.31 +#include <linux/spinlock.h>
    9.32 +#include "tpm.h"
    9.33 +
    9.34 +#define TPM_CHIP_NUM_MASK	0x0000ffff
    9.35 +#define TPM_CHIP_TYPE_SHIFT	16	
    9.36 +
    9.37 +enum tpm_const {
    9.38 +	TPM_MINOR = 224,	/* officially assigned */
    9.39 +	TPM_MIN_BUFSIZE = 2048,
    9.40 +	TPM_MAX_BUFSIZE = 64 * 1024,
    9.41 +	TPM_NUM_DEVICES = 256,
    9.42 +	TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
    9.43 +};
    9.44 +
    9.45 +static LIST_HEAD(tpm_chip_list);
    9.46 +static DEFINE_SPINLOCK(driver_lock);
    9.47 +static int dev_mask[TPM_NUM_MASK_ENTRIES];
    9.48 +
    9.49 +static void user_reader_timeout(unsigned long ptr)
    9.50 +{
    9.51 +	struct tpm_chip *chip = (struct tpm_chip *) ptr;
    9.52 +
    9.53 +	down(&chip->buffer_mutex);
    9.54 +	atomic_set(&chip->data_pending, 0);
    9.55 +	memset(chip->data_buffer, 0, chip->vendor->buffersize);
    9.56 +	up(&chip->buffer_mutex);
    9.57 +}
    9.58 +
    9.59 +/*
    9.60 + * Internal kernel interface to transmit TPM commands
    9.61 + */
    9.62 +static ssize_t tpm_transmit(struct tpm_chip * chip, const char *buf,
    9.63 +			    size_t bufsiz)
    9.64 +{
    9.65 +	ssize_t rc;
    9.66 +	u32 count;
    9.67 +	unsigned long stop;
    9.68 +
    9.69 +	if (!chip)
    9.70 +		return -ENODEV;
    9.71 +
    9.72 +	if ( !chip )
    9.73 +		return -ENODEV;
    9.74 +
    9.75 +	count = be32_to_cpu(*((__be32 *) (buf + 2)));
    9.76 +
    9.77 +	if (count == 0)
    9.78 +		return -ENODATA;
    9.79 +	if (count > bufsiz) {
    9.80 +		dev_err(chip->dev,
    9.81 +			"invalid count value %x %zx \n", count, bufsiz);
    9.82 +		return -E2BIG;
    9.83 +	}
    9.84 +
    9.85 +	down(&chip->tpm_mutex);
    9.86 +
    9.87 +	if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
    9.88 +		dev_err(chip->dev,
    9.89 +			"tpm_transmit: tpm_send: error %zd\n", rc);
    9.90 +		goto out;
    9.91 +	}
    9.92 +
    9.93 +	stop = jiffies + 2 * 60 * HZ;
    9.94 +	do {
    9.95 +		u8 status = chip->vendor->status(chip);
    9.96 +		if ((status & chip->vendor->req_complete_mask) ==
    9.97 +		    chip->vendor->req_complete_val) {
    9.98 +			goto out_recv;
    9.99 +		}
   9.100 +
   9.101 +		if ((status == chip->vendor->req_canceled)) {
   9.102 +			dev_err(chip->dev, "Operation Canceled\n");
   9.103 +			rc = -ECANCELED;
   9.104 +			goto out;
   9.105 +		}
   9.106 +
   9.107 +		msleep(TPM_TIMEOUT);	/* CHECK */
   9.108 +		rmb();
   9.109 +	} while (time_before(jiffies, stop));
   9.110 +
   9.111 +
   9.112 +	chip->vendor->cancel(chip);
   9.113 +	dev_err(chip->dev, "Operation Timed out\n");
   9.114 +	rc = -ETIME;
   9.115 +	goto out;
   9.116 +
   9.117 +out_recv:
   9.118 +	rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
   9.119 +	if (rc < 0)
   9.120 +		dev_err(chip->dev,
   9.121 +			"tpm_transmit: tpm_recv: error %zd\n", rc);
   9.122 +out:
   9.123 +	up(&chip->tpm_mutex);
   9.124 +	return rc;
   9.125 +}
   9.126 +
   9.127 +#define TPM_DIGEST_SIZE 20
   9.128 +#define CAP_PCR_RESULT_SIZE 18
   9.129 +static const u8 cap_pcr[] = {
   9.130 +	0, 193,			/* TPM_TAG_RQU_COMMAND */
   9.131 +	0, 0, 0, 22,		/* length */
   9.132 +	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
   9.133 +	0, 0, 0, 5,
   9.134 +	0, 0, 0, 4,
   9.135 +	0, 0, 1, 1
   9.136 +};
   9.137 +
   9.138 +#define READ_PCR_RESULT_SIZE 30
   9.139 +static const u8 pcrread[] = {
   9.140 +	0, 193,			/* TPM_TAG_RQU_COMMAND */
   9.141 +	0, 0, 0, 14,		/* length */
   9.142 +	0, 0, 0, 21,		/* TPM_ORD_PcrRead */
   9.143 +	0, 0, 0, 0		/* PCR index */
   9.144 +};
   9.145 +
   9.146 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
   9.147 +ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
   9.148 +		      char *buf)
   9.149 +#else
   9.150 +ssize_t tpm_show_pcrs(struct device *dev,
   9.151 +		      char *buf)
   9.152 +#endif
   9.153 +{
   9.154 +	u8 data[READ_PCR_RESULT_SIZE];
   9.155 +	ssize_t len;
   9.156 +	int i, j, num_pcrs;
   9.157 +	__be32 index;
   9.158 +	char *str = buf;
   9.159 +
   9.160 +	struct tpm_chip *chip = dev_get_drvdata(dev);
   9.161 +	if (chip == NULL)
   9.162 +		return -ENODEV;
   9.163 +
   9.164 +	memcpy(data, cap_pcr, sizeof(cap_pcr));
   9.165 +	if ((len = tpm_transmit(chip, data, sizeof(data)))
   9.166 +	    < CAP_PCR_RESULT_SIZE) {
   9.167 +		dev_dbg(chip->dev, "A TPM error (%d) occurred "
   9.168 +				"attempting to determine the number of PCRS\n",
   9.169 +			be32_to_cpu(*((__be32 *) (data + 6))));
   9.170 +		return 0;
   9.171 +	}
   9.172 +
   9.173 +	num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
   9.174 +
   9.175 +	for (i = 0; i < num_pcrs; i++) {
   9.176 +		memcpy(data, pcrread, sizeof(pcrread));
   9.177 +		index = cpu_to_be32(i);
   9.178 +		memcpy(data + 10, &index, 4);
   9.179 +		if ((len = tpm_transmit(chip, data, sizeof(data)))
   9.180 +		    < READ_PCR_RESULT_SIZE){
   9.181 +			dev_dbg(chip->dev, "A TPM error (%d) occurred"
   9.182 +				" attempting to read PCR %d of %d\n",
   9.183 +				be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs);
   9.184 +			goto out;
   9.185 +		}
   9.186 +		str += sprintf(str, "PCR-%02d: ", i);
   9.187 +		for (j = 0; j < TPM_DIGEST_SIZE; j++)
   9.188 +			str += sprintf(str, "%02X ", *(data + 10 + j));
   9.189 +		str += sprintf(str, "\n");
   9.190 +	}
   9.191 +out:
   9.192 +	return str - buf;
   9.193 +}
   9.194 +EXPORT_SYMBOL_GPL(tpm_show_pcrs);
   9.195 +
   9.196 +#define  READ_PUBEK_RESULT_SIZE 314
   9.197 +static const u8 readpubek[] = {
   9.198 +	0, 193,			/* TPM_TAG_RQU_COMMAND */
   9.199 +	0, 0, 0, 30,		/* length */
   9.200 +	0, 0, 0, 124,		/* TPM_ORD_ReadPubek */
   9.201 +};
   9.202 +
   9.203 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
   9.204 +ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
   9.205 +		       char *buf)
   9.206 +#else
   9.207 +ssize_t tpm_show_pubek(struct device *dev,
   9.208 +		       char *buf)
   9.209 +#endif
   9.210 +{
   9.211 +	u8 *data;
   9.212 +	ssize_t len;
   9.213 +	int i, rc;
   9.214 +	char *str = buf;
   9.215 +
   9.216 +	struct tpm_chip *chip = dev_get_drvdata(dev);
   9.217 +	if (chip == NULL)
   9.218 +		return -ENODEV;
   9.219 +
   9.220 +	data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
   9.221 +	if (!data)
   9.222 +		return -ENOMEM;
   9.223 +
   9.224 +	memcpy(data, readpubek, sizeof(readpubek));
   9.225 +	memset(data + sizeof(readpubek), 0, 20);	/* zero nonce */
   9.226 +
   9.227 +	if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
   9.228 +	    READ_PUBEK_RESULT_SIZE) {
   9.229 +		dev_dbg(chip->dev, "A TPM error (%d) occurred "
   9.230 +				"attempting to read the PUBEK\n",
   9.231 +			    be32_to_cpu(*((__be32 *) (data + 6))));
   9.232 +		rc = 0;
   9.233 +		goto out;
   9.234 +	}
   9.235 +
   9.236 +	/* 
   9.237 +	   ignore header 10 bytes
   9.238 +	   algorithm 32 bits (1 == RSA )
   9.239 +	   encscheme 16 bits
   9.240 +	   sigscheme 16 bits
   9.241 +	   parameters (RSA 12->bytes: keybit, #primes, expbit)  
   9.242 +	   keylenbytes 32 bits
   9.243 +	   256 byte modulus
   9.244 +	   ignore checksum 20 bytes
   9.245 +	 */
   9.246 +
   9.247 +	str +=
   9.248 +	    sprintf(str,
   9.249 +		    "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
   9.250 +		    "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
   9.251 +		    " %02X %02X %02X %02X %02X %02X %02X %02X\n"
   9.252 +		    "Modulus length: %d\nModulus: \n",
   9.253 +		    data[10], data[11], data[12], data[13], data[14],
   9.254 +		    data[15], data[16], data[17], data[22], data[23],
   9.255 +		    data[24], data[25], data[26], data[27], data[28],
   9.256 +		    data[29], data[30], data[31], data[32], data[33],
   9.257 +		    be32_to_cpu(*((__be32 *) (data + 34))));
   9.258 +
   9.259 +	for (i = 0; i < 256; i++) {
   9.260 +		str += sprintf(str, "%02X ", data[i + 38]);
   9.261 +		if ((i + 1) % 16 == 0)
   9.262 +			str += sprintf(str, "\n");
   9.263 +	}
   9.264 +	rc = str - buf;
   9.265 +out:
   9.266 +	kfree(data);
   9.267 +	return rc;
   9.268 +}
   9.269 +
   9.270 +EXPORT_SYMBOL_GPL(tpm_show_pubek);
   9.271 +
   9.272 +#define CAP_VER_RESULT_SIZE 18
   9.273 +static const u8 cap_version[] = {
   9.274 +	0, 193,			/* TPM_TAG_RQU_COMMAND */
   9.275 +	0, 0, 0, 18,		/* length */
   9.276 +	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
   9.277 +	0, 0, 0, 6,
   9.278 +	0, 0, 0, 0
   9.279 +};
   9.280 +
   9.281 +#define CAP_MANUFACTURER_RESULT_SIZE 18
   9.282 +static const u8 cap_manufacturer[] = {
   9.283 +	0, 193,			/* TPM_TAG_RQU_COMMAND */
   9.284 +	0, 0, 0, 22,		/* length */
   9.285 +	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
   9.286 +	0, 0, 0, 5,
   9.287 +	0, 0, 0, 4,
   9.288 +	0, 0, 1, 3
   9.289 +};
   9.290 +
   9.291 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
   9.292 +ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
   9.293 +		      char *buf)
   9.294 +#else
   9.295 +ssize_t tpm_show_caps(struct device *dev,
   9.296 +		      char *buf)
   9.297 +#endif
   9.298 +{
   9.299 +	u8 data[sizeof(cap_manufacturer)];
   9.300 +	ssize_t len;
   9.301 +	char *str = buf;
   9.302 +
   9.303 +	struct tpm_chip *chip = dev_get_drvdata(dev);
   9.304 +	if (chip == NULL)
   9.305 +		return -ENODEV;
   9.306 +
   9.307 +	memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
   9.308 +
   9.309 +	if ((len = tpm_transmit(chip, data, sizeof(data))) <
   9.310 +	    CAP_MANUFACTURER_RESULT_SIZE)
   9.311 +		return len;
   9.312 +
   9.313 +	str += sprintf(str, "Manufacturer: 0x%x\n",
   9.314 +		       be32_to_cpu(*((__be32 *) (data + 14))));
   9.315 +
   9.316 +	memcpy(data, cap_version, sizeof(cap_version));
   9.317 +
   9.318 +	if ((len = tpm_transmit(chip, data, sizeof(data))) <
   9.319 +	    CAP_VER_RESULT_SIZE)
   9.320 +		return len;
   9.321 +
   9.322 +	str +=
   9.323 +	    sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
   9.324 +		    (int) data[14], (int) data[15], (int) data[16],
   9.325 +		    (int) data[17]);
   9.326 +
   9.327 +	return str - buf;
   9.328 +}
   9.329 +EXPORT_SYMBOL_GPL(tpm_show_caps);
   9.330 +
   9.331 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
   9.332 +ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
   9.333 +			const char *buf, size_t count)
   9.334 +#else
   9.335 +ssize_t tpm_store_cancel(struct device *dev,
   9.336 +			const char *buf, size_t count)
   9.337 +#endif
   9.338 +{
   9.339 +	struct tpm_chip *chip = dev_get_drvdata(dev);
   9.340 +	if (chip == NULL)
   9.341 +		return 0;
   9.342 +
   9.343 +	chip->vendor->cancel(chip);
   9.344 +	return count;
   9.345 +}
   9.346 +EXPORT_SYMBOL_GPL(tpm_store_cancel);
   9.347 +
   9.348 +
   9.349 +/*
   9.350 + * Device file system interface to the TPM
   9.351 + */
   9.352 +int tpm_open(struct inode *inode, struct file *file)
   9.353 +{
   9.354 +	int rc = 0, minor = iminor(inode);
   9.355 +	struct tpm_chip *chip = NULL, *pos;
   9.356 +
   9.357 +	spin_lock(&driver_lock);
   9.358 +
   9.359 +	list_for_each_entry(pos, &tpm_chip_list, list) {
   9.360 +		if (pos->vendor->miscdev.minor == minor) {
   9.361 +			chip = pos;
   9.362 +			break;
   9.363 +		}
   9.364 +	}
   9.365 +
   9.366 +	if (chip == NULL) {
   9.367 +		rc = -ENODEV;
   9.368 +		goto err_out;
   9.369 +	}
   9.370 +
   9.371 +	if (chip->num_opens) {
   9.372 +		dev_dbg(chip->dev,
   9.373 +			"Another process owns this TPM\n");
   9.374 +		rc = -EBUSY;
   9.375 +		goto err_out;
   9.376 +	}
   9.377 +
   9.378 +	chip->num_opens++;
   9.379 +	get_device(chip->dev);
   9.380 +
   9.381 +	spin_unlock(&driver_lock);
   9.382 +
   9.383 +	chip->data_buffer = kmalloc(chip->vendor->buffersize * sizeof(u8), GFP_KERNEL);
   9.384 +	if (chip->data_buffer == NULL) {
   9.385 +		chip->num_opens--;
   9.386 +		put_device(chip->dev);
   9.387 +		return -ENOMEM;
   9.388 +	}
   9.389 +
   9.390 +	atomic_set(&chip->data_pending, 0);
   9.391 +
   9.392 +	file->private_data = chip;
   9.393 +	return 0;
   9.394 +
   9.395 +err_out:
   9.396 +	spin_unlock(&driver_lock);
   9.397 +	return rc;
   9.398 +}
   9.399 +
   9.400 +EXPORT_SYMBOL_GPL(tpm_open);
   9.401 +
   9.402 +int tpm_release(struct inode *inode, struct file *file)
   9.403 +{
   9.404 +	struct tpm_chip *chip = file->private_data;
   9.405 +
   9.406 +	spin_lock(&driver_lock);
   9.407 +	file->private_data = NULL;
   9.408 +	chip->num_opens--;
   9.409 +	del_singleshot_timer_sync(&chip->user_read_timer);
   9.410 +	atomic_set(&chip->data_pending, 0);
   9.411 +	put_device(chip->dev);
   9.412 +	kfree(chip->data_buffer);
   9.413 +	spin_unlock(&driver_lock);
   9.414 +	return 0;
   9.415 +}
   9.416 +
   9.417 +EXPORT_SYMBOL_GPL(tpm_release);
   9.418 +
   9.419 +ssize_t tpm_write(struct file * file, const char __user * buf,
   9.420 +		  size_t size, loff_t * off)
   9.421 +{
   9.422 +	struct tpm_chip *chip = file->private_data;
   9.423 +	int in_size = size, out_size;
   9.424 +
   9.425 +	/* cannot perform a write until the read has cleared
   9.426 +	   either via tpm_read or a user_read_timer timeout */
   9.427 +	while (atomic_read(&chip->data_pending) != 0)
   9.428 +		msleep(TPM_TIMEOUT);
   9.429 +
   9.430 +	down(&chip->buffer_mutex);
   9.431 +
   9.432 +	if (in_size > chip->vendor->buffersize)
   9.433 +		in_size = chip->vendor->buffersize;
   9.434 +
   9.435 +	if (copy_from_user
   9.436 +	    (chip->data_buffer, (void __user *) buf, in_size)) {
   9.437 +		up(&chip->buffer_mutex);
   9.438 +		return -EFAULT;
   9.439 +	}
   9.440 +
   9.441 +	/* atomic tpm command send and result receive */
   9.442 +	out_size = tpm_transmit(chip, chip->data_buffer, 
   9.443 +	                        chip->vendor->buffersize);
   9.444 +
   9.445 +	atomic_set(&chip->data_pending, out_size);
   9.446 +	atomic_set(&chip->data_position, 0);
   9.447 +	up(&chip->buffer_mutex);
   9.448 +
   9.449 +	/* Set a timeout by which the reader must come claim the result */
   9.450 +	mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
   9.451 +
   9.452 +	return in_size;
   9.453 +}
   9.454 +
   9.455 +EXPORT_SYMBOL_GPL(tpm_write);
   9.456 +
   9.457 +ssize_t tpm_read(struct file * file, char __user * buf,
   9.458 +		 size_t size, loff_t * off)
   9.459 +{
   9.460 +	struct tpm_chip *chip = file->private_data;
   9.461 +	int ret_size;
   9.462 +	int pos, pending = 0;
   9.463 +
   9.464 +	ret_size = atomic_read(&chip->data_pending);
   9.465 +	if (ret_size > 0) {	/* relay data */
   9.466 +		if (size < ret_size)
   9.467 +			ret_size = size;
   9.468 +
   9.469 +		pos = atomic_read(&chip->data_position);
   9.470 +
   9.471 +		down(&chip->buffer_mutex);
   9.472 +		if (copy_to_user
   9.473 +		    ((void __user *) buf, &chip->data_buffer[pos], ret_size)) {
   9.474 +			ret_size = -EFAULT;
   9.475 +		} else {
   9.476 +			pending = atomic_read(&chip->data_pending) - ret_size;
   9.477 +			if ( pending ) {
   9.478 +				atomic_set( &chip->data_pending, pending );
   9.479 +				atomic_set( &chip->data_position, pos+ret_size );
   9.480 +			}
   9.481 +		}
   9.482 +		up(&chip->buffer_mutex);
   9.483 +	}
   9.484 +	
   9.485 +	if ( ret_size <= 0 || pending == 0 ) {
   9.486 +		atomic_set( &chip->data_pending, 0 );
   9.487 +		del_singleshot_timer_sync(&chip->user_read_timer);
   9.488 +	}
   9.489 +
   9.490 +	return ret_size;
   9.491 +}
   9.492 +
   9.493 +EXPORT_SYMBOL_GPL(tpm_read);
   9.494 +
   9.495 +void tpm_remove_hardware(struct device *dev)
   9.496 +{
   9.497 +	struct tpm_chip *chip = dev_get_drvdata(dev);
   9.498 +
   9.499 +	if (chip == NULL) {
   9.500 +		dev_err(dev, "No device data found\n");
   9.501 +		return;
   9.502 +	}
   9.503 +
   9.504 +	spin_lock(&driver_lock);
   9.505 +
   9.506 +	list_del(&chip->list);
   9.507 +
   9.508 +	spin_unlock(&driver_lock);
   9.509 +
   9.510 +	dev_set_drvdata(dev, NULL);
   9.511 +	misc_deregister(&chip->vendor->miscdev);
   9.512 +	kfree(chip->vendor->miscdev.name);
   9.513 +
   9.514 +	sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
   9.515 +
   9.516 +	dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
   9.517 +
   9.518 +	kfree(chip);
   9.519 +
   9.520 +	put_device(dev);
   9.521 +}
   9.522 +
   9.523 +EXPORT_SYMBOL_GPL(tpm_remove_hardware);
   9.524 +
   9.525 +static u8 savestate[] = {
   9.526 +	0, 193,			/* TPM_TAG_RQU_COMMAND */
   9.527 +	0, 0, 0, 10,		/* blob length (in bytes) */
   9.528 +	0, 0, 0, 152		/* TPM_ORD_SaveState */
   9.529 +};
   9.530 +
   9.531 +/*
   9.532 + * We are about to suspend. Save the TPM state
   9.533 + * so that it can be restored.
   9.534 + */
   9.535 +int tpm_pm_suspend(struct pci_dev *pci_dev, pm_message_t pm_state)
   9.536 +{
   9.537 +	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
   9.538 +	if (chip == NULL)
   9.539 +		return -ENODEV;
   9.540 +
   9.541 +	tpm_transmit(chip, savestate, sizeof(savestate));
   9.542 +	return 0;
   9.543 +}
   9.544 +
   9.545 +EXPORT_SYMBOL_GPL(tpm_pm_suspend);
   9.546 +
   9.547 +/*
   9.548 + * Resume from a power safe. The BIOS already restored
   9.549 + * the TPM state.
   9.550 + */
   9.551 +int tpm_pm_resume(struct pci_dev *pci_dev)
   9.552 +{
   9.553 +	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
   9.554 +
   9.555 +	if (chip == NULL)
   9.556 +		return -ENODEV;
   9.557 +
   9.558 +	return 0;
   9.559 +}
   9.560 +
   9.561 +EXPORT_SYMBOL_GPL(tpm_pm_resume);
   9.562 +
   9.563 +/*
   9.564 + * Called from tpm_<specific>.c probe function only for devices 
   9.565 + * the driver has determined it should claim.  Prior to calling
   9.566 + * this function the specific probe function has called pci_enable_device
   9.567 + * upon errant exit from this function specific probe function should call
   9.568 + * pci_disable_device
   9.569 + */
   9.570 +int tpm_register_hardware(struct device *dev,
   9.571 +			  struct tpm_vendor_specific *entry)
   9.572 +{
   9.573 +#define DEVNAME_SIZE 7
   9.574 +
   9.575 +	char *devname;
   9.576 +	struct tpm_chip *chip;
   9.577 +	int i, j;
   9.578 +
   9.579 +	/* Driver specific per-device data */
   9.580 +	chip = kmalloc(sizeof(*chip), GFP_KERNEL);
   9.581 +	if (chip == NULL)
   9.582 +		return -ENOMEM;
   9.583 +
   9.584 +	memset(chip, 0, sizeof(struct tpm_chip));
   9.585 +
   9.586 +	init_MUTEX(&chip->buffer_mutex);
   9.587 +	init_MUTEX(&chip->tpm_mutex);
   9.588 +	INIT_LIST_HEAD(&chip->list);
   9.589 +
   9.590 +	init_timer(&chip->user_read_timer);
   9.591 +	chip->user_read_timer.function = user_reader_timeout;
   9.592 +	chip->user_read_timer.data = (unsigned long) chip;
   9.593 +
   9.594 +	chip->vendor = entry;
   9.595 +	
   9.596 +	if (entry->buffersize < TPM_MIN_BUFSIZE) {
   9.597 +		entry->buffersize = TPM_MIN_BUFSIZE;
   9.598 +	} else if (entry->buffersize > TPM_MAX_BUFSIZE) {
   9.599 +		entry->buffersize = TPM_MAX_BUFSIZE;
   9.600 +	}
   9.601 +
   9.602 +	chip->dev_num = -1;
   9.603 +
   9.604 +	for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
   9.605 +		for (j = 0; j < 8 * sizeof(int); j++)
   9.606 +			if ((dev_mask[i] & (1 << j)) == 0) {
   9.607 +				chip->dev_num =
   9.608 +				    i * TPM_NUM_MASK_ENTRIES + j;
   9.609 +				dev_mask[i] |= 1 << j;
   9.610 +				goto dev_num_search_complete;
   9.611 +			}
   9.612 +
   9.613 +dev_num_search_complete:
   9.614 +	if (chip->dev_num < 0) {
   9.615 +		dev_err(dev,
   9.616 +			"No available tpm device numbers\n");
   9.617 +		kfree(chip);
   9.618 +		return -ENODEV;
   9.619 +	} else if (chip->dev_num == 0)
   9.620 +		chip->vendor->miscdev.minor = TPM_MINOR;
   9.621 +	else
   9.622 +		chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
   9.623 +
   9.624 +	devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
   9.625 +	scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
   9.626 +	chip->vendor->miscdev.name = devname;
   9.627 +
   9.628 +	chip->vendor->miscdev.dev = dev;
   9.629 +	chip->dev = get_device(dev);
   9.630 +
   9.631 +	if (misc_register(&chip->vendor->miscdev)) {
   9.632 +		dev_err(chip->dev,
   9.633 +			"unable to misc_register %s, minor %d\n",
   9.634 +			chip->vendor->miscdev.name,
   9.635 +			chip->vendor->miscdev.minor);
   9.636 +		put_device(dev);
   9.637 +		kfree(chip);
   9.638 +		dev_mask[i] &= !(1 << j);
   9.639 +		return -ENODEV;
   9.640 +	}
   9.641 +
   9.642 +	spin_lock(&driver_lock);
   9.643 +
   9.644 +	dev_set_drvdata(dev, chip);
   9.645 +
   9.646 +	list_add(&chip->list, &tpm_chip_list);
   9.647 +
   9.648 +	spin_unlock(&driver_lock);
   9.649 +
   9.650 +	sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
   9.651 +
   9.652 +	return 0;
   9.653 +}
   9.654 +
   9.655 +EXPORT_SYMBOL_GPL(tpm_register_hardware);
   9.656 +
   9.657 +MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
   9.658 +MODULE_DESCRIPTION("TPM Driver");
   9.659 +MODULE_VERSION("2.0");
   9.660 +MODULE_LICENSE("GPL");
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h	Wed Oct 05 14:40:35 2005 +0100
    10.3 @@ -0,0 +1,118 @@
    10.4 +/*
    10.5 + * Copyright (C) 2004 IBM Corporation
    10.6 + *
    10.7 + * Authors:
    10.8 + * Leendert van Doorn <leendert@watson.ibm.com>
    10.9 + * Dave Safford <safford@watson.ibm.com>
   10.10 + * Reiner Sailer <sailer@watson.ibm.com>
   10.11 + * Kylene Hall <kjhall@us.ibm.com>
   10.12 + *
   10.13 + * Maintained by: <tpmdd_devel@lists.sourceforge.net>
   10.14 + *
   10.15 + * Device driver for TCG/TCPA TPM (trusted platform module).
   10.16 + * Specifications at www.trustedcomputinggroup.org	 
   10.17 + *
   10.18 + * This program is free software; you can redistribute it and/or
   10.19 + * modify it under the terms of the GNU General Public License as
   10.20 + * published by the Free Software Foundation, version 2 of the
   10.21 + * License.
   10.22 + * 
   10.23 + */
   10.24 +#include <linux/module.h>
   10.25 +#include <linux/version.h>
   10.26 +#include <linux/pci.h>
   10.27 +#include <linux/delay.h>
   10.28 +#include <linux/fs.h>
   10.29 +#include <linux/miscdevice.h>
   10.30 +
   10.31 +enum tpm_timeout {
   10.32 +	TPM_TIMEOUT = 5,	/* msecs */
   10.33 +};
   10.34 +
   10.35 +/* TPM addresses */
   10.36 +enum tpm_addr {
   10.37 +	TPM_SUPERIO_ADDR = 0x2E,
   10.38 +	TPM_ADDR = 0x4E,
   10.39 +};
   10.40 +
   10.41 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
   10.42 +extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
   10.43 +				char *);
   10.44 +extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
   10.45 +				char *);
   10.46 +extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
   10.47 +				char *);
   10.48 +extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
   10.49 +				const char *, size_t);
   10.50 +#else
   10.51 +extern ssize_t tpm_show_pubek(struct device *,
   10.52 +				char *);
   10.53 +extern ssize_t tpm_show_pcrs(struct device *,
   10.54 +				char *);
   10.55 +extern ssize_t tpm_show_caps(struct device *,
   10.56 +				char *);
   10.57 +extern ssize_t tpm_store_cancel(struct device *,
   10.58 +				const char *, size_t);
   10.59 +#endif
   10.60 +
   10.61 +struct tpm_chip;
   10.62 +
   10.63 +struct tpm_vendor_specific {
   10.64 +	u8 req_complete_mask;
   10.65 +	u8 req_complete_val;
   10.66 +	u8 req_canceled;
   10.67 +	u16 base;		/* TPM base address */
   10.68 +	int drv_type;
   10.69 +	u32 buffersize;
   10.70 +
   10.71 +	int (*recv) (struct tpm_chip *, u8 *, size_t);
   10.72 +	int (*send) (struct tpm_chip *, u8 *, size_t);
   10.73 +	void (*cancel) (struct tpm_chip *);
   10.74 +	u8 (*status) (struct tpm_chip *);
   10.75 +	struct miscdevice miscdev;
   10.76 +	struct attribute_group *attr_group;
   10.77 +};
   10.78 +
   10.79 +struct tpm_chip {
   10.80 +	struct device *dev;	/* Device stuff */
   10.81 +
   10.82 +	int dev_num;		/* /dev/tpm# */
   10.83 +	int num_opens;		/* only one allowed */
   10.84 +	int time_expired;
   10.85 +
   10.86 +	/* Data passed to and from the tpm via the read/write calls */
   10.87 +	u8 *data_buffer;
   10.88 +	atomic_t data_pending;
   10.89 +	atomic_t data_position;
   10.90 +	struct semaphore buffer_mutex;
   10.91 +
   10.92 +	struct timer_list user_read_timer;	/* user needs to claim result */
   10.93 +	struct semaphore tpm_mutex;	/* tpm is processing */
   10.94 +
   10.95 +	struct tpm_vendor_specific *vendor;
   10.96 +
   10.97 +	struct list_head list;
   10.98 +};
   10.99 +
  10.100 +static inline int tpm_read_index(int base, int index)
  10.101 +{
  10.102 +	outb(index, base);
  10.103 +	return inb(base+1) & 0xFF;
  10.104 +}
  10.105 +
  10.106 +static inline void tpm_write_index(int base, int index, int value)
  10.107 +{
  10.108 +	outb(index, base);
  10.109 +	outb(value & 0xFF, base+1);
  10.110 +}
  10.111 +
  10.112 +extern int tpm_register_hardware(struct device *,
  10.113 +				 struct tpm_vendor_specific *);
  10.114 +extern int tpm_open(struct inode *, struct file *);
  10.115 +extern int tpm_release(struct inode *, struct file *);
  10.116 +extern ssize_t tpm_write(struct file *, const char __user *, size_t,
  10.117 +			 loff_t *);
  10.118 +extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
  10.119 +extern void tpm_remove_hardware(struct device *);
  10.120 +extern int tpm_pm_suspend(struct pci_dev *, pm_message_t);
  10.121 +extern int tpm_pm_resume(struct pci_dev *);
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_atmel.c	Wed Oct 05 14:40:35 2005 +0100
    11.3 @@ -0,0 +1,263 @@
    11.4 +/*
    11.5 + * Copyright (C) 2004 IBM Corporation
    11.6 + *
    11.7 + * Authors:
    11.8 + * Leendert van Doorn <leendert@watson.ibm.com>
    11.9 + * Dave Safford <safford@watson.ibm.com>
   11.10 + * Reiner Sailer <sailer@watson.ibm.com>
   11.11 + * Kylene Hall <kjhall@us.ibm.com>
   11.12 + *
   11.13 + * Maintained by: <tpmdd_devel@lists.sourceforge.net>
   11.14 + *
   11.15 + * Device driver for TCG/TCPA TPM (trusted platform module).
   11.16 + * Specifications at www.trustedcomputinggroup.org	 
   11.17 + *
   11.18 + * This program is free software; you can redistribute it and/or
   11.19 + * modify it under the terms of the GNU General Public License as
   11.20 + * published by the Free Software Foundation, version 2 of the
   11.21 + * License.
   11.22 + * 
   11.23 + */
   11.24 +
   11.25 +#include "tpm.h"
   11.26 +
   11.27 +/* Atmel definitions */
   11.28 +enum tpm_atmel_addr {
   11.29 +	TPM_ATMEL_BASE_ADDR_LO = 0x08,
   11.30 +	TPM_ATMEL_BASE_ADDR_HI = 0x09
   11.31 +};
   11.32 +
   11.33 +/* write status bits */
   11.34 +enum tpm_atmel_write_status {
   11.35 +	ATML_STATUS_ABORT = 0x01,
   11.36 +	ATML_STATUS_LASTBYTE = 0x04
   11.37 +};
   11.38 +/* read status bits */
   11.39 +enum tpm_atmel_read_status {
   11.40 +	ATML_STATUS_BUSY = 0x01,
   11.41 +	ATML_STATUS_DATA_AVAIL = 0x02,
   11.42 +	ATML_STATUS_REWRITE = 0x04,
   11.43 +	ATML_STATUS_READY = 0x08
   11.44 +};
   11.45 +
   11.46 +static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
   11.47 +{
   11.48 +	u8 status, *hdr = buf;
   11.49 +	u32 size;
   11.50 +	int i;
   11.51 +	__be32 *native_size;
   11.52 +
   11.53 +	/* start reading header */
   11.54 +	if (count < 6)
   11.55 +		return -EIO;
   11.56 +
   11.57 +	for (i = 0; i < 6; i++) {
   11.58 +		status = inb(chip->vendor->base + 1);
   11.59 +		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
   11.60 +			dev_err(chip->dev,
   11.61 +				"error reading header\n");
   11.62 +			return -EIO;
   11.63 +		}
   11.64 +		*buf++ = inb(chip->vendor->base);
   11.65 +	}
   11.66 +
   11.67 +	/* size of the data received */
   11.68 +	native_size = (__force __be32 *) (hdr + 2);
   11.69 +	size = be32_to_cpu(*native_size);
   11.70 +
   11.71 +	if (count < size) {
   11.72 +		dev_err(chip->dev,
   11.73 +			"Recv size(%d) less than available space\n", size);
   11.74 +		for (; i < size; i++) {	/* clear the waiting data anyway */
   11.75 +			status = inb(chip->vendor->base + 1);
   11.76 +			if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
   11.77 +				dev_err(chip->dev,
   11.78 +					"error reading data\n");
   11.79 +				return -EIO;
   11.80 +			}
   11.81 +		}
   11.82 +		return -EIO;
   11.83 +	}
   11.84 +
   11.85 +	/* read all the data available */
   11.86 +	for (; i < size; i++) {
   11.87 +		status = inb(chip->vendor->base + 1);
   11.88 +		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
   11.89 +			dev_err(chip->dev,
   11.90 +				"error reading data\n");
   11.91 +			return -EIO;
   11.92 +		}
   11.93 +		*buf++ = inb(chip->vendor->base);
   11.94 +	}
   11.95 +
   11.96 +	/* make sure data available is gone */
   11.97 +	status = inb(chip->vendor->base + 1);
   11.98 +	if (status & ATML_STATUS_DATA_AVAIL) {
   11.99 +		dev_err(chip->dev, "data available is stuck\n");
  11.100 +		return -EIO;
  11.101 +	}
  11.102 +
  11.103 +	return size;
  11.104 +}
  11.105 +
  11.106 +static int tpm_atml_send(struct tpm_chip *chip, u8 * buf, size_t count)
  11.107 +{
  11.108 +	int i;
  11.109 +
  11.110 +	dev_dbg(chip->dev, "tpm_atml_send:\n");
  11.111 +	for (i = 0; i < count; i++) {
  11.112 +		dev_dbg(chip->dev, "%d 0x%x(%d)\n",  i, buf[i], buf[i]);
  11.113 +		outb(buf[i], chip->vendor->base);
  11.114 +	}
  11.115 +
  11.116 +	return count;
  11.117 +}
  11.118 +
  11.119 +static void tpm_atml_cancel(struct tpm_chip *chip)
  11.120 +{
  11.121 +	outb(ATML_STATUS_ABORT, chip->vendor->base + 1);
  11.122 +}
  11.123 +
  11.124 +static u8 tpm_atml_status(struct tpm_chip *chip)
  11.125 +{
  11.126 +	return inb(chip->vendor->base + 1);
  11.127 +}
  11.128 +
  11.129 +static struct file_operations atmel_ops = {
  11.130 +	.owner = THIS_MODULE,
  11.131 +	.llseek = no_llseek,
  11.132 +	.open = tpm_open,
  11.133 +	.read = tpm_read,
  11.134 +	.write = tpm_write,
  11.135 +	.release = tpm_release,
  11.136 +};
  11.137 +
  11.138 +static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
  11.139 +static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
  11.140 +static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
  11.141 +static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
  11.142 +
  11.143 +static struct attribute* atmel_attrs[] = {
  11.144 +	&dev_attr_pubek.attr,
  11.145 +	&dev_attr_pcrs.attr,
  11.146 +	&dev_attr_caps.attr,
  11.147 +	&dev_attr_cancel.attr,
  11.148 +	0,
  11.149 +};
  11.150 +
  11.151 +static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
  11.152 +
  11.153 +static struct tpm_vendor_specific tpm_atmel = {
  11.154 +	.recv = tpm_atml_recv,
  11.155 +	.send = tpm_atml_send,
  11.156 +	.cancel = tpm_atml_cancel,
  11.157 +	.status = tpm_atml_status,
  11.158 +	.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
  11.159 +	.req_complete_val = ATML_STATUS_DATA_AVAIL,
  11.160 +	.req_canceled = ATML_STATUS_READY,
  11.161 +	.attr_group = &atmel_attr_grp,
  11.162 +	.miscdev = { .fops = &atmel_ops, },
  11.163 +};
  11.164 +
  11.165 +static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
  11.166 +				   const struct pci_device_id *pci_id)
  11.167 +{
  11.168 +	u8 version[4];
  11.169 +	int rc = 0;
  11.170 +	int lo, hi;
  11.171 +
  11.172 +	if (pci_enable_device(pci_dev))
  11.173 +		return -EIO;
  11.174 +
  11.175 +	lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
  11.176 +	hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
  11.177 +
  11.178 +	tpm_atmel.base = (hi<<8)|lo;
  11.179 +	dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
  11.180 +
  11.181 +	/* verify that it is an Atmel part */
  11.182 +	if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
  11.183 +	    || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
  11.184 +		rc = -ENODEV;
  11.185 +		goto out_err;
  11.186 +	}
  11.187 +
  11.188 +	/* query chip for its version number */
  11.189 +	if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) {
  11.190 +		version[1] = tpm_read_index(TPM_ADDR, 0x01);
  11.191 +		version[2] = tpm_read_index(TPM_ADDR, 0x02);
  11.192 +		version[3] = tpm_read_index(TPM_ADDR, 0x03);
  11.193 +	} else {
  11.194 +		dev_info(&pci_dev->dev, "version query failed\n");
  11.195 +		rc = -ENODEV;
  11.196 +		goto out_err;
  11.197 +	}
  11.198 +
  11.199 +	if ((rc = tpm_register_hardware(&pci_dev->dev, &tpm_atmel)) < 0)
  11.200 +		goto out_err;
  11.201 +
  11.202 +	dev_info(&pci_dev->dev,
  11.203 +		 "Atmel TPM version %d.%d.%d.%d\n", version[0], version[1],
  11.204 +		 version[2], version[3]);
  11.205 +
  11.206 +	return 0;
  11.207 +out_err:
  11.208 +	pci_disable_device(pci_dev);
  11.209 +	return rc;
  11.210 +}
  11.211 +
  11.212 +static void __devexit tpm_atml_remove(struct pci_dev *pci_dev) 
  11.213 +{
  11.214 +	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
  11.215 +
  11.216 +	if ( chip )
  11.217 +		tpm_remove_hardware(chip->dev);
  11.218 +}
  11.219 +
  11.220 +static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
  11.221 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
  11.222 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
  11.223 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
  11.224 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
  11.225 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
  11.226 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
  11.227 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
  11.228 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
  11.229 +	{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
  11.230 +#ifndef PCI_DEVICE_ID_SERVERWORKS_CSB6LPC
  11.231 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
  11.232 +#else
  11.233 +#warning Remove the define of PCI_DEVICE_ID_SERVERWORKS_CSB6LPC
  11.234 +#endif
  11.235 +	{PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
  11.236 +	{0,}
  11.237 +};
  11.238 +
  11.239 +MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
  11.240 +
  11.241 +static struct pci_driver atmel_pci_driver = {
  11.242 +	.name = "tpm_atmel",
  11.243 +	.id_table = tpm_pci_tbl,
  11.244 +	.probe = tpm_atml_init,
  11.245 +	.remove = __devexit_p(tpm_atml_remove),
  11.246 +	.suspend = tpm_pm_suspend,
  11.247 +	.resume = tpm_pm_resume,
  11.248 +};
  11.249 +
  11.250 +static int __init init_atmel(void)
  11.251 +{
  11.252 +	return pci_register_driver(&atmel_pci_driver);
  11.253 +}
  11.254 +
  11.255 +static void __exit cleanup_atmel(void)
  11.256 +{
  11.257 +	pci_unregister_driver(&atmel_pci_driver);
  11.258 +}
  11.259 +
  11.260 +fs_initcall(init_atmel);
  11.261 +module_exit(cleanup_atmel);
  11.262 +
  11.263 +MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
  11.264 +MODULE_DESCRIPTION("TPM Driver");
  11.265 +MODULE_VERSION("2.0");
  11.266 +MODULE_LICENSE("GPL");
    12.1 --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.c	Wed Oct 05 14:38:19 2005 +0100
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,751 +0,0 @@
    12.4 -/*
    12.5 - * Copyright (C) 2004 IBM Corporation
    12.6 - *
    12.7 - * Authors:
    12.8 - * Leendert van Doorn <leendert@watson.ibm.com>
    12.9 - * Dave Safford <safford@watson.ibm.com>
   12.10 - * Reiner Sailer <sailer@watson.ibm.com>
   12.11 - * Kylene Hall <kjhall@us.ibm.com>
   12.12 - *
   12.13 - * Maintained by: <tpmdd_devel@lists.sourceforge.net>
   12.14 - *
   12.15 - * Device driver for TCG/TCPA TPM (trusted platform module).
   12.16 - * Specifications at www.trustedcomputinggroup.org
   12.17 - *
   12.18 - * This program is free software; you can redistribute it and/or
   12.19 - * modify it under the terms of the GNU General Public License as
   12.20 - * published by the Free Software Foundation, version 2 of the
   12.21 - * License.
   12.22 - *
   12.23 - * Note, the TPM chip is not interrupt driven (only polling)
   12.24 - * and can have very long timeouts (minutes!). Hence the unusual
   12.25 - * calls to schedule_timeout.
   12.26 - *
   12.27 - */
   12.28 -
   12.29 -#include <linux/sched.h>
   12.30 -#include <linux/poll.h>
   12.31 -#include <linux/spinlock.h>
   12.32 -#include "tpm_nopci.h"
   12.33 -
   12.34 -enum {
   12.35 -	TPM_MINOR = 224,	/* officially assigned */
   12.36 -	TPM_MIN_BUFSIZE = 2048,
   12.37 -	TPM_MAX_BUFSIZE = 65536,
   12.38 -	TPM_NUM_DEVICES = 256,
   12.39 -	TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
   12.40 -};
   12.41 -
   12.42 -  /* PCI configuration addresses */
   12.43 -enum {
   12.44 -	PCI_GEN_PMCON_1 = 0xA0,
   12.45 -	PCI_GEN1_DEC = 0xE4,
   12.46 -	PCI_LPC_EN = 0xE6,
   12.47 -	PCI_GEN2_DEC = 0xEC
   12.48 -};
   12.49 -
   12.50 -enum {
   12.51 -	TPM_LOCK_REG = 0x0D,
   12.52 -	TPM_INTERUPT_REG = 0x0A,
   12.53 -	TPM_BASE_ADDR_LO = 0x08,
   12.54 -	TPM_BASE_ADDR_HI = 0x09,
   12.55 -	TPM_UNLOCK_VALUE = 0x55,
   12.56 -	TPM_LOCK_VALUE = 0xAA,
   12.57 -	TPM_DISABLE_INTERUPT_VALUE = 0x00
   12.58 -};
   12.59 -
   12.60 -static LIST_HEAD(tpm_chip_list);
   12.61 -static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
   12.62 -static int dev_mask[32];
   12.63 -
   12.64 -static void user_reader_timeout(unsigned long ptr)
   12.65 -{
   12.66 -	struct tpm_chip *chip = (struct tpm_chip *) ptr;
   12.67 -
   12.68 -	down(&chip->buffer_mutex);
   12.69 -	atomic_set(&chip->data_pending, 0);
   12.70 -	memset(chip->data_buffer, 0, chip->vendor->buffersize);
   12.71 -	up(&chip->buffer_mutex);
   12.72 -}
   12.73 -
   12.74 -void tpm_time_expired(unsigned long ptr)
   12.75 -{
   12.76 -	int *exp = (int *) ptr;
   12.77 -	*exp = 1;
   12.78 -}
   12.79 -
   12.80 -EXPORT_SYMBOL_GPL(tpm_time_expired);
   12.81 -
   12.82 -
   12.83 -/*
   12.84 - * This function should be used by other kernel subsystems attempting to use the tpm through the tpm_transmit interface.
   12.85 - * A call to this function will return the chip structure corresponding to the TPM you are looking for that can then be sent with your command to tpm_transmit.
   12.86 - * Passing 0 as the argument corresponds to /dev/tpm0 and thus the first and probably primary TPM on the system.  Passing 1 corresponds to /dev/tpm1 and the next TPM discovered.  If a TPM with the given chip_num does not exist NULL will be returned.
   12.87 - */
   12.88 -struct tpm_chip* tpm_chip_lookup(int chip_num)
   12.89 -{
   12.90 -
   12.91 -	struct tpm_chip *pos;
   12.92 -	list_for_each_entry(pos, &tpm_chip_list, list)
   12.93 -		if (pos->dev_num == chip_num ||
   12.94 -		    chip_num == TPM_ANY_NUM)
   12.95 -			return pos;
   12.96 -
   12.97 -	return NULL;
   12.98 -
   12.99 -}
  12.100 -
  12.101 -/*
  12.102 - * Internal kernel interface to transmit TPM commands
  12.103 - */
  12.104 -ssize_t tpm_transmit(struct tpm_chip * chip, const char *buf,
  12.105 -		     size_t bufsiz)
  12.106 -{
  12.107 -	ssize_t rc;
  12.108 -	u32 count;
  12.109 -	unsigned long stop;
  12.110 -
  12.111 -	count = be32_to_cpu(*((__be32 *) (buf + 2)));
  12.112 -
  12.113 -	if (count == 0)
  12.114 -		return -ENODATA;
  12.115 -	if (count > bufsiz) {
  12.116 -		dev_err(chip->dev,
  12.117 -			"invalid count value %x %x \n", count, bufsiz);
  12.118 -		return -E2BIG;
  12.119 -	}
  12.120 -
  12.121 -	dev_dbg(chip->dev, "TPM Ordinal: %d\n",
  12.122 -		be32_to_cpu(*((__be32 *) (buf + 6))));
  12.123 -	dev_dbg(chip->dev, "Chip Status: %x\n",
  12.124 -		inb(chip->vendor->base + 1));
  12.125 -
  12.126 -	down(&chip->tpm_mutex);
  12.127 -
  12.128 -	if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
  12.129 -		dev_err(chip->dev,
  12.130 -			"tpm_transmit: tpm_send: error %d\n", rc);
  12.131 -		goto out;
  12.132 -	}
  12.133 -
  12.134 -	stop = jiffies + 2 * 60 * HZ;
  12.135 -	do {
  12.136 -		u8 status = chip->vendor->status(chip);
  12.137 -		if ((status & chip->vendor->req_complete_mask) ==
  12.138 -		    chip->vendor->req_complete_val) {
  12.139 -			goto out_recv;
  12.140 -		}
  12.141 -
  12.142 -		if ((status == chip->vendor->req_canceled)) {
  12.143 -			dev_err(chip->dev, "Operation Canceled\n");
  12.144 -			rc = -ECANCELED;
  12.145 -			goto out;
  12.146 -		}
  12.147 -
  12.148 -		msleep(TPM_TIMEOUT);	/* CHECK */
  12.149 -		rmb();
  12.150 -	}
  12.151 -	while (time_before(jiffies, stop));
  12.152 -
  12.153 -
  12.154 -	chip->vendor->cancel(chip);
  12.155 -	dev_err(chip->dev, "Operation Timed out\n");
  12.156 -	rc = -ETIME;
  12.157 -	goto out;
  12.158 -
  12.159 -out_recv:
  12.160 -	rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
  12.161 -	if (rc < 0)
  12.162 -		dev_err(chip->dev,
  12.163 -			"tpm_transmit: tpm_recv: error %d\n", rc);
  12.164 -	atomic_set(&chip->data_position, 0);
  12.165 -
  12.166 -out:
  12.167 -	up(&chip->tpm_mutex);
  12.168 -	return rc;
  12.169 -}
  12.170 -
  12.171 -EXPORT_SYMBOL_GPL(tpm_transmit);
  12.172 -
  12.173 -#define TPM_DIGEST_SIZE 20
  12.174 -#define CAP_PCR_RESULT_SIZE 18
  12.175 -static const u8 cap_pcr[] = {
  12.176 -	0, 193,			/* TPM_TAG_RQU_COMMAND */
  12.177 -	0, 0, 0, 22,		/* length */
  12.178 -	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
  12.179 -	0, 0, 0, 5,
  12.180 -	0, 0, 0, 4,
  12.181 -	0, 0, 1, 1
  12.182 -};
  12.183 -
  12.184 -#define READ_PCR_RESULT_SIZE 30
  12.185 -static const u8 pcrread[] = {
  12.186 -	0, 193,			/* TPM_TAG_RQU_COMMAND */
  12.187 -	0, 0, 0, 14,		/* length */
  12.188 -	0, 0, 0, 21,		/* TPM_ORD_PcrRead */
  12.189 -	0, 0, 0, 0		/* PCR index */
  12.190 -};
  12.191 -
  12.192 -ssize_t tpm_show_pcrs(struct device *dev, char *buf)
  12.193 -{
  12.194 -	u8 data[READ_PCR_RESULT_SIZE];
  12.195 -	ssize_t len;
  12.196 -	int i, j, num_pcrs;
  12.197 -	__be32 index;
  12.198 -	char *str = buf;
  12.199 -
  12.200 -	struct tpm_chip *chip = dev_get_drvdata(dev);
  12.201 -	if (chip == NULL)
  12.202 -		return -ENODEV;
  12.203 -
  12.204 -	memcpy(data, cap_pcr, sizeof(cap_pcr));
  12.205 -	if ((len = tpm_transmit(chip, data, sizeof(data)))
  12.206 -	    < CAP_PCR_RESULT_SIZE)
  12.207 -		return len;
  12.208 -
  12.209 -	num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
  12.210 -
  12.211 -	for (i = 0; i < num_pcrs; i++) {
  12.212 -		memcpy(data, pcrread, sizeof(pcrread));
  12.213 -		index = cpu_to_be32(i);
  12.214 -		memcpy(data + 10, &index, 4);
  12.215 -		if ((len = tpm_transmit(chip, data, sizeof(data)))
  12.216 -		    < READ_PCR_RESULT_SIZE)
  12.217 -			return len;
  12.218 -		str += sprintf(str, "PCR-%02d: ", i);
  12.219 -		for (j = 0; j < TPM_DIGEST_SIZE; j++)
  12.220 -			str += sprintf(str, "%02X ", *(data + 10 + j));
  12.221 -		str += sprintf(str, "\n");
  12.222 -	}
  12.223 -	return str - buf;
  12.224 -}
  12.225 -
  12.226 -EXPORT_SYMBOL_GPL(tpm_show_pcrs);
  12.227 -
  12.228 -/*
  12.229 - * Return 0 on success.  On error pass along error code.
  12.230 - * chip_id Upper 2 bytes equal ANY, HW_ONLY or SW_ONLY
  12.231 - * Lower 2 bytes equal tpm idx # or AN&
  12.232 - * res_buf must fit a TPM_PCR (20 bytes) or NULL if you don't care
  12.233 - */
  12.234 -int tpm_pcr_read( u32 chip_id, int pcr_idx, u8* res_buf, int res_buf_size )
  12.235 -{
  12.236 -	u8 data[READ_PCR_RESULT_SIZE];
  12.237 -	int rc;
  12.238 -	__be32 index;
  12.239 -	int chip_num = chip_id & TPM_CHIP_NUM_MASK;
  12.240 -	struct tpm_chip* chip;
  12.241 -
  12.242 -	if ( res_buf && res_buf_size < TPM_DIGEST_SIZE )
  12.243 -		return -ENOSPC;
  12.244 -	if ( (chip = tpm_chip_lookup( chip_num /*,
  12.245 -				       chip_id >> TPM_CHIP_TYPE_SHIFT*/ ) ) == NULL ) {
  12.246 -		printk("chip %d not found.\n",chip_num);
  12.247 -		return -ENODEV;
  12.248 -	}
  12.249 -	memcpy(data, pcrread, sizeof(pcrread));
  12.250 -	index = cpu_to_be32(pcr_idx);
  12.251 -	memcpy(data + 10, &index, 4);
  12.252 -	if ((rc = tpm_transmit(chip, data, sizeof(data))) > 0 )
  12.253 -		rc = be32_to_cpu(*((u32*)(data+6)));
  12.254 -
  12.255 -	if ( rc == 0 && res_buf )
  12.256 -		memcpy(res_buf, data+10, TPM_DIGEST_SIZE);
  12.257 -	return rc;
  12.258 -}
  12.259 -EXPORT_SYMBOL_GPL(tpm_pcr_read);
  12.260 -
  12.261 -#define EXTEND_PCR_SIZE 34
  12.262 -static const u8 pcrextend[] = {
  12.263 -	0, 193,		 		 		 /* TPM_TAG_RQU_COMMAND */
  12.264 -	0, 0, 0, 34,		 		 /* length */
  12.265 -	0, 0, 0, 20,		 		 /* TPM_ORD_Extend */
  12.266 -	0, 0, 0, 0		 		 /* PCR index */
  12.267 -};
  12.268 -
  12.269 -/*
  12.270 - * Return 0 on success.  On error pass along error code.
  12.271 - * chip_id Upper 2 bytes equal ANY, HW_ONLY or SW_ONLY
  12.272 - * Lower 2 bytes equal tpm idx # or ANY
  12.273 - */
  12.274 -int tpm_pcr_extend(u32 chip_id, int pcr_idx, const u8* hash)
  12.275 -{
  12.276 -	u8 data[EXTEND_PCR_SIZE];
  12.277 -	int rc;
  12.278 -	__be32 index;
  12.279 -	int chip_num = chip_id & TPM_CHIP_NUM_MASK;
  12.280 -	struct tpm_chip* chip;
  12.281 -
  12.282 -	if ( (chip = tpm_chip_lookup( chip_num /*,
  12.283 -				      chip_id >> TPM_CHIP_TYPE_SHIFT */)) == NULL )
  12.284 -		return -ENODEV;
  12.285 -
  12.286 -	memcpy(data, pcrextend, sizeof(pcrextend));
  12.287 -	index = cpu_to_be32(pcr_idx);
  12.288 -	memcpy(data + 10, &index, 4);
  12.289 -	memcpy( data + 14, hash, TPM_DIGEST_SIZE );
  12.290 -	if ((rc = tpm_transmit(chip, data, sizeof(data))) > 0 )
  12.291 -		rc = be32_to_cpu(*((u32*)(data+6)));
  12.292 -	return rc;
  12.293 -}
  12.294 -EXPORT_SYMBOL_GPL(tpm_pcr_extend);
  12.295 -
  12.296 -
  12.297 -
  12.298 -#define  READ_PUBEK_RESULT_SIZE 314
  12.299 -static const u8 readpubek[] = {
  12.300 -	0, 193,			/* TPM_TAG_RQU_COMMAND */
  12.301 -	0, 0, 0, 30,		/* length */
  12.302 -	0, 0, 0, 124,		/* TPM_ORD_ReadPubek */
  12.303 -};
  12.304 -
  12.305 -ssize_t tpm_show_pubek(struct device *dev, char *buf)
  12.306 -{
  12.307 -	u8 *data;
  12.308 -	ssize_t len;
  12.309 -	int i, rc;
  12.310 -	char *str = buf;
  12.311 -
  12.312 -	struct tpm_chip *chip = dev_get_drvdata(dev);
  12.313 -	if (chip == NULL)
  12.314 -		return -ENODEV;
  12.315 -
  12.316 -	data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
  12.317 -	if (!data)
  12.318 -		return -ENOMEM;
  12.319 -
  12.320 -	memcpy(data, readpubek, sizeof(readpubek));
  12.321 -	memset(data + sizeof(readpubek), 0, 20);	/* zero nonce */
  12.322 -
  12.323 -	if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
  12.324 -	    READ_PUBEK_RESULT_SIZE) {
  12.325 -		rc = len;
  12.326 -		goto out;
  12.327 -	}
  12.328 -
  12.329 -	/*
  12.330 -	   ignore header 10 bytes
  12.331 -	   algorithm 32 bits (1 == RSA )
  12.332 -	   encscheme 16 bits
  12.333 -	   sigscheme 16 bits
  12.334 -	   parameters (RSA 12->bytes: keybit, #primes, expbit)
  12.335 -	   keylenbytes 32 bits
  12.336 -	   256 byte modulus
  12.337 -	   ignore checksum 20 bytes
  12.338 -	 */
  12.339 -
  12.340 -	str +=
  12.341 -	    sprintf(str,
  12.342 -		    "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
  12.343 -		    "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
  12.344 -		    " %02X %02X %02X %02X %02X %02X %02X %02X\n"
  12.345 -		    "Modulus length: %d\nModulus: \n",
  12.346 -		    data[10], data[11], data[12], data[13], data[14],
  12.347 -		    data[15], data[16], data[17], data[22], data[23],
  12.348 -		    data[24], data[25], data[26], data[27], data[28],
  12.349 -		    data[29], data[30], data[31], data[32], data[33],
  12.350 -		    be32_to_cpu(*((__be32 *) (data + 32))));
  12.351 -
  12.352 -	for (i = 0; i < 256; i++) {
  12.353 -		str += sprintf(str, "%02X ", data[i + 39]);
  12.354 -		if ((i + 1) % 16 == 0)
  12.355 -			str += sprintf(str, "\n");
  12.356 -	}
  12.357 -	rc = str - buf;
  12.358 -out:
  12.359 -	kfree(data);
  12.360 -	return rc;
  12.361 -}
  12.362 -
  12.363 -EXPORT_SYMBOL_GPL(tpm_show_pubek);
  12.364 -
  12.365 -#define CAP_VER_RESULT_SIZE 18
  12.366 -static const u8 cap_version[] = {
  12.367 -	0, 193,			/* TPM_TAG_RQU_COMMAND */
  12.368 -	0, 0, 0, 18,		/* length */
  12.369 -	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
  12.370 -	0, 0, 0, 6,
  12.371 -	0, 0, 0, 0
  12.372 -};
  12.373 -
  12.374 -#define CAP_MANUFACTURER_RESULT_SIZE 18
  12.375 -static const u8 cap_manufacturer[] = {
  12.376 -	0, 193,			/* TPM_TAG_RQU_COMMAND */
  12.377 -	0, 0, 0, 22,		/* length */
  12.378 -	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
  12.379 -	0, 0, 0, 5,
  12.380 -	0, 0, 0, 4,
  12.381 -	0, 0, 1, 3
  12.382 -};
  12.383 -
  12.384 -ssize_t tpm_show_caps(struct device *dev, char *buf)
  12.385 -{
  12.386 -	u8 data[sizeof(cap_manufacturer)];
  12.387 -	ssize_t len;
  12.388 -	char *str = buf;
  12.389 -
  12.390 -	struct tpm_chip *chip = dev_get_drvdata(dev);
  12.391 -	if (chip == NULL)
  12.392 -		return -ENODEV;
  12.393 -
  12.394 -	memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
  12.395 -
  12.396 -	if ((len = tpm_transmit(chip, data, sizeof(data))) <
  12.397 -	    CAP_MANUFACTURER_RESULT_SIZE)
  12.398 -		return len;
  12.399 -
  12.400 -	str += sprintf(str, "Manufacturer: 0x%x\n",
  12.401 -		       be32_to_cpu(*((__be32 *)(data + 14))));
  12.402 -
  12.403 -	memcpy(data, cap_version, sizeof(cap_version));
  12.404 -
  12.405 -	if ((len = tpm_transmit(chip, data, sizeof(data))) <
  12.406 -	    CAP_VER_RESULT_SIZE)
  12.407 -		return len;
  12.408 -
  12.409 -	str +=
  12.410 -	    sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
  12.411 -		    (int) data[14], (int) data[15], (int) data[16],
  12.412 -		    (int) data[17]);
  12.413 -
  12.414 -	return str - buf;
  12.415 -}
  12.416 -
  12.417 -EXPORT_SYMBOL_GPL(tpm_show_caps);
  12.418 -
  12.419 -ssize_t tpm_store_cancel(struct device * dev, const char *buf,
  12.420 -			 size_t count)
  12.421 -{
  12.422 -	struct tpm_chip *chip = dev_get_drvdata(dev);
  12.423 -	if (chip == NULL)
  12.424 -		return 0;
  12.425 -
  12.426 -	chip->vendor->cancel(chip);
  12.427 -	return count;
  12.428 -}
  12.429 -
  12.430 -EXPORT_SYMBOL_GPL(tpm_store_cancel);
  12.431 -
  12.432 -/*
  12.433 - * Device file system interface to the TPM
  12.434 - */
  12.435 -int tpm_open(struct inode *inode, struct file *file)
  12.436 -{
  12.437 -	int rc = 0, minor = iminor(inode);
  12.438 -	struct tpm_chip *chip = NULL, *pos;
  12.439 -
  12.440 -	spin_lock(&driver_lock);
  12.441 -
  12.442 -	list_for_each_entry(pos, &tpm_chip_list, list) {
  12.443 -		if (pos->vendor->miscdev.minor == minor) {
  12.444 -			chip = pos;
  12.445 -			break;
  12.446 -		}
  12.447 -	}
  12.448 -
  12.449 -	if (chip == NULL) {
  12.450 -		rc = -ENODEV;
  12.451 -		goto err_out;
  12.452 -	}
  12.453 -
  12.454 -	if (chip->num_opens) {
  12.455 -		dev_dbg(chip->dev, "Another process owns this TPM\n");
  12.456 -		rc = -EBUSY;
  12.457 -		goto err_out;
  12.458 -	}
  12.459 -
  12.460 -	chip->num_opens++;
  12.461 -	get_device(chip->dev);
  12.462 -
  12.463 -	spin_unlock(&driver_lock);
  12.464 -
  12.465 -	chip->data_buffer = kmalloc(chip->vendor->buffersize * sizeof(u8),
  12.466 -	                            GFP_KERNEL);
  12.467 -	if (chip->data_buffer == NULL) {
  12.468 -		chip->num_opens--;
  12.469 -		put_device(chip->dev);
  12.470 -		return -ENOMEM;
  12.471 -	}
  12.472 -
  12.473 -	atomic_set(&chip->data_pending, 0);
  12.474 -
  12.475 -	file->private_data = chip;
  12.476 -	return 0;
  12.477 -
  12.478 -err_out:
  12.479 -	spin_unlock(&driver_lock);
  12.480 -	return rc;
  12.481 -}
  12.482 -
  12.483 -EXPORT_SYMBOL_GPL(tpm_open);
  12.484 -
  12.485 -int tpm_release(struct inode *inode, struct file *file)
  12.486 -{
  12.487 -	struct tpm_chip *chip = file->private_data;
  12.488 -
  12.489 -	spin_lock(&driver_lock);
  12.490 -	file->private_data = NULL;
  12.491 -	chip->num_opens--;
  12.492 -	del_singleshot_timer_sync(&chip->user_read_timer);
  12.493 -	atomic_set(&chip->data_pending, 0);
  12.494 -	put_device(chip->dev);
  12.495 -	kfree(chip->data_buffer);
  12.496 -	spin_unlock(&driver_lock);
  12.497 -	return 0;
  12.498 -}
  12.499 -
  12.500 -EXPORT_SYMBOL_GPL(tpm_release);
  12.501 -
  12.502 -ssize_t tpm_write(struct file * file, const char __user * buf,
  12.503 -		  size_t size, loff_t * off)
  12.504 -{
  12.505 -	struct tpm_chip *chip = file->private_data;
  12.506 -	int in_size = size, out_size;
  12.507 -
  12.508 -	/* cannot perform a write until the read has cleared
  12.509 -	   either via tpm_read or a user_read_timer timeout */
  12.510 -	while (atomic_read(&chip->data_pending) != 0)
  12.511 -		msleep(TPM_TIMEOUT);
  12.512 -
  12.513 -	down(&chip->buffer_mutex);
  12.514 -
  12.515 -	if (in_size > chip->vendor->buffersize)
  12.516 -		in_size = chip->vendor->buffersize;
  12.517 -
  12.518 -	if (copy_from_user
  12.519 -	    (chip->data_buffer, (void __user *) buf, in_size)) {
  12.520 -		up(&chip->buffer_mutex);
  12.521 -		return -EFAULT;
  12.522 -	}
  12.523 -
  12.524 -	/* atomic tpm command send and result receive */
  12.525 -	out_size = tpm_transmit(chip,
  12.526 -	                        chip->data_buffer,
  12.527 -	                        chip->vendor->buffersize);
  12.528 -
  12.529 -	atomic_set(&chip->data_pending, out_size);
  12.530 -	up(&chip->buffer_mutex);
  12.531 -
  12.532 -	/* Set a timeout by which the reader must come claim the result */
  12.533 -	mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
  12.534 -
  12.535 -	return in_size;
  12.536 -}
  12.537 -
  12.538 -EXPORT_SYMBOL_GPL(tpm_write);
  12.539 -
  12.540 -ssize_t tpm_read(struct file * file, char __user * buf,
  12.541 -		 size_t size, loff_t * off)
  12.542 -{
  12.543 -	struct tpm_chip *chip = file->private_data;
  12.544 -	int ret_size;
  12.545 -
  12.546 -	del_singleshot_timer_sync(&chip->user_read_timer);
  12.547 -	ret_size = atomic_read(&chip->data_pending);
  12.548 -
  12.549 -	if (ret_size > 0) {	/* relay data */
  12.550 -		int position = atomic_read(&chip->data_position);
  12.551 -
  12.552 -		if (size < ret_size)
  12.553 -			ret_size = size;
  12.554 -
  12.555 -		down(&chip->buffer_mutex);
  12.556 -
  12.557 -		if (copy_to_user((void __user *) buf,
  12.558 -				 &chip->data_buffer[position],
  12.559 -				 ret_size)) {
  12.560 -			ret_size = -EFAULT;
  12.561 -		} else {
  12.562 -		 	int pending = atomic_read(&chip->data_pending) - ret_size;
  12.563 -			atomic_set(&chip->data_pending,
  12.564 -			           pending);
  12.565 -			atomic_set(&chip->data_position,
  12.566 -			           position + ret_size);
  12.567 -		}
  12.568 -		up(&chip->buffer_mutex);
  12.569 -	}
  12.570 -
  12.571 -	return ret_size;
  12.572 -}
  12.573 -
  12.574 -EXPORT_SYMBOL_GPL(tpm_read);
  12.575 -
  12.576 -void tpm_remove_hardware(struct device *dev)
  12.577 -{
  12.578 -	struct tpm_chip *chip = dev_get_drvdata(dev);
  12.579 -	int i;
  12.580 -
  12.581 -	if (chip == NULL) {
  12.582 -		dev_err(dev, "No device data found\n");
  12.583 -		return;
  12.584 -	}
  12.585 -
  12.586 -	spin_lock(&driver_lock);
  12.587 -
  12.588 -	list_del(&chip->list);
  12.589 -
  12.590 -	spin_unlock(&driver_lock);
  12.591 -
  12.592 -	dev_set_drvdata(dev, NULL);
  12.593 -	misc_deregister(&chip->vendor->miscdev);
  12.594 -
  12.595 -	for (i = 0; i < TPM_NUM_ATTR; i++)
  12.596 -		device_remove_file(dev, &chip->vendor->attr[i]);
  12.597 -
  12.598 -	dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES] &=
  12.599 -	    !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
  12.600 -
  12.601 -	kfree(chip);
  12.602 -
  12.603 -	put_device(dev);
  12.604 -}
  12.605 -
  12.606 -EXPORT_SYMBOL_GPL(tpm_remove_hardware);
  12.607 -
  12.608 -static const u8 savestate[] = {
  12.609 -	0, 193,			/* TPM_TAG_RQU_COMMAND */
  12.610 -	0, 0, 0, 10,		/* blob length (in bytes) */
  12.611 -	0, 0, 0, 152		/* TPM_ORD_SaveState */
  12.612 -};
  12.613 -
  12.614 -/*
  12.615 - * We are about to suspend. Save the TPM state
  12.616 - * so that it can be restored.
  12.617 - */
  12.618 -int tpm_pm_suspend(struct pci_dev *pci_dev, u32 pm_state)
  12.619 -{
  12.620 -	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
  12.621 -	if (chip == NULL)
  12.622 -		return -ENODEV;
  12.623 -
  12.624 -	tpm_transmit(chip, savestate, sizeof(savestate));
  12.625 -	return 0;
  12.626 -}
  12.627 -
  12.628 -EXPORT_SYMBOL_GPL(tpm_pm_suspend);
  12.629 -
  12.630 -/*
  12.631 - * Resume from a power safe. The BIOS already restored
  12.632 - * the TPM state.
  12.633 - */
  12.634 -int tpm_pm_resume(struct pci_dev *pci_dev)
  12.635 -{
  12.636 -	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
  12.637 -
  12.638 -	if (chip == NULL)
  12.639 -		return -ENODEV;
  12.640 -
  12.641 -	return 0;
  12.642 -}
  12.643 -
  12.644 -EXPORT_SYMBOL_GPL(tpm_pm_resume);
  12.645 -
  12.646 -/*
  12.647 - * Called from tpm_<specific>.c probe function only for devices
  12.648 - * the driver has determined it should claim.  Prior to calling
  12.649 - * this function the specific probe function has called pci_enable_device
  12.650 - * upon errant exit from this function specific probe function should call
  12.651 - * pci_disable_device
  12.652 - */
  12.653 -int tpm_register_hardware_nopci(struct device *dev,
  12.654 -			        struct tpm_vendor_specific *entry)
  12.655 -{
  12.656 -	char devname[7];
  12.657 -	struct tpm_chip *chip;
  12.658 -	int i, j;
  12.659 -
  12.660 -	/* Driver specific per-device data */
  12.661 -	chip = kmalloc(sizeof(*chip), GFP_KERNEL);
  12.662 -	if (chip == NULL)
  12.663 -		return -ENOMEM;
  12.664 -
  12.665 -	memset(chip, 0, sizeof(struct tpm_chip));
  12.666 -
  12.667 -	init_MUTEX(&chip->buffer_mutex);
  12.668 -	init_MUTEX(&chip->tpm_mutex);
  12.669 -	INIT_LIST_HEAD(&chip->list);
  12.670 -
  12.671 -	init_timer(&chip->user_read_timer);
  12.672 -	chip->user_read_timer.function = user_reader_timeout;
  12.673 -	chip->user_read_timer.data = (unsigned long) chip;
  12.674 -
  12.675 -	chip->vendor = entry;
  12.676 -
  12.677 -	if (entry->buffersize < TPM_MIN_BUFSIZE) {
  12.678 -		entry->buffersize = TPM_MIN_BUFSIZE;
  12.679 -	} else if (entry->buffersize > TPM_MAX_BUFSIZE) {
  12.680 -		entry->buffersize = TPM_MAX_BUFSIZE;
  12.681 -	}
  12.682 -
  12.683 -	chip->dev_num = -1;
  12.684 -
  12.685 -	for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
  12.686 -		for (j = 0; j < 8 * sizeof(int); j++)
  12.687 -			if ((dev_mask[i] & (1 << j)) == 0) {
  12.688 -				chip->dev_num =
  12.689 -				    i * TPM_NUM_MASK_ENTRIES + j;
  12.690 -				dev_mask[i] |= 1 << j;
  12.691 -				goto dev_num_search_complete;
  12.692 -			}
  12.693 -
  12.694 -dev_num_search_complete:
  12.695 -	if (chip->dev_num < 0) {
  12.696 -		dev_err(dev, "No available tpm device numbers\n");
  12.697 -		kfree(chip);
  12.698 -		return -ENODEV;
  12.699 -	} else if (chip->dev_num == 0)
  12.700 -		chip->vendor->miscdev.minor = TPM_MINOR;
  12.701 -	else
  12.702 -		chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
  12.703 -
  12.704 -	snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
  12.705 -	chip->vendor->miscdev.name = devname;
  12.706 -
  12.707 -	chip->vendor->miscdev.dev = dev;
  12.708 -	chip->dev = get_device(dev);
  12.709 -
  12.710 -
  12.711 -	if (misc_register(&chip->vendor->miscdev)) {
  12.712 -		dev_err(chip->dev,
  12.713 -			"unable to misc_register %s, minor %d\n",
  12.714 -			chip->vendor->miscdev.name,
  12.715 -			chip->vendor->miscdev.minor);
  12.716 -		put_device(dev);
  12.717 -		kfree(chip);
  12.718 -		dev_mask[i] &= !(1 << j);
  12.719 -		return -ENODEV;
  12.720 -	}
  12.721 -
  12.722 -	spin_lock(&driver_lock);
  12.723 -
  12.724 -	dev_set_drvdata(dev, chip);
  12.725 -
  12.726 -	list_add(&chip->list, &tpm_chip_list);
  12.727 -
  12.728 -	spin_unlock(&driver_lock);
  12.729 -
  12.730 -	for (i = 0; i < TPM_NUM_ATTR; i++)
  12.731 -		device_create_file(dev, &chip->vendor->attr[i]);
  12.732 -
  12.733 -	return 0;
  12.734 -}
  12.735 -
  12.736 -EXPORT_SYMBOL_GPL(tpm_register_hardware_nopci);
  12.737 -
  12.738 -static int __init init_tpm(void)
  12.739 -{
  12.740 -	return 0;
  12.741 -}
  12.742 -
  12.743 -static void __exit cleanup_tpm(void)
  12.744 -{
  12.745 -
  12.746 -}
  12.747 -
  12.748 -module_init(init_tpm);
  12.749 -module_exit(cleanup_tpm);
  12.750 -
  12.751 -MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
  12.752 -MODULE_DESCRIPTION("TPM Driver");
  12.753 -MODULE_VERSION("2.0");
  12.754 -MODULE_LICENSE("GPL");
    13.1 --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.h	Wed Oct 05 14:38:19 2005 +0100
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,128 +0,0 @@
    13.4 -/*
    13.5 - * Copyright (C) 2004 IBM Corporation
    13.6 - *
    13.7 - * Authors:
    13.8 - * Leendert van Doorn <leendert@watson.ibm.com>
    13.9 - * Dave Safford <safford@watson.ibm.com>
   13.10 - * Reiner Sailer <sailer@watson.ibm.com>
   13.11 - * Kylene Hall <kjhall@us.ibm.com>
   13.12 - *
   13.13 - * Maintained by: <tpmdd_devel@lists.sourceforge.net>
   13.14 - *
   13.15 - * Device driver for TCG/TCPA TPM (trusted platform module).
   13.16 - * Specifications at www.trustedcomputinggroup.org
   13.17 - *
   13.18 - * This program is free software; you can redistribute it and/or
   13.19 - * modify it under the terms of the GNU General Public License as
   13.20 - * published by the Free Software Foundation, version 2 of the
   13.21 - * License.
   13.22 - *
   13.23 - */
   13.24 -#include <linux/module.h>
   13.25 -#include <linux/version.h>
   13.26 -#include <linux/pci.h>
   13.27 -#include <linux/delay.h>
   13.28 -#include <linux/miscdevice.h>
   13.29 -
   13.30 -enum {
   13.31 -	TPM_TIMEOUT = 5,	/* msecs */
   13.32 -	TPM_NUM_ATTR = 4
   13.33 -};
   13.34 -
   13.35 -/* TPM addresses */
   13.36 -enum {
   13.37 -	TPM_ADDR = 0x4E,
   13.38 -	TPM_DATA = 0x4F
   13.39 -};
   13.40 -
   13.41 -/*
   13.42 - * Chip num is this value or a valid tpm idx in lower two bytes of chip_id
   13.43 - */
   13.44 -enum tpm_chip_num {
   13.45 -	TPM_ANY_NUM = 0xFFFF,
   13.46 -};
   13.47 -
   13.48 -#define TPM_CHIP_NUM_MASK	0x0000ffff
   13.49 -
   13.50 -extern ssize_t tpm_show_pubek(struct device *, char *);
   13.51 -extern ssize_t tpm_show_pcrs(struct device *, char *);
   13.52 -extern ssize_t tpm_show_caps(struct device *, char *);
   13.53 -extern ssize_t tpm_store_cancel(struct device *, const char *, size_t);
   13.54 -
   13.55 -#define TPM_DEVICE_ATTRS { \
   13.56 -	__ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL), \
   13.57 -	__ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL), \
   13.58 -	__ATTR(caps, S_IRUGO, tpm_show_caps, NULL), \
   13.59 -	__ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel) }
   13.60 -
   13.61 -struct tpm_chip;
   13.62 -
   13.63 -struct tpm_vendor_specific {
   13.64 -	u8 req_complete_mask;
   13.65 -	u8 req_complete_val;
   13.66 -	u8 req_canceled;
   13.67 -	u16 base;		/* TPM base address */
   13.68 -	u32 buffersize;         /* The device's requested buffersize */
   13.69 -
   13.70 -	int (*recv) (struct tpm_chip *, u8 *, size_t);
   13.71 -	int (*send) (struct tpm_chip *, u8 *, size_t);
   13.72 -	void (*cancel) (struct tpm_chip *);
   13.73 -	 u8(*status) (struct tpm_chip *);
   13.74 -	struct miscdevice miscdev;
   13.75 -	struct device_attribute attr[TPM_NUM_ATTR];
   13.76 -};
   13.77 -
   13.78 -struct tpm_chip {
   13.79 -	struct device *dev;	/* PCI device stuff */
   13.80 -
   13.81 -	int dev_num;		/* /dev/tpm# */
   13.82 -	int num_opens;		/* only one allowed */
   13.83 -	int time_expired;
   13.84 -
   13.85 -	/* Data passed to and from the tpm via the read/write calls */
   13.86 -	u8 *data_buffer;
   13.87 -	atomic_t data_pending;
   13.88 -	atomic_t data_position;
   13.89 -	struct semaphore buffer_mutex;
   13.90 -
   13.91 -	struct timer_list user_read_timer;	/* user needs to claim result */
   13.92 -	struct semaphore tpm_mutex;	/* tpm is processing */
   13.93 -
   13.94 -	struct tpm_vendor_specific *vendor;
   13.95 -
   13.96 -	struct list_head list;
   13.97 -};
   13.98 -
   13.99 -static inline int tpm_read_index(int index)
  13.100 -{
  13.101 -	outb(index, TPM_ADDR);
  13.102 -	return inb(TPM_DATA) & 0xFF;
  13.103 -}
  13.104 -
  13.105 -static inline void tpm_write_index(int index, int value)
  13.106 -{
  13.107 -	outb(index, TPM_ADDR);
  13.108 -	outb(value & 0xFF, TPM_DATA);
  13.109 -}
  13.110 -
  13.111 -extern void tpm_time_expired(unsigned long);
  13.112 -extern int tpm_lpc_bus_init(struct pci_dev *, u16);
  13.113 -
  13.114 -extern int tpm_register_hardware_nopci(struct device *,
  13.115 -				       struct tpm_vendor_specific *);
  13.116 -extern void tpm_remove_hardware(struct device *);
  13.117 -extern int tpm_open(struct inode *, struct file *);
  13.118 -extern int tpm_release(struct inode *, struct file *);
  13.119 -extern ssize_t tpm_write(struct file *, const char __user *, size_t,
  13.120 -			 loff_t *);
  13.121 -extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
  13.122 -extern int tpm_pcr_extend(u32 chip_id, int pcr_idx, const u8* hash);
  13.123 -extern int tpm_pcr_read( u32 chip_id, int pcr_idx, u8* res_buf, int res_buf_size );
  13.124 -
  13.125 -extern int tpm_pm_suspend(struct pci_dev *, u32);
  13.126 -extern int tpm_pm_resume(struct pci_dev *);
  13.127 -
  13.128 -/* internal kernel interface */
  13.129 -extern ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
  13.130 -			    size_t bufsiz);
  13.131 -extern struct tpm_chip *tpm_chip_lookup(int chip_num);
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nsc.c	Wed Oct 05 14:40:35 2005 +0100
    14.3 @@ -0,0 +1,386 @@
    14.4 +/*
    14.5 + * Copyright (C) 2004 IBM Corporation
    14.6 + *
    14.7 + * Authors:
    14.8 + * Leendert van Doorn <leendert@watson.ibm.com>
    14.9 + * Dave Safford <safford@watson.ibm.com>
   14.10 + * Reiner Sailer <sailer@watson.ibm.com>
   14.11 + * Kylene Hall <kjhall@us.ibm.com>
   14.12 + *
   14.13 + * Maintained by: <tpmdd_devel@lists.sourceforge.net>
   14.14 + *
   14.15 + * Device driver for TCG/TCPA TPM (trusted platform module).
   14.16 + * Specifications at www.trustedcomputinggroup.org	 
   14.17 + *
   14.18 + * This program is free software; you can redistribute it and/or
   14.19 + * modify it under the terms of the GNU General Public License as
   14.20 + * published by the Free Software Foundation, version 2 of the
   14.21 + * License.
   14.22 + * 
   14.23 + */
   14.24 +
   14.25 +#include "tpm.h"
   14.26 +
   14.27 +/* National definitions */
   14.28 +enum tpm_nsc_addr{
   14.29 +	TPM_NSC_IRQ = 0x07,
   14.30 +	TPM_NSC_BASE0_HI = 0x60,
   14.31 +	TPM_NSC_BASE0_LO = 0x61,
   14.32 +	TPM_NSC_BASE1_HI = 0x62,
   14.33 +	TPM_NSC_BASE1_LO = 0x63
   14.34 +};
   14.35 +
   14.36 +enum tpm_nsc_index {
   14.37 +	NSC_LDN_INDEX = 0x07,
   14.38 +	NSC_SID_INDEX = 0x20,
   14.39 +	NSC_LDC_INDEX = 0x30,
   14.40 +	NSC_DIO_INDEX = 0x60,
   14.41 +	NSC_CIO_INDEX = 0x62,
   14.42 +	NSC_IRQ_INDEX = 0x70,
   14.43 +	NSC_ITS_INDEX = 0x71
   14.44 +};
   14.45 +
   14.46 +enum tpm_nsc_status_loc {
   14.47 +	NSC_STATUS = 0x01,
   14.48 +	NSC_COMMAND = 0x01,
   14.49 +	NSC_DATA = 0x00
   14.50 +};
   14.51 +
   14.52 +/* status bits */
   14.53 +enum tpm_nsc_status {
   14.54 +	NSC_STATUS_OBF = 0x01,	/* output buffer full */
   14.55 +	NSC_STATUS_IBF = 0x02,	/* input buffer full */
   14.56 +	NSC_STATUS_F0 = 0x04,	/* F0 */
   14.57 +	NSC_STATUS_A2 = 0x08,	/* A2 */
   14.58 +	NSC_STATUS_RDY = 0x10,	/* ready to receive command */
   14.59 +	NSC_STATUS_IBR = 0x20	/* ready to receive data */
   14.60 +};
   14.61 +
   14.62 +/* command bits */
   14.63 +enum tpm_nsc_cmd_mode {
   14.64 +	NSC_COMMAND_NORMAL = 0x01,	/* normal mode */
   14.65 +	NSC_COMMAND_EOC = 0x03,
   14.66 +	NSC_COMMAND_CANCEL = 0x22
   14.67 +};
   14.68 +/*
   14.69 + * Wait for a certain status to appear
   14.70 + */
   14.71 +static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
   14.72 +{
   14.73 +	unsigned long stop;
   14.74 +
   14.75 +	/* status immediately available check */
   14.76 +	*data = inb(chip->vendor->base + NSC_STATUS);
   14.77 +	if ((*data & mask) == val)
   14.78 +		return 0;
   14.79 +
   14.80 +	/* wait for status */
   14.81 +	stop = jiffies + 10 * HZ;
   14.82 +	do {
   14.83 +		msleep(TPM_TIMEOUT);
   14.84 +		*data = inb(chip->vendor->base + 1);
   14.85 +		if ((*data & mask) == val)
   14.86 +			return 0;
   14.87 +	}
   14.88 +	while (time_before(jiffies, stop));
   14.89 +
   14.90 +	return -EBUSY;
   14.91 +}
   14.92 +
   14.93 +static int nsc_wait_for_ready(struct tpm_chip *chip)
   14.94 +{
   14.95 +	int status;
   14.96 +	unsigned long stop;
   14.97 +
   14.98 +	/* status immediately available check */
   14.99 +	status = inb(chip->vendor->base + NSC_STATUS);
  14.100 +	if (status & NSC_STATUS_OBF)
  14.101 +		status = inb(chip->vendor->base + NSC_DATA);
  14.102 +	if (status & NSC_STATUS_RDY)
  14.103 +		return 0;
  14.104 +
  14.105 +	/* wait for status */
  14.106 +	stop = jiffies + 100;
  14.107 +	do {
  14.108 +		msleep(TPM_TIMEOUT);
  14.109 +		status = inb(chip->vendor->base + NSC_STATUS);
  14.110 +		if (status & NSC_STATUS_OBF)
  14.111 +			status = inb(chip->vendor->base + NSC_DATA);
  14.112 +		if (status & NSC_STATUS_RDY)
  14.113 +			return 0;
  14.114 +	}
  14.115 +	while (time_before(jiffies, stop));
  14.116 +
  14.117 +	dev_info(chip->dev, "wait for ready failed\n");
  14.118 +	return -EBUSY;
  14.119 +}
  14.120 +
  14.121 +
  14.122 +static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
  14.123 +{
  14.124 +	u8 *buffer = buf;
  14.125 +	u8 data, *p;
  14.126 +	u32 size;
  14.127 +	__be32 *native_size;
  14.128 +
  14.129 +	if (count < 6)
  14.130 +		return -EIO;
  14.131 +
  14.132 +	if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
  14.133 +		dev_err(chip->dev, "F0 timeout\n");
  14.134 +		return -EIO;
  14.135 +	}
  14.136 +	if ((data =
  14.137 +	     inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
  14.138 +		dev_err(chip->dev, "not in normal mode (0x%x)\n",
  14.139 +			data);
  14.140 +		return -EIO;
  14.141 +	}
  14.142 +
  14.143 +	/* read the whole packet */
  14.144 +	for (p = buffer; p < &buffer[count]; p++) {
  14.145 +		if (wait_for_stat
  14.146 +		    (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
  14.147 +			dev_err(chip->dev,
  14.148 +				"OBF timeout (while reading data)\n");
  14.149 +			return -EIO;
  14.150 +		}
  14.151 +		if (data & NSC_STATUS_F0)
  14.152 +			break;
  14.153 +		*p = inb(chip->vendor->base + NSC_DATA);
  14.154 +	}
  14.155 +
  14.156 +	if ((data & NSC_STATUS_F0) == 0 &&
  14.157 +	(wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
  14.158 +		dev_err(chip->dev, "F0 not set\n");
  14.159 +		return -EIO;
  14.160 +	}
  14.161 +	if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
  14.162 +		dev_err(chip->dev,
  14.163 +			"expected end of command(0x%x)\n", data);
  14.164 +		return -EIO;
  14.165 +	}
  14.166 +
  14.167 +	native_size = (__force __be32 *) (buf + 2);
  14.168 +	size = be32_to_cpu(*native_size);
  14.169 +
  14.170 +	if (count < size)
  14.171 +		return -EIO;
  14.172 +
  14.173 +	return size;
  14.174 +}
  14.175 +
  14.176 +static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
  14.177 +{
  14.178 +	u8 data;
  14.179 +	int i;
  14.180 +
  14.181 +	/*
  14.182 +	 * If we hit the chip with back to back commands it locks up
  14.183 +	 * and never set IBF. Hitting it with this "hammer" seems to
  14.184 +	 * fix it. Not sure why this is needed, we followed the flow
  14.185 +	 * chart in the manual to the letter.
  14.186 +	 */
  14.187 +	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
  14.188 +
  14.189 +	if (nsc_wait_for_ready(chip) != 0)
  14.190 +		return -EIO;
  14.191 +
  14.192 +	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
  14.193 +		dev_err(chip->dev, "IBF timeout\n");
  14.194 +		return -EIO;
  14.195 +	}
  14.196 +
  14.197 +	outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
  14.198 +	if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
  14.199 +		dev_err(chip->dev, "IBR timeout\n");
  14.200 +		return -EIO;
  14.201 +	}
  14.202 +
  14.203 +	for (i = 0; i < count; i++) {
  14.204 +		if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
  14.205 +			dev_err(chip->dev,
  14.206 +				"IBF timeout (while writing data)\n");
  14.207 +			return -EIO;
  14.208 +		}
  14.209 +		outb(buf[i], chip->vendor->base + NSC_DATA);
  14.210 +	}
  14.211 +
  14.212 +	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
  14.213 +		dev_err(chip->dev, "IBF timeout\n");
  14.214 +		return -EIO;
  14.215 +	}
  14.216 +	outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
  14.217 +
  14.218 +	return count;
  14.219 +}
  14.220 +
  14.221 +static void tpm_nsc_cancel(struct tpm_chip *chip)
  14.222 +{
  14.223 +	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
  14.224 +}
  14.225 +
  14.226 +static u8 tpm_nsc_status(struct tpm_chip *chip)
  14.227 +{
  14.228 +	return inb(chip->vendor->base + NSC_STATUS);
  14.229 +}
  14.230 +
  14.231 +static struct file_operations nsc_ops = {
  14.232 +	.owner = THIS_MODULE,
  14.233 +	.llseek = no_llseek,
  14.234 +	.open = tpm_open,
  14.235 +	.read = tpm_read,
  14.236 +	.write = tpm_write,
  14.237 +	.release = tpm_release,
  14.238 +};
  14.239 +
  14.240 +static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
  14.241 +static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
  14.242 +static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
  14.243 +static DEVICE_ATTR(cancel, S_IWUSR|S_IWGRP, NULL, tpm_store_cancel);
  14.244 +
  14.245 +static struct attribute * nsc_attrs[] = {
  14.246 +	&dev_attr_pubek.attr,
  14.247 +	&dev_attr_pcrs.attr,
  14.248 +	&dev_attr_caps.attr,
  14.249 +	&dev_attr_cancel.attr,
  14.250 +	0,
  14.251 +};
  14.252 +
  14.253 +static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
  14.254 +
  14.255 +static struct tpm_vendor_specific tpm_nsc = {
  14.256 +	.recv = tpm_nsc_recv,
  14.257 +	.send = tpm_nsc_send,
  14.258 +	.cancel = tpm_nsc_cancel,
  14.259 +	.status = tpm_nsc_status,
  14.260 +	.req_complete_mask = NSC_STATUS_OBF,
  14.261 +	.req_complete_val = NSC_STATUS_OBF,
  14.262 +	.req_canceled = NSC_STATUS_RDY,
  14.263 +	.attr_group = &nsc_attr_grp,
  14.264 +	.miscdev = { .fops = &nsc_ops, },
  14.265 +};
  14.266 +
  14.267 +static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
  14.268 +				  const struct pci_device_id *pci_id)
  14.269 +{
  14.270 +	int rc = 0;
  14.271 +	int lo, hi;
  14.272 +	int nscAddrBase = TPM_ADDR;
  14.273 +
  14.274 +
  14.275 +	if (pci_enable_device(pci_dev))
  14.276 +		return -EIO;
  14.277 +
  14.278 +	/* select PM channel 1 */
  14.279 +	tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12);
  14.280 +
  14.281 +	/* verify that it is a National part (SID) */
  14.282 +	if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
  14.283 +		nscAddrBase = (tpm_read_index(TPM_SUPERIO_ADDR, 0x2C)<<8)|
  14.284 +			(tpm_read_index(TPM_SUPERIO_ADDR, 0x2B)&0xFE);
  14.285 +		if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6) {
  14.286 +			rc = -ENODEV;
  14.287 +			goto out_err;
  14.288 +		}
  14.289 +	}
  14.290 +
  14.291 +	hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
  14.292 +	lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
  14.293 +	tpm_nsc.base = (hi<<8) | lo;
  14.294 +
  14.295 +	dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
  14.296 +	dev_dbg(&pci_dev->dev,
  14.297 +		"NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
  14.298 +		tpm_read_index(nscAddrBase,0x07), tpm_read_index(nscAddrBase,0x20),
  14.299 +		tpm_read_index(nscAddrBase,0x27));
  14.300 +	dev_dbg(&pci_dev->dev,
  14.301 +		"NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
  14.302 +		tpm_read_index(nscAddrBase,0x21), tpm_read_index(nscAddrBase,0x25),
  14.303 +		tpm_read_index(nscAddrBase,0x26), tpm_read_index(nscAddrBase,0x28));
  14.304 +	dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
  14.305 +		(tpm_read_index(nscAddrBase,0x60) << 8) | tpm_read_index(nscAddrBase,0x61));
  14.306 +	dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
  14.307 +		(tpm_read_index(nscAddrBase,0x62) << 8) | tpm_read_index(nscAddrBase,0x63));
  14.308 +	dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
  14.309 +		tpm_read_index(nscAddrBase,0x70));
  14.310 +	dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
  14.311 +		tpm_read_index(nscAddrBase,0x71));
  14.312 +	dev_dbg(&pci_dev->dev,
  14.313 +		"NSC DMA channel select0 0x%x, select1 0x%x\n",
  14.314 +		tpm_read_index(nscAddrBase,0x74), tpm_read_index(nscAddrBase,0x75));
  14.315 +	dev_dbg(&pci_dev->dev,
  14.316 +		"NSC Config "
  14.317 +		"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
  14.318 +		tpm_read_index(nscAddrBase,0xF0), tpm_read_index(nscAddrBase,0xF1),
  14.319 +		tpm_read_index(nscAddrBase,0xF2), tpm_read_index(nscAddrBase,0xF3),
  14.320 +		tpm_read_index(nscAddrBase,0xF4), tpm_read_index(nscAddrBase,0xF5),
  14.321 +		tpm_read_index(nscAddrBase,0xF6), tpm_read_index(nscAddrBase,0xF7),
  14.322 +		tpm_read_index(nscAddrBase,0xF8), tpm_read_index(nscAddrBase,0xF9));
  14.323 +
  14.324 +	dev_info(&pci_dev->dev,
  14.325 +		 "NSC TPM revision %d\n",
  14.326 +		 tpm_read_index(nscAddrBase, 0x27) & 0x1F);
  14.327 +
  14.328 +	/* enable the DPM module */
  14.329 +	tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
  14.330 +
  14.331 +	if ((rc = tpm_register_hardware(&pci_dev->dev, &tpm_nsc)) < 0)
  14.332 +		goto out_err;
  14.333 +
  14.334 +	return 0;
  14.335 +
  14.336 +out_err:
  14.337 +	pci_disable_device(pci_dev);
  14.338 +	return rc;
  14.339 +}
  14.340 +
  14.341 +static void __devexit tpm_nsc_remove(struct pci_dev *pci_dev) 
  14.342 +{
  14.343 +	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
  14.344 +
  14.345 +	if ( chip )
  14.346 +		tpm_remove_hardware(chip->dev);
  14.347 +}
  14.348 +
  14.349 +static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
  14.350 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
  14.351 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
  14.352 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
  14.353 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
  14.354 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
  14.355 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
  14.356 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
  14.357 +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
  14.358 +	{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
  14.359 +	{0,}
  14.360 +};
  14.361 +
  14.362 +MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
  14.363 +
  14.364 +static struct pci_driver nsc_pci_driver = {
  14.365 +	.name = "tpm_nsc",
  14.366 +	.id_table = tpm_pci_tbl,
  14.367 +	.probe = tpm_nsc_init,
  14.368 +	.remove = __devexit_p(tpm_nsc_remove),
  14.369 +	.suspend = tpm_pm_suspend,
  14.370 +	.resume = tpm_pm_resume,
  14.371 +};
  14.372 +
  14.373 +static int __init init_nsc(void)
  14.374 +{
  14.375 +	return pci_register_driver(&nsc_pci_driver);
  14.376 +}
  14.377 +
  14.378 +static void __exit cleanup_nsc(void)
  14.379 +{
  14.380 +	pci_unregister_driver(&nsc_pci_driver);
  14.381 +}
  14.382 +
  14.383 +fs_initcall(init_nsc);
  14.384 +module_exit(cleanup_nsc);
  14.385 +
  14.386 +MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
  14.387 +MODULE_DESCRIPTION("TPM Driver");
  14.388 +MODULE_VERSION("2.0");
  14.389 +MODULE_LICENSE("GPL");
    15.1 --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c	Wed Oct 05 14:38:19 2005 +0100
    15.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c	Wed Oct 05 14:40:35 2005 +0100
    15.3 @@ -25,7 +25,7 @@
    15.4  #include <linux/tpmfe.h>
    15.5  #include <linux/device.h>
    15.6  #include <linux/interrupt.h>
    15.7 -#include "tpm_nopci.h"
    15.8 +#include "tpm.h"
    15.9  
   15.10  /* read status bits */
   15.11  enum {
   15.12 @@ -434,6 +434,21 @@ static struct file_operations tpm_xen_op
   15.13  	.release = tpm_release,
   15.14  };
   15.15  
   15.16 +static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
   15.17 +static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
   15.18 +static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
   15.19 +static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
   15.20 +
   15.21 +static struct attribute* xen_attrs[] = {
   15.22 +	&dev_attr_pubek.attr,
   15.23 +	&dev_attr_pcrs.attr,
   15.24 +	&dev_attr_caps.attr,
   15.25 +	&dev_attr_cancel.attr,
   15.26 +	0,
   15.27 +};
   15.28 +
   15.29 +static struct attribute_group xen_attr_grp = { .attrs = xen_attrs };
   15.30 +
   15.31  static struct tpm_vendor_specific tpm_xen = {
   15.32  	.recv = tpm_xen_recv,
   15.33  	.send = tpm_xen_send,
   15.34 @@ -443,7 +458,7 @@ static struct tpm_vendor_specific tpm_xe
   15.35  	.req_complete_val  = STATUS_DATA_AVAIL,
   15.36  	.req_canceled = STATUS_READY,
   15.37  	.base = 0,
   15.38 -	.attr = TPM_DEVICE_ATTRS,
   15.39 +	.attr_group = &xen_attr_grp,
   15.40  	.miscdev.fops = &tpm_xen_ops,
   15.41  	.buffersize = 64 * 1024,
   15.42  };
   15.43 @@ -480,7 +495,7 @@ static int __init init_xen(void)
   15.44  
   15.45  	tpm_xen.buffersize = tpmfe.max_tx_size;
   15.46  
   15.47 -	if ((rc = tpm_register_hardware_nopci(&tpm_device, &tpm_xen)) < 0) {
   15.48 +	if ((rc = tpm_register_hardware(&tpm_device, &tpm_xen)) < 0) {
   15.49  		device_unregister(&tpm_device);
   15.50  		tpm_fe_unregister_receiver();
   15.51  		return rc;
    16.1 --- a/patches/linux-2.6.12/tpm_partial_read.patch	Wed Oct 05 14:38:19 2005 +0100
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,74 +0,0 @@
    16.4 ---- ref-linux-2.6.12/drivers/char/tpm/tpm.c	2005-06-17 15:48:29.000000000 -0400
    16.5 -+++ linux-2.6-xen-sparse/drivers/char/tpm/tpm.c	2005-09-15 14:56:05.000000000 -0400
    16.6 -@@ -473,6 +401,7 @@ ssize_t tpm_write(struct file * file, co
    16.7 - 	out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
    16.8 - 
    16.9 - 	atomic_set(&chip->data_pending, out_size);
   16.10 -+	atomic_set(&chip->data_position, 0);
   16.11 - 	up(&chip->buffer_mutex);
   16.12 - 
   16.13 - 	/* Set a timeout by which the reader must come claim the result */
   16.14 -@@ -494,29 +423,34 @@ ssize_t tpm_read(struct file * file, cha
   16.15 - {
   16.16 - 	struct tpm_chip *chip = file->private_data;
   16.17 - 	int ret_size = -ENODATA;
   16.18 -+	int pos, pending = 0;
   16.19 - 
   16.20 --	if (atomic_read(&chip->data_pending) != 0) {	/* Result available */
   16.21 -+	down(&chip->buffer_mutex);
   16.22 -+	ret_size = atomic_read(&chip->data_pending);
   16.23 -+	if ( ret_size > 0 ) {	/* Result available */
   16.24 -+		if (size < ret_size)
   16.25 -+			ret_size = size;
   16.26 -+
   16.27 -+		pos = atomic_read(&chip->data_position);
   16.28 -+
   16.29 -+		if (copy_to_user((void __user *) buf,
   16.30 -+				 &chip->data_buffer[pos], ret_size)) {
   16.31 -+			ret_size = -EFAULT;
   16.32 -+		} else {
   16.33 -+			pending = atomic_read(&chip->data_pending) - ret_size;
   16.34 -+			if ( pending ) {
   16.35 -+				atomic_set( &chip->data_pending, pending );
   16.36 -+				atomic_set( &chip->data_position, pos+ret_size );
   16.37 -+			}
   16.38 -+		}
   16.39 -+	}
   16.40 -+	up(&chip->buffer_mutex);
   16.41 -+
   16.42 -+	if ( ret_size <= 0 || pending == 0 ) {
   16.43 -+		atomic_set( &chip->data_pending, 0 );
   16.44 - 		down(&chip->timer_manipulation_mutex);
   16.45 - 		del_singleshot_timer_sync(&chip->user_read_timer);
   16.46 - 		up(&chip->timer_manipulation_mutex);
   16.47 --
   16.48 --		down(&chip->buffer_mutex);
   16.49 --
   16.50 --		ret_size = atomic_read(&chip->data_pending);
   16.51 --		atomic_set(&chip->data_pending, 0);
   16.52 --
   16.53 --		if (ret_size == 0)	/* timeout just occurred */
   16.54 --			ret_size = -ETIME;
   16.55 --		else if (ret_size > 0) {	/* relay data */
   16.56 --			if (size < ret_size)
   16.57 --				ret_size = size;
   16.58 --
   16.59 --			if (copy_to_user((void __user *) buf,
   16.60 --					 chip->data_buffer, ret_size)) {
   16.61 --				ret_size = -EFAULT;
   16.62 --			}
   16.63 --		}
   16.64 --		up(&chip->buffer_mutex);
   16.65 - 	}
   16.66 - 
   16.67 - 	return ret_size;
   16.68 ---- ref-linux-2.6.12/drivers/char/tpm/tpm.h	2005-06-17 15:48:29.000000000 -0400
   16.69 -+++ linux-2.6-xen-sparse/drivers/char/tpm/tpm.h	2005-09-15 14:56:05.000000000 -0400
   16.70 -@@ -54,6 +54,7 @@ struct tpm_chip {
   16.71 - 	/* Data passed to and from the tpm via the read/write calls */
   16.72 - 	u8 *data_buffer;
   16.73 - 	atomic_t data_pending;
   16.74 -+	atomic_t data_position;
   16.75 - 	struct semaphore buffer_mutex;
   16.76 - 
   16.77 - 	struct timer_list user_read_timer;	/* user needs to claim result */
    17.1 --- a/tools/examples/Makefile	Wed Oct 05 14:38:19 2005 +0100
    17.2 +++ b/tools/examples/Makefile	Wed Oct 05 14:40:35 2005 +0100
    17.3 @@ -44,7 +44,7 @@ install-configs: $(XEN_CONFIGS)
    17.4  	[ -d $(DESTDIR)$(XEN_CONFIG_DIR)/auto ] || \
    17.5  		$(INSTALL_DIR) $(DESTDIR)$(XEN_CONFIG_DIR)/auto
    17.6  	for i in $(XEN_CONFIGS); \
    17.7 -	    do [ -a $(DESTDIR)$(XEN_CONFIG_DIR)/$$i ] || \
    17.8 +	    do [ -e $(DESTDIR)$(XEN_CONFIG_DIR)/$$i ] || \
    17.9  	    $(INSTALL_DATA) $$i $(DESTDIR)$(XEN_CONFIG_DIR); \
   17.10  	done
   17.11  
   17.12 @@ -52,7 +52,7 @@ install-scripts:
   17.13  	[ -d $(DESTDIR)$(XEN_SCRIPT_DIR) ] || \
   17.14  		$(INSTALL_DIR) $(DESTDIR)$(XEN_SCRIPT_DIR)
   17.15  	for i in $(XEN_SCRIPTS); \
   17.16 -	    do [ -a $(DESTDIR)$(XEN_SCRIPT_DIR)/$$i ] || \
   17.17 +	    do \
   17.18  	    $(INSTALL_PROG) $$i $(DESTDIR)$(XEN_SCRIPT_DIR); \
   17.19  	done
   17.20  
    18.1 --- a/tools/examples/network-bridge	Wed Oct 05 14:38:19 2005 +0100
    18.2 +++ b/tools/examples/network-bridge	Wed Oct 05 14:40:35 2005 +0100
    18.3 @@ -55,6 +55,17 @@ antispoof=${antispoof:-no}
    18.4  
    18.5  echo "*network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof" >&2
    18.6  
    18.7 +# Gentoo doesn't have ifup/ifdown: define appropriate alternatives
    18.8 +which ifup >& /dev/null
    18.9 +if [ "$?" != 0 -a -e /etc/conf.d/net ]; then
   18.10 +    ifup() {
   18.11 +        /etc/init.d/net.$1 start
   18.12 +    }
   18.13 +    ifdown() {
   18.14 +        /etc/init.d/net.$1 stop
   18.15 +    }
   18.16 +fi
   18.17 +
   18.18  # Usage: transfer_addrs src dst
   18.19  # Copy all IP addresses (including aliases) from device $src to device $dst.
   18.20  transfer_addrs () {
    19.1 --- a/xen/Rules.mk	Wed Oct 05 14:38:19 2005 +0100
    19.2 +++ b/xen/Rules.mk	Wed Oct 05 14:40:35 2005 +0100
    19.3 @@ -10,7 +10,8 @@ trace       ?= n
    19.4  domu_debug  ?= n
    19.5  crash_debug ?= n
    19.6  
    19.7 -include $(BASEDIR)/../Config.mk
    19.8 +XEN_ROOT=$(BASEDIR)/..
    19.9 +include $(XEN_ROOT)/Config.mk
   19.10  
   19.11  # Set ARCH/SUBARCH appropriately.
   19.12  override COMPILE_SUBARCH := $(XEN_COMPILE_ARCH)
    20.1 --- a/xen/arch/x86/dom0_ops.c	Wed Oct 05 14:38:19 2005 +0100
    20.2 +++ b/xen/arch/x86/dom0_ops.c	Wed Oct 05 14:40:35 2005 +0100
    20.3 @@ -186,7 +186,7 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
    20.4          pi->sockets_per_node = 
    20.5              num_online_cpus() / (pi->threads_per_core * pi->cores_per_socket);
    20.6          pi->nr_nodes         = 1;
    20.7 -        pi->total_pages      = max_page;
    20.8 +        pi->total_pages      = total_pages;
    20.9          pi->free_pages       = avail_domheap_pages();
   20.10          pi->cpu_khz          = cpu_khz;
   20.11          memset(pi->hw_cap, 0, sizeof(pi->hw_cap));
    21.1 --- a/xen/arch/x86/mm.c	Wed Oct 05 14:38:19 2005 +0100
    21.2 +++ b/xen/arch/x86/mm.c	Wed Oct 05 14:40:35 2005 +0100
    21.3 @@ -147,6 +147,7 @@ static struct domain *dom_xen, *dom_io;
    21.4  /* Frame table and its size in pages. */
    21.5  struct pfn_info *frame_table;
    21.6  unsigned long max_page;
    21.7 +unsigned long total_pages;
    21.8  
    21.9  void __init init_frametable(void)
   21.10  {
    22.1 --- a/xen/arch/x86/setup.c	Wed Oct 05 14:38:19 2005 +0100
    22.2 +++ b/xen/arch/x86/setup.c	Wed Oct 05 14:40:35 2005 +0100
    22.3 @@ -418,6 +418,7 @@ void __init __start_xen(multiboot_info_t
    22.4      printk("System RAM: %luMB (%lukB)\n", 
    22.5             nr_pages >> (20 - PAGE_SHIFT),
    22.6             nr_pages << (PAGE_SHIFT - 10));
    22.7 +    total_pages = nr_pages;
    22.8  
    22.9      init_frametable();
   22.10  
   22.11 @@ -474,13 +475,14 @@ void __init __start_xen(multiboot_info_t
   22.12      {
   22.13          static char dom0_cmdline[MAX_GUEST_CMDLINE];
   22.14  
   22.15 -        /* Skip past the image name. */
   22.16 +        /* Skip past the image name and copy to a local buffer. */
   22.17          while ( *cmdline == ' ' ) cmdline++;
   22.18          if ( (cmdline = strchr(cmdline, ' ')) != NULL )
   22.19 +        {
   22.20              while ( *cmdline == ' ' ) cmdline++;
   22.21 +            strcpy(dom0_cmdline, cmdline);
   22.22 +        }
   22.23  
   22.24 -        /* Copy the command line to a local buffer. */
   22.25 -        strcpy(dom0_cmdline, cmdline);
   22.26          cmdline = dom0_cmdline;
   22.27  
   22.28          /* Append any extra parameters. */
    23.1 --- a/xen/include/asm-x86/mm.h	Wed Oct 05 14:38:19 2005 +0100
    23.2 +++ b/xen/include/asm-x86/mm.h	Wed Oct 05 14:40:35 2005 +0100
    23.3 @@ -156,6 +156,7 @@ static inline u32 pickle_domptr(struct d
    23.4  
    23.5  extern struct pfn_info *frame_table;
    23.6  extern unsigned long max_page;
    23.7 +extern unsigned long total_pages;
    23.8  void init_frametable(void);
    23.9  
   23.10  int alloc_page_type(struct pfn_info *page, unsigned long type);