WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [TPM] Add an upgrade patch to bring TPM s

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [TPM] Add an upgrade patch to bring TPM subsystem to 2.6.17-rc4.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 30 Jun 2006 15:40:19 +0000
Delivery-date: Fri, 30 Jun 2006 08:42:46 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID e3ad9b9c95eedaa44144e97c34024ba902dca0bf
# Parent  da8da6e1e1d609b1ceedb552475b72684e8461f5
[TPM] Add an upgrade patch to bring TPM subsystem to 2.6.17-rc4.

This patch adds the updated and newer driver plugins appearing in
2.6.17-rc4 to the 2.6.16.13 kernel. The patch needs to be placed into
the patches/linux-2.6.16.13 directory and should be removed once an
upgrade is done to 2.6.17-rc4 or later version.

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>
---
 patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch |  704 ++++++++++++++++++++++++
 1 files changed, 704 insertions(+)

diff -r da8da6e1e1d6 -r e3ad9b9c95ee 
patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch   Wed Jun 28 16:21:30 
2006 +0100
@@ -0,0 +1,1546 @@
+diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.c 
./drivers/char/tpm/tpm_atmel.c
+--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.c   2006-06-26 
18:05:03.000000000 -0400
++++ ./drivers/char/tpm/tpm_atmel.c     2006-06-26 18:16:33.000000000 -0400
+@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip
+               return -EIO;
+ 
+       for (i = 0; i < 6; i++) {
+-              status = ioread8(chip->vendor->iobase + 1);
++              status = ioread8(chip->vendor.iobase + 1);
+               if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+                       dev_err(chip->dev, "error reading header\n");
+                       return -EIO;
+               }
+-              *buf++ = ioread8(chip->vendor->iobase);
++              *buf++ = ioread8(chip->vendor.iobase);
+       }
+ 
+       /* size of the data received */
+@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip
+               dev_err(chip->dev,
+                       "Recv size(%d) less than available space\n", size);
+               for (; i < size; i++) { /* clear the waiting data anyway */
+-                      status = ioread8(chip->vendor->iobase + 1);
++                      status = ioread8(chip->vendor.iobase + 1);
+                       if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+                               dev_err(chip->dev, "error reading data\n");
+                               return -EIO;
+@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip
+ 
+       /* read all the data available */
+       for (; i < size; i++) {
+-              status = ioread8(chip->vendor->iobase + 1);
++              status = ioread8(chip->vendor.iobase + 1);
+               if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+                       dev_err(chip->dev, "error reading data\n");
+                       return -EIO;
+               }
+-              *buf++ = ioread8(chip->vendor->iobase);
++              *buf++ = ioread8(chip->vendor.iobase);
+       }
+ 
+       /* make sure data available is gone */
+-      status = ioread8(chip->vendor->iobase + 1);
++      status = ioread8(chip->vendor.iobase + 1);
+ 
+       if (status & ATML_STATUS_DATA_AVAIL) {
+               dev_err(chip->dev, "data available is stuck\n");
+@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip
+       dev_dbg(chip->dev, "tpm_atml_send:\n");
+       for (i = 0; i < count; i++) {
+               dev_dbg(chip->dev, "%d 0x%x(%d)\n",  i, buf[i], buf[i]);
+-              iowrite8(buf[i], chip->vendor->iobase);
++              iowrite8(buf[i], chip->vendor.iobase);
+       }
+ 
+       return count;
+@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip
+ 
+ static void tpm_atml_cancel(struct tpm_chip *chip)
+ {
+-      iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1);
++      iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1);
+ }
+ 
+ static u8 tpm_atml_status(struct tpm_chip *chip)
+ {
+-      return ioread8(chip->vendor->iobase + 1);
++      return ioread8(chip->vendor.iobase + 1);
+ }
+ 
+ static struct file_operations atmel_ops = {
+@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] =
+ 
+ static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
+ 
+-static struct tpm_vendor_specific tpm_atmel = {
++static const struct tpm_vendor_specific tpm_atmel = {
+       .recv = tpm_atml_recv,
+       .send = tpm_atml_send,
+       .cancel = tpm_atml_cancel,
+@@ -159,10 +159,10 @@ static void atml_plat_remove(void)
+       struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
+ 
+       if (chip) {
+-              if (chip->vendor->have_region)
+-                      atmel_release_region(chip->vendor->base,
+-                                           chip->vendor->region_size);
+-              atmel_put_base_addr(chip->vendor);
++              if (chip->vendor.have_region)
++                      atmel_release_region(chip->vendor.base,
++                                           chip->vendor.region_size);
++              atmel_put_base_addr(chip->vendor.iobase);
+               tpm_remove_hardware(chip->dev);
+               platform_device_unregister(pdev);
+       }
+@@ -179,18 +179,22 @@ static struct device_driver atml_drv = {
+ static int __init init_atmel(void)
+ {
+       int rc = 0;
++      void __iomem *iobase = NULL;
++      int have_region, region_size;
++      unsigned long base;
++      struct  tpm_chip *chip;
+ 
+       driver_register(&atml_drv);
+ 
+-      if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) {
++      if ((iobase = atmel_get_base_addr(&base, &region_size)) == NULL) {
+               rc = -ENODEV;
+               goto err_unreg_drv;
+       }
+ 
+-      tpm_atmel.have_region =
++      have_region =
+           (atmel_request_region
+-           (tpm_atmel.base, tpm_atmel.region_size,
+-            "tpm_atmel0") == NULL) ? 0 : 1;
++           (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
++
+ 
+       if (IS_ERR
+           (pdev =
+@@ -199,17 +203,25 @@ static int __init init_atmel(void)
+               goto err_rel_reg;
+       }
+ 
+-      if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0)
++      if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) {
++              rc = -ENODEV;
+               goto err_unreg_dev;
++      }
++
++      chip->vendor.iobase = iobase;
++      chip->vendor.base = base;
++      chip->vendor.have_region = have_region;
++      chip->vendor.region_size = region_size;
++
+       return 0;
+ 
+ err_unreg_dev:
+       platform_device_unregister(pdev);
+ err_rel_reg:
+-      atmel_put_base_addr(&tpm_atmel);
+-      if (tpm_atmel.have_region)
+-              atmel_release_region(tpm_atmel.base,
+-                                   tpm_atmel.region_size);
++      atmel_put_base_addr(iobase);
++      if (have_region)
++              atmel_release_region(base,
++                                   region_size);
+ err_unreg_drv:
+       driver_unregister(&atml_drv);
+       return rc;
+diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.h 
./drivers/char/tpm/tpm_atmel.h
+--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.h   2006-06-26 
18:05:03.000000000 -0400
++++ ./drivers/char/tpm/tpm_atmel.h     2006-06-26 18:16:33.000000000 -0400
+@@ -28,13 +28,12 @@
+ #define atmel_request_region request_mem_region
+ #define atmel_release_region release_mem_region
+ 
+-static inline void atmel_put_base_addr(struct tpm_vendor_specific
+-                                       *vendor)
++static inline void atmel_put_base_addr(void __iomem *iobase)
+ {
+-      iounmap(vendor->iobase);
++      iounmap(iobase);
+ }
+ 
+-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
++static void __iomem * atmel_get_base_addr(unsigned long *base, int 
*region_size)
+ {
+       struct device_node *dn;
+       unsigned long address, size;
+@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_add
+       else
+               size = reg[naddrc];
+ 
+-      vendor->base = address;
+-      vendor->region_size = size;
+-      return ioremap(vendor->base, vendor->region_size);
++      *base = address;
++      *region_size = size;
++      return ioremap(*base, *region_size);
+ }
+ #else
+ #define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
+@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void)
+       return 0;
+ }
+ 
+-static inline void atmel_put_base_addr(struct tpm_vendor_specific
+-                                       *vendor)
++static inline void atmel_put_base_addr(void __iomem *iobase)
+ {
+ }
+ 
+ /* Determine where to talk to device */
+-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
+-                                       *vendor)
++static void __iomem * atmel_get_base_addr(unsigned long *base, int 
*region_size)
+ {
+       int lo, hi;
+ 
+@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_add
+       lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
+       hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
+ 
+-      vendor->base = (hi << 8) | lo;
+-      vendor->region_size = 2;
++      *base = (hi << 8) | lo;
++      *region_size = 2;
+ 
+-      return ioport_map(vendor->base, vendor->region_size);
++      return ioport_map(*base, *region_size);
+ }
+ #endif
+diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_bios.c 
./drivers/char/tpm/tpm_bios.c
+--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_bios.c    2006-06-26 
18:05:03.000000000 -0400
++++ ./drivers/char/tpm/tpm_bios.c      2006-06-26 18:16:33.000000000 -0400
+@@ -29,6 +29,11 @@
+ #define MAX_TEXT_EVENT                1000    /* Max event string length */
+ #define ACPI_TCPA_SIG         "TCPA"  /* 0x41504354 /'TCPA' */
+ 
++enum bios_platform_class {
++      BIOS_CLIENT = 0x00,
++      BIOS_SERVER = 0x01,
++};
++
+ struct tpm_bios_log {
+       void *bios_event_log;
+       void *bios_event_log_end;
+@@ -36,9 +41,18 @@ struct tpm_bios_log {
+ 
+ struct acpi_tcpa {
+       struct acpi_table_header hdr;
+-      u16 reserved;
+-      u32 log_max_len __attribute__ ((packed));
+-      u32 log_start_addr __attribute__ ((packed));
++      u16 platform_class;
++      union {
++              struct client_hdr {
++                      u32 log_max_len __attribute__ ((packed));
++                      u64 log_start_addr __attribute__ ((packed));
++              } client;
++              struct server_hdr {
++                      u16 reserved;
++                      u64 log_max_len __attribute__ ((packed));
++                      u64 log_start_addr __attribute__ ((packed));
++              } server;
++      };
+ };
+ 
+ struct tcpa_event {
+@@ -91,6 +105,12 @@ static const char* tcpa_event_type_strin
+       "Non-Host Info"
+ };
+ 
++struct tcpa_pc_event {
++      u32 event_id;
++      u32 event_size;
++      u8 event_data[0];
++};
++
+ enum tcpa_pc_event_ids {
+       SMBIOS = 1,
+       BIS_CERT,
+@@ -100,14 +120,15 @@ enum tcpa_pc_event_ids {
+       NVRAM,
+       OPTION_ROM_EXEC,
+       OPTION_ROM_CONFIG,
+-      OPTION_ROM_MICROCODE,
++      OPTION_ROM_MICROCODE = 10,
+       S_CRTM_VERSION,
+       S_CRTM_CONTENTS,
+       POST_CONTENTS,
++      HOST_TABLE_OF_DEVICES,
+ };
+ 
+ static const char* tcpa_pc_event_id_strings[] = {
+-      ""
++      "",
+       "SMBIOS",
+       "BIS Certificate",
+       "POST BIOS ",
+@@ -116,10 +137,12 @@ static const char* tcpa_pc_event_id_stri
+       "NVRAM",
+       "Option ROM",
+       "Option ROM config",
+-      "Option ROM microcode",
++      "",
++      "Option ROM microcode ",
+       "S-CRTM Version",
+-      "S-CRTM Contents",
+-      "S-CRTM POST Contents",
++      "S-CRTM Contents ",
++      "POST Contents ",
++      "Table of Devices",
+ };
+ 
+ /* returns pointer to start of pos. entry of tcg log */
+@@ -191,7 +214,7 @@ static int get_event_name(char *dest, st
+       const char *name = "";
+       char data[40] = "";
+       int i, n_len = 0, d_len = 0;
+-      u32 event_id;
++      struct tcpa_pc_event *pc_event;
+ 
+       switch(event->event_type) {
+       case PREBOOT:
+@@ -220,31 +243,32 @@ static int get_event_name(char *dest, st
+               }
+               break;
+       case EVENT_TAG:
+-              event_id = be32_to_cpu(*((u32 *)event_entry));
++              pc_event = (struct tcpa_pc_event *)event_entry;
+ 
+               /* ToDo Row data -> Base64 */
+ 
+-              switch (event_id) {
++              switch (pc_event->event_id) {
+               case SMBIOS:
+               case BIS_CERT:
+               case CMOS:
+               case NVRAM:
+               case OPTION_ROM_EXEC:
+               case OPTION_ROM_CONFIG:
+-              case OPTION_ROM_MICROCODE:
+               case S_CRTM_VERSION:
+-              case S_CRTM_CONTENTS:
+-              case POST_CONTENTS:
+-                      name = tcpa_pc_event_id_strings[event_id];
++                      name = tcpa_pc_event_id_strings[pc_event->event_id];
+                       n_len = strlen(name);
+                       break;
++              /* hash data */
+               case POST_BIOS_ROM:
+               case ESCD:
+-                      name = tcpa_pc_event_id_strings[event_id];
++              case OPTION_ROM_MICROCODE:
++              case S_CRTM_CONTENTS:
++              case POST_CONTENTS:
++                      name = tcpa_pc_event_id_strings[pc_event->event_id];
+                       n_len = strlen(name);
+                       for (i = 0; i < 20; i++)
+-                              d_len += sprintf(data, "%02x",
+-                                              event_entry[8 + i]);
++                              d_len += sprintf(&data[2*i], "%02x",
++                                              pc_event->event_data[i]);
+                       break;
+               default:
+                       break;
+@@ -260,52 +284,13 @@ static int get_event_name(char *dest, st
+ 
+ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
+ {
++      struct tcpa_event *event = v;
++      char *data = v;
++      int i;
+ 
+-      char *eventname;
+-      char data[4];
+-      u32 help;
+-      int i, len;
+-      struct tcpa_event *event = (struct tcpa_event *) v;
+-      unsigned char *event_entry =
+-          (unsigned char *) (v + sizeof(struct tcpa_event));
+-
+-      eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
+-      if (!eventname) {
+-              printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
+-                     __func__);
+-              return -ENOMEM;
+-      }
+-
+-      /* 1st: PCR used is in little-endian format (4 bytes) */
+-      help = le32_to_cpu(event->pcr_index);
+-      memcpy(data, &help, 4);
+-      for (i = 0; i < 4; i++)
+-              seq_putc(m, data[i]);
+-
+-      /* 2nd: SHA1 (20 bytes) */
+-      for (i = 0; i < 20; i++)
+-              seq_putc(m, event->pcr_value[i]);
+-
+-      /* 3rd: event type identifier (4 bytes) */
+-      help = le32_to_cpu(event->event_type);
+-      memcpy(data, &help, 4);
+-      for (i = 0; i < 4; i++)
++      for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
+               seq_putc(m, data[i]);
+ 
+-      len = 0;
+-
+-      len += get_event_name(eventname, event, event_entry);
+-
+-      /* 4th:  filename <= 255 + \'0' delimiter */
+-      if (len > TCG_EVENT_NAME_LEN_MAX)
+-              len = TCG_EVENT_NAME_LEN_MAX;
+-
+-      for (i = 0; i < len; i++)
+-              seq_putc(m, eventname[i]);
+-
+-      /* 5th: delimiter */
+-      seq_putc(m, '\0');
+-
+       return 0;
+ }
+ 
+@@ -353,6 +338,7 @@ static int tpm_ascii_bios_measurements_s
+       /* 4th: eventname <= max + \'0' delimiter */
+       seq_printf(m, " %s\n", eventname);
+ 
++      kfree(eventname);
+       return 0;
+ }
+ 
+@@ -376,6 +362,7 @@ static int read_log(struct tpm_bios_log 
+       struct acpi_tcpa *buff;
+       acpi_status status;
+       struct acpi_table_header *virt;
++      u64 len, start;
+ 
+       if (log->bios_event_log != NULL) {
+               printk(KERN_ERR
+@@ -396,27 +383,37 @@ static int read_log(struct tpm_bios_log 
+               return -EIO;
+       }
+ 
+-      if (buff->log_max_len == 0) {
++      switch(buff->platform_class) {
++      case BIOS_SERVER:
++              len = buff->server.log_max_len;
++              start = buff->server.log_start_addr;
++              break;
++      case BIOS_CLIENT:
++      default:
++              len = buff->client.log_max_len;
++              start = buff->client.log_start_addr;
++              break;
++      }
++      if (!len) {
+               printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
+               return -EIO;
+       }
+ 
+       /* malloc EventLog space */
+-      log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
++      log->bios_event_log = kmalloc(len, GFP_KERNEL);
+       if (!log->bios_event_log) {
+-              printk
+-                  ("%s: ERROR - Not enough  Memory for BIOS measurements\n",
+-                   __func__);
++              printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
++                      __func__);
+               return -ENOMEM;
+       }
+ 
+-      log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
++      log->bios_event_log_end = log->bios_event_log + len;
+ 
+-      acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) 
&virt);
++      acpi_os_map_memory(start, len, (void *) &virt);
+ 
+-      memcpy(log->bios_event_log, virt, buff->log_max_len);
++      memcpy(log->bios_event_log, virt, len);
+ 
+-      acpi_os_unmap_memory(virt, buff->log_max_len);
++      acpi_os_unmap_memory(virt, len);
+       return 0;
+ }
+ 
+diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_infineon.c 
./drivers/char/tpm/tpm_infineon.c
+--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_infineon.c        
2006-06-26 18:05:03.000000000 -0400
++++ ./drivers/char/tpm/tpm_infineon.c  2006-06-26 18:16:33.000000000 -0400
+@@ -15,6 +15,7 @@
+  * License.
+  */
+ 
++#include <linux/init.h>
+ #include <linux/pnp.h>
+ #include "tpm.h"
+ 
+@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *c
+ 
+       if (clear_wrfifo) {
+               for (i = 0; i < 4096; i++) {
+-                      status = inb(chip->vendor->base + WRFIFO);
++                      status = inb(chip->vendor.base + WRFIFO);
+                       if (status == 0xff) {
+                               if (check == 5)
+                                       break;
+@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *c
+        */
+       i = 0;
+       do {
+-              status = inb(chip->vendor->base + RDFIFO);
+-              status = inb(chip->vendor->base + STAT);
++              status = inb(chip->vendor.base + RDFIFO);
++              status = inb(chip->vendor.base + STAT);
+               i++;
+               if (i == TPM_MAX_TRIES)
+                       return -EIO;
+@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, i
+       int status;
+       int i;
+       for (i = 0; i < TPM_MAX_TRIES; i++) {
+-              status = inb(chip->vendor->base + STAT);
++              status = inb(chip->vendor.base + STAT);
+               /* check the status-register if wait_for_bit is set */
+               if (status & 1 << wait_for_bit)
+                       break;
+@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, i
+ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
+ {
+       wait(chip, STAT_XFE);
+-      outb(sendbyte, chip->vendor->base + WRFIFO);
++      outb(sendbyte, chip->vendor.base + WRFIFO);
+ }
+ 
+     /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
+@@ -204,7 +205,7 @@ recv_begin:
+               ret = wait(chip, STAT_RDA);
+               if (ret)
+                       return -EIO;
+-              buf[i] = inb(chip->vendor->base + RDFIFO);
++              buf[i] = inb(chip->vendor.base + RDFIFO);
+       }
+ 
+       if (buf[0] != TPM_VL_VER) {
+@@ -219,7 +220,7 @@ recv_begin:
+ 
+               for (i = 0; i < size; i++) {
+                       wait(chip, STAT_RDA);
+-                      buf[i] = inb(chip->vendor->base + RDFIFO);
++                      buf[i] = inb(chip->vendor.base + RDFIFO);
+               }
+ 
+               if ((size == 0x6D00) && (buf[1] == 0x80)) {
+@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip 
+       u8 count_high, count_low, count_4, count_3, count_2, count_1;
+ 
+       /* Disabling Reset, LP and IRQC */
+-      outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
++      outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD);
+ 
+       ret = empty_fifo(chip, 1);
+       if (ret) {
+@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_ch
+ 
+ static u8 tpm_inf_status(struct tpm_chip *chip)
+ {
+-      return inb(chip->vendor->base + STAT);
++      return inb(chip->vendor.base + STAT);
+ }
+ 
+ static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+@@ -346,7 +347,7 @@ static struct file_operations inf_ops = 
+       .release = tpm_release,
+ };
+ 
+-static struct tpm_vendor_specific tpm_inf = {
++static const struct tpm_vendor_specific tpm_inf = {
+       .recv = tpm_inf_recv,
+       .send = tpm_inf_send,
+       .cancel = tpm_inf_cancel,
+@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(s
+       int version[2];
+       int productid[2];
+       char chipname[20];
++      struct tpm_chip *chip;
+ 
+       /* read IO-ports through PnP */
+       if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
+@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(s
+                       goto err_last;
+               }
+               /* publish my base address and request region */
+-              tpm_inf.base = TPM_INF_BASE;
+               if (request_region
+-                  (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
++                  (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
+                       rc = -EINVAL;
+                       goto err_last;
+               }
+-              if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN,
+-                              "tpm_infineon0") == NULL) {
++              if (request_region
++                  (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) {
+                       rc = -EINVAL;
+                       goto err_last;
+               }
+@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(s
+ 
+               /* configure TPM with IO-ports */
+               outb(IOLIMH, TPM_INF_ADDR);
+-              outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
++              outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA);
+               outb(IOLIML, TPM_INF_ADDR);
+-              outb((tpm_inf.base & 0xff), TPM_INF_DATA);
++              outb((TPM_INF_BASE & 0xff), TPM_INF_DATA);
+ 
+               /* control if IO-ports are set correctly */
+               outb(IOLIMH, TPM_INF_ADDR);
+@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(s
+               outb(IOLIML, TPM_INF_ADDR);
+               iol = inb(TPM_INF_DATA);
+ 
+-              if ((ioh << 8 | iol) != tpm_inf.base) {
++              if ((ioh << 8 | iol) != TPM_INF_BASE) {
+                       dev_err(&dev->dev,
+-                              "Could not set IO-ports to 0x%lx\n",
+-                              tpm_inf.base);
++                              "Could not set IO-ports to 0x%x\n",
++                              TPM_INF_BASE);
+                       rc = -EIO;
+                       goto err_release_region;
+               }
+@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(s
+               outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
+ 
+               /* disable RESET, LP and IRQC */
+-              outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
++              outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD);
+ 
+               /* Finally, we're done, print some infos */
+               dev_info(&dev->dev, "TPM found: "
+                        "config base 0x%x, "
+                        "io base 0x%x, "
+-                       "chip version %02x%02x, "
+-                       "vendor id %x%x (Infineon), "
+-                       "product id %02x%02x"
++                       "chip version 0x%02x%02x, "
++                       "vendor id 0x%x%x (Infineon), "
++                       "product id 0x%02x%02x"
+                        "%s\n",
+                        TPM_INF_ADDR,
+                        TPM_INF_BASE,
+@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(s
+                        vendorid[0], vendorid[1],
+                        productid[0], productid[1], chipname);
+ 
+-              rc = tpm_register_hardware(&dev->dev, &tpm_inf);
+-              if (rc < 0) {
+-                      rc = -ENODEV;
++              if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) {
+                       goto err_release_region;
+               }
++              chip->vendor.base = TPM_INF_BASE;
+               return 0;
+       } else {
+               rc = -ENODEV;
+@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(s
+       }
+ 
+ err_release_region:
+-      release_region(tpm_inf.base, TPM_INF_PORT_LEN);
++      release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
+       release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
+ 
+ err_last:
+@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove
+       struct tpm_chip *chip = pnp_get_drvdata(dev);
+ 
+       if (chip) {
+-              release_region(chip->vendor->base, TPM_INF_PORT_LEN);
++              release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
++              release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
+               tpm_remove_hardware(chip->dev);
+       }
+ }
+@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = {
+       },
+       .id_table = tpm_pnp_tbl,
+       .probe = tpm_inf_pnp_probe,
+-      .remove = tpm_inf_pnp_remove,
++      .remove = __devexit_p(tpm_inf_pnp_remove),
+ };
+ 
+ static int __init init_inf(void)
+@@ -538,5 +539,5 @@ module_exit(cleanup_inf);
+ 
+ MODULE_AUTHOR("Marcel Selhorst <selhorst@xxxxxxxxxxxxx>");
+ MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 
1.2");
+-MODULE_VERSION("1.7");
++MODULE_VERSION("1.8");
+ MODULE_LICENSE("GPL");
+diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_nsc.c 
./drivers/char/tpm/tpm_nsc.c
+--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_nsc.c     2006-06-26 
18:05:03.000000000 -0400
++++ ./drivers/char/tpm/tpm_nsc.c       2006-06-26 18:16:33.000000000 -0400
+@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip
+       unsigned long stop;
+ 
+       /* status immediately available check */
+-      *data = inb(chip->vendor->base + NSC_STATUS);
++      *data = inb(chip->vendor.base + NSC_STATUS);
+       if ((*data & mask) == val)
+               return 0;
+ 
+@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip
+       stop = jiffies + 10 * HZ;
+       do {
+               msleep(TPM_TIMEOUT);
+-              *data = inb(chip->vendor->base + 1);
++              *data = inb(chip->vendor.base + 1);
+               if ((*data & mask) == val)
+                       return 0;
+       }
+@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm
+       unsigned long stop;
+ 
+       /* status immediately available check */
+-      status = inb(chip->vendor->base + NSC_STATUS);
++      status = inb(chip->vendor.base + NSC_STATUS);
+       if (status & NSC_STATUS_OBF)
+-              status = inb(chip->vendor->base + NSC_DATA);
++              status = inb(chip->vendor.base + NSC_DATA);
+       if (status & NSC_STATUS_RDY)
+               return 0;
+ 
+@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm
+       stop = jiffies + 100;
+       do {
+               msleep(TPM_TIMEOUT);
+-              status = inb(chip->vendor->base + NSC_STATUS);
++              status = inb(chip->vendor.base + NSC_STATUS);
+               if (status & NSC_STATUS_OBF)
+-                      status = inb(chip->vendor->base + NSC_DATA);
++                      status = inb(chip->vendor.base + NSC_DATA);
+               if (status & NSC_STATUS_RDY)
+                       return 0;
+       }
+@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip 
+               return -EIO;
+       }
+       if ((data =
+-           inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
++           inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+               dev_err(chip->dev, "not in normal mode (0x%x)\n",
+                       data);
+               return -EIO;
+@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip 
+               }
+               if (data & NSC_STATUS_F0)
+                       break;
+-              *p = inb(chip->vendor->base + NSC_DATA);
++              *p = inb(chip->vendor.base + NSC_DATA);
+       }
+ 
+       if ((data & NSC_STATUS_F0) == 0 &&
+@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip 
+               dev_err(chip->dev, "F0 not set\n");
+               return -EIO;
+       }
+-      if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
++      if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
+               dev_err(chip->dev,
+                       "expected end of command(0x%x)\n", data);
+               return -EIO;
+@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip 
+        * fix it. Not sure why this is needed, we followed the flow
+        * chart in the manual to the letter.
+        */
+-      outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
++      outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
+ 
+       if (nsc_wait_for_ready(chip) != 0)
+               return -EIO;
+@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip 
+               return -EIO;
+       }
+ 
+-      outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
++      outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
+       if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
+               dev_err(chip->dev, "IBR timeout\n");
+               return -EIO;
+@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip 
+                               "IBF timeout (while writing data)\n");
+                       return -EIO;
+               }
+-              outb(buf[i], chip->vendor->base + NSC_DATA);
++              outb(buf[i], chip->vendor.base + NSC_DATA);
+       }
+ 
+       if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+               dev_err(chip->dev, "IBF timeout\n");
+               return -EIO;
+       }
+-      outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
++      outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
+ 
+       return count;
+ }
+ 
+ static void tpm_nsc_cancel(struct tpm_chip *chip)
+ {
+-      outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
++      outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
+ }
+ 
+ static u8 tpm_nsc_status(struct tpm_chip *chip)
+ {
+-      return inb(chip->vendor->base + NSC_STATUS);
++      return inb(chip->vendor.base + NSC_STATUS);
+ }
+ 
+ static struct file_operations nsc_ops = {
+@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] = 
+ 
+ static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
+ 
+-static struct tpm_vendor_specific tpm_nsc = {
++static const struct tpm_vendor_specific tpm_nsc = {
+       .recv = tpm_nsc_recv,
+       .send = tpm_nsc_send,
+       .cancel = tpm_nsc_cancel,
+@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(str
+ {
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+       if ( chip ) {
+-              release_region(chip->vendor->base, 2);
++              release_region(chip->vendor.base, 2);
+               tpm_remove_hardware(chip->dev);
+       }
+ }
+@@ -286,7 +286,8 @@ static int __init init_nsc(void)
+       int rc = 0;
+       int lo, hi;
+       int nscAddrBase = TPM_ADDR;
+-
++      struct tpm_chip *chip;
++      unsigned long base;
+ 
+       /* verify that it is a National part (SID) */
+       if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
+@@ -300,7 +301,7 @@ static int __init init_nsc(void)
+ 
+       hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
+       lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
+-      tpm_nsc.base = (hi<<8) | lo;
++      base = (hi<<8) | lo;
+ 
+       /* enable the DPM module */
+       tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
+@@ -320,13 +321,15 @@ static int __init init_nsc(void)
+       if ((rc = platform_device_register(pdev)) < 0)
+               goto err_free_dev;
+ 
+-      if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
++      if (request_region(base, 2, "tpm_nsc0") == NULL ) {
+               rc = -EBUSY;
+               goto err_unreg_dev;
+       }
+ 
+-      if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0)
++      if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
++              rc = -ENODEV;
+               goto err_rel_reg;
++      }
+ 
+       dev_dbg(&pdev->dev, "NSC TPM detected\n");
+       dev_dbg(&pdev->dev,
+@@ -361,10 +364,12 @@ static int __init init_nsc(void)
+                "NSC TPM revision %d\n",
+                tpm_read_index(nscAddrBase, 0x27) & 0x1F);
+ 
++      chip->vendor.base = base;
++
+       return 0;
+ 
+ err_rel_reg:
+-      release_region(tpm_nsc.base, 2);
++      release_region(base, 2);
+ err_unreg_dev:
+       platform_device_unregister(pdev);
+ err_free_dev:
+diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_tis.c 
./drivers/char/tpm/tpm_tis.c
+--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_tis.c     1969-12-31 
19:00:00.000000000 -0500
++++ ./drivers/char/tpm/tpm_tis.c       2006-06-26 18:16:33.000000000 -0400
+@@ -0,0 +1,665 @@
++/*
++ * Copyright (C) 2005, 2006 IBM Corporation
++ *
++ * Authors:
++ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
++ * Kylene Hall <kjhall@xxxxxxxxxx>
++ *
++ * Device driver for TCG/TCPA TPM (trusted platform module).
++ * Specifications at www.trustedcomputinggroup.org
++ *
++ * This device driver implements the TPM interface as defined in
++ * the TCG TPM Interface Spec version 1.2, revision 1.0.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation, version 2 of the
++ * License.
++ */
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/pnp.h>
++#include <linux/interrupt.h>
++#include <linux/wait.h>
++#include "tpm.h"
++
++#define TPM_HEADER_SIZE 10
++
++enum tis_access {
++      TPM_ACCESS_VALID = 0x80,
++      TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
++      TPM_ACCESS_REQUEST_PENDING = 0x04,
++      TPM_ACCESS_REQUEST_USE = 0x02,
++};
++
++enum tis_status {
++      TPM_STS_VALID = 0x80,
++      TPM_STS_COMMAND_READY = 0x40,
++      TPM_STS_GO = 0x20,
++      TPM_STS_DATA_AVAIL = 0x10,
++      TPM_STS_DATA_EXPECT = 0x08,
++};
++
++enum tis_int_flags {
++      TPM_GLOBAL_INT_ENABLE = 0x80000000,
++      TPM_INTF_BURST_COUNT_STATIC = 0x100,
++      TPM_INTF_CMD_READY_INT = 0x080,
++      TPM_INTF_INT_EDGE_FALLING = 0x040,
++      TPM_INTF_INT_EDGE_RISING = 0x020,
++      TPM_INTF_INT_LEVEL_LOW = 0x010,
++      TPM_INTF_INT_LEVEL_HIGH = 0x008,
++      TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
++      TPM_INTF_STS_VALID_INT = 0x002,
++      TPM_INTF_DATA_AVAIL_INT = 0x001,
++};
++
++enum tis_defaults {
++      TIS_MEM_BASE = 0xFED40000,
++      TIS_MEM_LEN = 0x5000,
++      TIS_SHORT_TIMEOUT = 750,        /* ms */
++      TIS_LONG_TIMEOUT = 2000,        /* 2 sec */
++};
++
++#define       TPM_ACCESS(l)                   (0x0000 | ((l) << 12))
++#define       TPM_INT_ENABLE(l)               (0x0008 | ((l) << 12))
++#define       TPM_INT_VECTOR(l)               (0x000C | ((l) << 12))
++#define       TPM_INT_STATUS(l)               (0x0010 | ((l) << 12))
++#define       TPM_INTF_CAPS(l)                (0x0014 | ((l) << 12))
++#define       TPM_STS(l)                      (0x0018 | ((l) << 12))
++#define       TPM_DATA_FIFO(l)                (0x0024 | ((l) << 12))
++
++#define       TPM_DID_VID(l)                  (0x0F00 | ((l) << 12))
++#define       TPM_RID(l)                      (0x0F04 | ((l) << 12))
++
++static LIST_HEAD(tis_chips);
++static DEFINE_SPINLOCK(tis_lock);
++
++static int check_locality(struct tpm_chip *chip, int l)
++{
++      if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
++           (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
++          (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
++              return chip->vendor.locality = l;
++
++      return -1;
++}
++
++static void release_locality(struct tpm_chip *chip, int l, int force)
++{
++      if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
++                    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
++          (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
++              iowrite8(TPM_ACCESS_ACTIVE_LOCALITY,
++                       chip->vendor.iobase + TPM_ACCESS(l));
++}
++
++static int request_locality(struct tpm_chip *chip, int l)
++{
++      unsigned long stop;
++      long rc;
++
++      if (check_locality(chip, l) >= 0)
++              return l;
++
++      iowrite8(TPM_ACCESS_REQUEST_USE,
++               chip->vendor.iobase + TPM_ACCESS(l));
++
++      if (chip->vendor.irq) {
++              rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
++                                                    (check_locality
++                                                     (chip, l) >= 0),
++                                                    chip->vendor.timeout_a);
++              if (rc > 0)
++                      return l;
++
++      } else {
++              /* wait for burstcount */
++              stop = jiffies + chip->vendor.timeout_a;
++              do {
++                      if (check_locality(chip, l) >= 0)
++                              return l;
++                      msleep(TPM_TIMEOUT);
++              }
++              while (time_before(jiffies, stop));
++      }
++      return -1;
++}
++
++static u8 tpm_tis_status(struct tpm_chip *chip)
++{
++      return ioread8(chip->vendor.iobase +
++                     TPM_STS(chip->vendor.locality));
++}
++
++static void tpm_tis_ready(struct tpm_chip *chip)
++{
++      /* this causes the current command to be aborted */
++      iowrite8(TPM_STS_COMMAND_READY,
++               chip->vendor.iobase + TPM_STS(chip->vendor.locality));
++}
++
++static int get_burstcount(struct tpm_chip *chip)
++{
++      unsigned long stop;
++      int burstcnt;
++
++      /* wait for burstcount */
++      /* which timeout value, spec has 2 answers (c & d) */
++      stop = jiffies + chip->vendor.timeout_d;
++      do {
++              burstcnt = ioread8(chip->vendor.iobase +
++                                 TPM_STS(chip->vendor.locality) + 1);
++              burstcnt += ioread8(chip->vendor.iobase +
++                                  TPM_STS(chip->vendor.locality) +
++                                  2) << 8;
++              if (burstcnt)
++                      return burstcnt;
++              msleep(TPM_TIMEOUT);
++      } while (time_before(jiffies, stop));
++      return -EBUSY;
++}
++
++static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long 
timeout,
++                       wait_queue_head_t *queue)
++{
++      unsigned long stop;
++      long rc;
++      u8 status;
++
++      /* check current status */
++      status = tpm_tis_status(chip);
++      if ((status & mask) == mask)
++              return 0;
++
++      if (chip->vendor.irq) {
++              rc = wait_event_interruptible_timeout(*queue,
++                                                    ((tpm_tis_status
++                                                      (chip) & mask) ==
++                                                     mask), timeout);
++              if (rc > 0)
++                      return 0;
++      } else {
++              stop = jiffies + timeout;
++              do {
++                      msleep(TPM_TIMEOUT);
++                      status = tpm_tis_status(chip);
++                      if ((status & mask) == mask)
++                              return 0;
++              } while (time_before(jiffies, stop));
++      }
++      return -ETIME;
++}
++
++static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
++{
++      int size = 0, burstcnt;
++      while (size < count &&
++             wait_for_stat(chip,
++                           TPM_STS_DATA_AVAIL | TPM_STS_VALID,
++                           chip->vendor.timeout_c,
++                           &chip->vendor.read_queue)
++             == 0) {
++              burstcnt = get_burstcount(chip);
++              for (; burstcnt > 0 && size < count; burstcnt--)
++                      buf[size++] = ioread8(chip->vendor.iobase +
++                                            TPM_DATA_FIFO(chip->vendor.
++                                                          locality));
++      }
++      return size;
++}
++
++static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
++{
++      int size = 0;
++      int expected, status;
++
++      if (count < TPM_HEADER_SIZE) {
++              size = -EIO;
++              goto out;
++      }
++
++      /* read first 10 bytes, including tag, paramsize, and result */
++      if ((size =
++           recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
++              dev_err(chip->dev, "Unable to read header\n");
++              goto out;
++      }
++
++      expected = be32_to_cpu(*(__be32 *) (buf + 2));
++      if (expected > count) {
++              size = -EIO;
++              goto out;
++      }
++
++      if ((size +=
++           recv_data(chip, &buf[TPM_HEADER_SIZE],
++                     expected - TPM_HEADER_SIZE)) < expected) {
++              dev_err(chip->dev, "Unable to read remainder of result\n");
++              size = -ETIME;
++              goto out;
++      }
++
++      wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
++                    &chip->vendor.int_queue);
++      status = tpm_tis_status(chip);
++      if (status & TPM_STS_DATA_AVAIL) {      /* retry? */
++              dev_err(chip->dev, "Error left over data\n");
++              size = -EIO;
++              goto out;
++      }
++
++out:
++      tpm_tis_ready(chip);
++      release_locality(chip, chip->vendor.locality, 0);
++      return size;
++}
++
++/*
++ * If interrupts are used (signaled by an irq set in the vendor structure)
++ * tpm.c can skip polling for the data to be available as the interrupt is
++ * waited for here
++ */
++static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
++{
++      int rc, status, burstcnt;
++      size_t count = 0;
++      u32 ordinal;
++
++      if (request_locality(chip, 0) < 0)
++              return -EBUSY;
++
++      status = tpm_tis_status(chip);
++      if ((status & TPM_STS_COMMAND_READY) == 0) {
++              tpm_tis_ready(chip);
++              if (wait_for_stat
++                  (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
++                   &chip->vendor.int_queue) < 0) {
++                      rc = -ETIME;
++                      goto out_err;
++              }
++      }
++
++      while (count < len - 1) {
++              burstcnt = get_burstcount(chip);
++              for (; burstcnt > 0 && count < len - 1; burstcnt--) {
++                      iowrite8(buf[count], chip->vendor.iobase +
++                               TPM_DATA_FIFO(chip->vendor.locality));
++                      count++;
++              }
++
++              wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
++                            &chip->vendor.int_queue);
++              status = tpm_tis_status(chip);
++              if ((status & TPM_STS_DATA_EXPECT) == 0) {
++                      rc = -EIO;
++                      goto out_err;
++              }
++      }
++
++      /* write last byte */
++      iowrite8(buf[count],
++               chip->vendor.iobase +
++               TPM_DATA_FIFO(chip->vendor.locality));
++      wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
++                    &chip->vendor.int_queue);
++      status = tpm_tis_status(chip);
++      if ((status & TPM_STS_DATA_EXPECT) != 0) {
++              rc = -EIO;
++              goto out_err;
++      }
++
++      /* go and do it */
++      iowrite8(TPM_STS_GO,
++               chip->vendor.iobase + TPM_STS(chip->vendor.locality));
++
++      if (chip->vendor.irq) {
++              ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
++              if (wait_for_stat
++                  (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
++                   tpm_calc_ordinal_duration(chip, ordinal),
++                   &chip->vendor.read_queue) < 0) {
++                      rc = -ETIME;
++                      goto out_err;
++              }
++      }
++      return len;
++out_err:
++      tpm_tis_ready(chip);
++      release_locality(chip, chip->vendor.locality, 0);
++      return rc;
++}
++
++static struct file_operations tis_ops = {
++      .owner = THIS_MODULE,
++      .llseek = no_llseek,
++      .open = tpm_open,
++      .read = tpm_read,
++      .write = tpm_write,
++      .release = tpm_release,
++};
++
++static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
++static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
++static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
++static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
++static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
++static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
++                 NULL);
++static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
++static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
++
++static struct attribute *tis_attrs[] = {
++      &dev_attr_pubek.attr,
++      &dev_attr_pcrs.attr,
++      &dev_attr_enabled.attr,
++      &dev_attr_active.attr,
++      &dev_attr_owned.attr,
++      &dev_attr_temp_deactivated.attr,
++      &dev_attr_caps.attr,
++      &dev_attr_cancel.attr, NULL,
++};
++
++static struct attribute_group tis_attr_grp = {
++      .attrs = tis_attrs
++};
++
++static struct tpm_vendor_specific tpm_tis = {
++      .status = tpm_tis_status,
++      .recv = tpm_tis_recv,
++      .send = tpm_tis_send,
++      .cancel = tpm_tis_ready,
++      .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
++      .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
++      .req_canceled = TPM_STS_COMMAND_READY,
++      .attr_group = &tis_attr_grp,
++      .miscdev = {
++                  .fops = &tis_ops,},
++};
++
++static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs)
++{
++      struct tpm_chip *chip = (struct tpm_chip *) dev_id;
++      u32 interrupt;
++
++      interrupt = ioread32(chip->vendor.iobase +
++                           TPM_INT_STATUS(chip->vendor.locality));
++
++      if (interrupt == 0)
++              return IRQ_NONE;
++
++      chip->vendor.irq = irq;
++
++      /* Clear interrupts handled with TPM_EOI */
++      iowrite32(interrupt,
++                chip->vendor.iobase +
++                TPM_INT_STATUS(chip->vendor.locality));
++      return IRQ_HANDLED;
++}
++
++static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs 
*regs)
++{
++      struct tpm_chip *chip = (struct tpm_chip *) dev_id;
++      u32 interrupt;
++      int i;
++
++      interrupt = ioread32(chip->vendor.iobase +
++                           TPM_INT_STATUS(chip->vendor.locality));
++
++      if (interrupt == 0)
++              return IRQ_NONE;
++
++      if (interrupt & TPM_INTF_DATA_AVAIL_INT)
++              wake_up_interruptible(&chip->vendor.read_queue);
++      if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
++              for (i = 0; i < 5; i++)
++                      if (check_locality(chip, i) >= 0)
++                              break;
++      if (interrupt &
++          (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
++           TPM_INTF_CMD_READY_INT))
++              wake_up_interruptible(&chip->vendor.int_queue);
++
++      /* Clear interrupts handled with TPM_EOI */
++      iowrite32(interrupt,
++                chip->vendor.iobase +
++                TPM_INT_STATUS(chip->vendor.locality));
++      return IRQ_HANDLED;
++}
++
++static int interrupts = 1;
++module_param(interrupts, bool, 0444);
++MODULE_PARM_DESC(interrupts, "Enable interrupts");
++
++static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
++                                    const struct pnp_device_id *pnp_id)
++{
++      u32 vendor, intfcaps, intmask;
++      int rc, i;
++      unsigned long start, len;
++      struct tpm_chip *chip;
++
++      start = pnp_mem_start(pnp_dev, 0);
++      len = pnp_mem_len(pnp_dev, 0);
++
++      if (!start)
++              start = TIS_MEM_BASE;
++      if (!len)
++              len = TIS_MEM_LEN;
++
++      if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis)))
++              return -ENODEV;
++
++      chip->vendor.iobase = ioremap(start, len);
++      if (!chip->vendor.iobase) {
++              rc = -EIO;
++              goto out_err;
++      }
++
++      vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
++
++      /* Default timeouts */
++      chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
++      chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
++      chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
++      chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
++
++      dev_info(&pnp_dev->dev,
++               "1.2 TPM (device-id 0x%X, rev-id %d)\n",
++               vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
++
++      /* Figure out the capabilities */
++      intfcaps =
++          ioread32(chip->vendor.iobase +
++                   TPM_INTF_CAPS(chip->vendor.locality));
++      dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n",
++              intfcaps);
++      if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
++              dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n");
++      if (intfcaps & TPM_INTF_CMD_READY_INT)
++              dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n");
++      if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
++              dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n");
++      if (intfcaps & TPM_INTF_INT_EDGE_RISING)
++              dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n");
++      if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
++              dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n");
++      if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
++              dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n");
++      if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
++              dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n");
++      if (intfcaps & TPM_INTF_STS_VALID_INT)
++              dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n");
++      if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
++              dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n");
++
++      if (request_locality(chip, 0) != 0) {
++              rc = -ENODEV;
++              goto out_err;
++      }
++
++      /* INTERRUPT Setup */
++      init_waitqueue_head(&chip->vendor.read_queue);
++      init_waitqueue_head(&chip->vendor.int_queue);
++
++      intmask =
++          ioread32(chip->vendor.iobase +
++                   TPM_INT_ENABLE(chip->vendor.locality));
++
++      intmask |= TPM_INTF_CMD_READY_INT
++          | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
++          | TPM_INTF_STS_VALID_INT;
++
++      iowrite32(intmask,
++                chip->vendor.iobase +
++                TPM_INT_ENABLE(chip->vendor.locality));
++      if (interrupts) {
++              chip->vendor.irq =
++                  ioread8(chip->vendor.iobase +
++                          TPM_INT_VECTOR(chip->vendor.locality));
++
++              for (i = 3; i < 16 && chip->vendor.irq == 0; i++) {
++                      iowrite8(i, chip->vendor.iobase +
++                                  TPM_INT_VECTOR(chip->vendor.locality));
++                      if (request_irq
++                          (i, tis_int_probe, SA_SHIRQ,
++                           chip->vendor.miscdev.name, chip) != 0) {
++                              dev_info(chip->dev,
++                                       "Unable to request irq: %d for 
probe\n",
++                                       i);
++                              continue;
++                      }
++
++                      /* Clear all existing */
++                      iowrite32(ioread32
++                                (chip->vendor.iobase +
++                                 TPM_INT_STATUS(chip->vendor.locality)),
++                                chip->vendor.iobase +
++                                TPM_INT_STATUS(chip->vendor.locality));
++
++                      /* Turn on */
++                      iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
++                                chip->vendor.iobase +
++                                TPM_INT_ENABLE(chip->vendor.locality));
++
++                      /* Generate Interrupts */
++                      tpm_gen_interrupt(chip);
++
++                      /* Turn off */
++                      iowrite32(intmask,
++                                chip->vendor.iobase +
++                                TPM_INT_ENABLE(chip->vendor.locality));
++                      free_irq(i, chip);
++              }
++      }
++      if (chip->vendor.irq) {
++              iowrite8(chip->vendor.irq,
++                       chip->vendor.iobase +
++                       TPM_INT_VECTOR(chip->vendor.locality));
++              if (request_irq
++                  (chip->vendor.irq, tis_int_handler, SA_SHIRQ,
++                   chip->vendor.miscdev.name, chip) != 0) {
++                      dev_info(chip->dev,
++                               "Unable to request irq: %d for use\n",
++                               chip->vendor.irq);
++                      chip->vendor.irq = 0;
++              } else {
++                      /* Clear all existing */
++                      iowrite32(ioread32
++                                (chip->vendor.iobase +
++                                 TPM_INT_STATUS(chip->vendor.locality)),
++                                chip->vendor.iobase +
++                                TPM_INT_STATUS(chip->vendor.locality));
++
++                      /* Turn on */
++                      iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
++                                chip->vendor.iobase +
++                                TPM_INT_ENABLE(chip->vendor.locality));
++              }
++      }
++
++      INIT_LIST_HEAD(&chip->vendor.list);
++      spin_lock(&tis_lock);
++      list_add(&chip->vendor.list, &tis_chips);
++      spin_unlock(&tis_lock);
++
++      tpm_get_timeouts(chip);
++      tpm_continue_selftest(chip);
++
++      return 0;
++out_err:
++      if (chip->vendor.iobase)
++              iounmap(chip->vendor.iobase);
++      tpm_remove_hardware(chip->dev);
++      return rc;
++}
++
++static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
++{
++      return tpm_pm_suspend(&dev->dev, msg);
++}
++
++static int tpm_tis_pnp_resume(struct pnp_dev *dev)
++{
++      return tpm_pm_resume(&dev->dev);
++}
++
++static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
++      {"PNP0C31", 0},         /* TPM */
++      {"ATM1200", 0},         /* Atmel */
++      {"IFX0102", 0},         /* Infineon */
++      {"BCM0101", 0},         /* Broadcom */
++      {"NSC1200", 0},         /* National */
++      /* Add new here */
++      {"", 0},                /* User Specified */
++      {"", 0}                 /* Terminator */
++};
++
++static struct pnp_driver tis_pnp_driver = {
++      .name = "tpm_tis",
++      .id_table = tpm_pnp_tbl,
++      .probe = tpm_tis_pnp_init,
++      .suspend = tpm_tis_pnp_suspend,
++      .resume = tpm_tis_pnp_resume,
++};
++
++#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
++module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
++                  sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
++MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
++
++static int __init init_tis(void)
++{
++      return pnp_register_driver(&tis_pnp_driver);
++}
++
++static void __exit cleanup_tis(void)
++{
++      struct tpm_vendor_specific *i, *j;
++      struct tpm_chip *chip;
++      spin_lock(&tis_lock);
++      list_for_each_entry_safe(i, j, &tis_chips, list) {
++              chip = to_tpm_chip(i);
++              iowrite32(~TPM_GLOBAL_INT_ENABLE &
++                        ioread32(chip->vendor.iobase +
++                                 TPM_INT_ENABLE(chip->vendor.
++                                                locality)),
++                        chip->vendor.iobase +
++                        TPM_INT_ENABLE(chip->vendor.locality));
++              release_locality(chip, chip->vendor.locality, 1);
++              if (chip->vendor.irq)
++                      free_irq(chip->vendor.irq, chip);
++              iounmap(i->iobase);
++              list_del(&i->list);
++              tpm_remove_hardware(chip->dev);
++      }
++      spin_unlock(&tis_lock);
++      pnp_unregister_driver(&tis_pnp_driver);
++}
++
++module_init(init_tis);
++module_exit(cleanup_tis);
++MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
++MODULE_DESCRIPTION("TPM Driver");
++MODULE_VERSION("2.0");
++MODULE_LICENSE("GPL");
+

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [TPM] Add an upgrade patch to bring TPM subsystem to 2.6.17-rc4., Xen patchbot-unstable <=