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] [HVM] Add TCG BIOS extensions to the high

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [HVM] Add TCG BIOS extensions to the high memory area along with
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 27 Jan 2007 13:00:26 -0800
Delivery-date: Sat, 27 Jan 2007 13:02:20 -0800
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@xxxxxxxxxxxxxxxxxxxxx
# Date 1169829512 0
# Node ID c07326324f8dea5b60e6a85383a562b4b12d1d9d
# Parent  480436ef6255aa1a38e2cafc9a63f565f633f6fc
[HVM] Add TCG BIOS extensions to the high memory area along with
some often-used libc utility functions. The TCG extensions are
described here:

https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf

I have tried to keep the patching with rombios.c to a minimum, but
some amount of code needs to be inserted at various locations.

The code is currently deactivated, but can be activated by setting
BX_TCGBIOS to '1'.

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>
---
 tools/firmware/rombios/32bit/32bitbios.c           |   16 
 tools/firmware/rombios/32bit/Makefile              |   27 
 tools/firmware/rombios/32bit/tcgbios/Makefile      |   20 
 tools/firmware/rombios/32bit/tcgbios/tcgbios.c     | 1526 +++++++++++++++++++++
 tools/firmware/rombios/32bit/tcgbios/tcgbios.h     |  288 +++
 tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c |  180 ++
 tools/firmware/rombios/32bit/tcgbios/tpm_drivers.h |   18 
 tools/firmware/rombios/32bit/util.c                |  450 ++++++
 tools/firmware/rombios/32bit/util.h                |   28 
 tools/firmware/rombios/32bitgateway.c              |    2 
 tools/firmware/rombios/32bitprotos.h               |   41 
 tools/firmware/rombios/Makefile                    |    2 
 tools/firmware/rombios/rombios.c                   |   58 
 tools/firmware/rombios/tcgbios.c                   |  263 +++
 14 files changed, 2907 insertions(+), 12 deletions(-)

diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/32bitbios.c
--- a/tools/firmware/rombios/32bit/32bitbios.c  Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/32bit/32bitbios.c  Fri Jan 26 16:38:32 2007 +0000
@@ -55,6 +55,22 @@ uint32_t jumptable[IDX_LAST+1] __attribu
        TABLE_ENTRY(IDX_ADD        , add),
        TABLE_ENTRY(IDX_SET_STATIC , set_static),
 
+       TABLE_ENTRY(IDX_TCPA_ACPI_INIT, tcpa_acpi_init),
+       TABLE_ENTRY(IDX_TCPA_EXTEND_ACPI_LOG, tcpa_extend_acpi_log),
+
+       TABLE_ENTRY(IDX_TCGINTERRUPTHANDLER, TCGInterruptHandler),
+
+       TABLE_ENTRY(IDX_TCPA_CALLING_INT19H, tcpa_calling_int19h),
+       TABLE_ENTRY(IDX_TCPA_RETURNED_INT19H, tcpa_returned_int19h),
+       TABLE_ENTRY(IDX_TCPA_ADD_EVENT_SEPARATORS, tcpa_add_event_separators),
+       TABLE_ENTRY(IDX_TCPA_WAKE_EVENT, tcpa_wake_event),
+       TABLE_ENTRY(IDX_TCPA_ADD_BOOTDEVICE, tcpa_add_bootdevice),
+       TABLE_ENTRY(IDX_TCPA_START_OPTION_ROM_SCAN, tcpa_start_option_rom_scan),
+       TABLE_ENTRY(IDX_TCPA_OPTION_ROM, tcpa_option_rom),
+       TABLE_ENTRY(IDX_TCPA_IPL, tcpa_ipl),
+       TABLE_ENTRY(IDX_TCPA_MEASURE_POST, tcpa_measure_post),
+
+       TABLE_ENTRY(IDX_TCPA_INITIALIZE_TPM, tcpa_initialize_tpm),
 
        TABLE_ENTRY(IDX_LAST       , 0)     /* keep last */
 };
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/Makefile
--- a/tools/firmware/rombios/32bit/Makefile     Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/32bit/Makefile     Fri Jan 26 16:38:32 2007 +0000
@@ -4,21 +4,34 @@ CFLAGS :=
 CFLAGS :=
 include $(XEN_ROOT)/tools/Rules.mk
 
+SOURCES = util.c
 TARGET = 32bitbios_flat.h
 
-CFLAGS += -fno-builtin -O2 -msoft-float
+CFLAGS += -fno-builtin -O2 -msoft-float -nostdlib
 CFLAGS += -I../
 
-MODULES = 32bitbios.o
+SUBDIRS = tcgbios
 
-.PHONY: all
+MODULES := 32bitbios.o
+MODULES += tcgbios/tcgbiosext.o
+MODULES += util.o
 
-all : $(TARGET)
+.PHONY: all subdirs
 
-clean ::
+subdirs:
+       @for subdir in $(SUBDIRS); do \
+               $(MAKE) -C $$subdir all; \
+       done;
+
+all: subdirs $(TARGET)
+
+clean::
        rm -rf *.o $(TARGET)
+       @for subdir in $(SUBDIRS); do \
+               $(MAKE) -C $$subdir $@; \
+       done;
 
-$(TARGET) : 32bitbios_all.o $(SOURCES)
+$(TARGET): 32bitbios_all.o $(SOURCES)
        unref=`nm -u 32bitbios_all.o`
        @if [ "$$unref" != "" ]; then \
                echo "There are unresolved symbols in the BIOS.";       \
@@ -27,5 +40,5 @@ clean ::
                bash mkhex highbios_array 32bitbios_all.o > $(TARGET); \
        fi
 
-32bitbios_all.o : 32bitbios.o $(MODULES)
+32bitbios_all.o: $(MODULES)
        ld $(LDFLAGS_DIRECT) -r $(MODULES) -o 32bitbios_all.o
diff -r 480436ef6255 -r c07326324f8d 
tools/firmware/rombios/32bit/tcgbios/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/tcgbios/Makefile     Fri Jan 26 16:38:32 
2007 +0000
@@ -0,0 +1,20 @@
+
+override XEN_TARGET_ARCH = x86_32
+XEN_ROOT = ../../../../..
+CFLAGS :=
+include $(XEN_ROOT)/tools/Rules.mk
+
+TARGET  = tcgbiosext.o
+FILES   = tcgbios tpm_drivers
+OBJECTS = $(foreach f,$(FILES),$(f).o)
+
+CFLAGS += -fno-builtin -O2 -msoft-float -nostdlib
+CFLAGS += -I../ -I../../
+
+all: $(TARGET)
+
+clean::
+       rm -rf *.o $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       ld $(LDFLAGS_DIRECT) -r $^ -o $@
diff -r 480436ef6255 -r c07326324f8d 
tools/firmware/rombios/32bit/tcgbios/tcgbios.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c    Fri Jan 26 16:38:32 
2007 +0000
@@ -0,0 +1,1526 @@
+/*
+ *  Implementation of the TCG BIOS extension according to the specification
+ *  described in
+ *  
https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Author: Stefan Berger <stefanb@xxxxxxxxxx>
+ */
+#include "rombios_compat.h"
+#include "tpm_drivers.h"
+
+#include "tcgbios.h"
+#include "32bitprotos.h"
+#include "util.h"
+
+
+/* local structure and variables */
+struct ptti_cust {
+       uint16_t    ipblength;
+       uint16_t    reserved;
+       uint16_t    opblength;
+       uint16_t    reserved2;
+       uint8_t     tpmoperandin[18];
+} __attribute__((packed));
+
+struct ptti_cust CMD_TPM_Startup_0x01_IPB = {
+    0x8+0xc, 0x00, 4+10, 0x00,
+    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x99, 0x00, 0x01 },
+};
+
+struct ptti_cust CMD_TSC_PhysicalPresence_0x20_IPB = {
+    0x8+0xc, 0x00, 4+10, 0x00,
+    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x20 },
+};
+
+struct ptti_cust CMD_TSC_PhysicalPresence_0x08_IPB = {
+    0x8+0xc, 0x00, 4+10, 0x00,
+    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x08 },
+};
+
+struct ptti_cust CMD_TSC_PhysicalPresence_0x100_IPB = {
+    0x8+0xc, 0x00, 4+10, 0x00,
+    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x01, 0x00 },
+};
+
+struct ptti_cust CMD_TSC_PhysicalPresence_0x10_IPB = {
+    0x8+0xc, 0x00, 4+10, 0x00,
+    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x10 },
+};
+
+struct ptti_cust CMD_TPM_PhysicalEnable_IPB = {
+    0x8+0xa, 0x00, 4+10, 0x00,
+    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x6f },
+};
+
+struct ptti_cust CMD_TPM_PhysicalSetDeactivated_0x00_IPB = {
+    0x8+0xb, 0x00, 4+10, 0x00,
+    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x72, 0x00 }
+};
+struct ptti_cust CMD_TPM_SHA1Start_IPB = {
+    0x8+0xa, 0x00, 4+10, 0x00,
+    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa0 },
+};
+
+struct ptti_cust CMD_TPM_GetCap_Version_IPB = {
+    0x8+0x12, 0x00, 4+18, 0x00,
+    {0x00, 0xc1, 0x00, 0x00, 0x00, 0x12,
+     0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00 },
+};
+
+struct ptti_cust *TCG_CommandList[] = {
+       &CMD_TPM_Startup_0x01_IPB,
+       &CMD_TSC_PhysicalPresence_0x20_IPB,
+       &CMD_TSC_PhysicalPresence_0x08_IPB,
+       &CMD_TSC_PhysicalPresence_0x100_IPB,
+       &CMD_TSC_PhysicalPresence_0x10_IPB,
+       &CMD_TPM_PhysicalEnable_IPB,
+       &CMD_TPM_PhysicalSetDeactivated_0x00_IPB,
+       &CMD_TPM_SHA1Start_IPB,
+};
+
+/* local function prototypes */
+static void sha1(const unsigned char *data, uint32_t length, unsigned char 
*hash);
+static uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx);
+static uint32_t HashAll32(struct hai *hai, unsigned char *hash,
+                          uint32_t magic, uint32_t ecx, uint32_t edx);
+static uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
+                                     struct hleeo *hleeo,
+                                     uint32_t magic, uint32_t ecx, uint32_t 
edx);
+static uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
+                               uint32_t ebx, uint32_t ecx, uint32_t edx);
+static uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto,
+                                   uint32_t magic, uint32_t ecx, uint32_t edx);
+static uint32_t MA_Transmit(unsigned char *cmdbuffer,
+                            unsigned char *respbuffer,
+                            uint32_t respbufferlen);
+
+static unsigned char *tcpa_get_lasa_last_ptr(void);
+static unsigned char *tcpa_get_lasa_base_ptr(void);
+static void tcpa_reset_acpi_log(void);
+static uint32_t tcpa_get_laml(void);
+
+
+extern struct tpm_driver tpm_drivers[];
+
+/* utility functions */
+
+static inline uint32_t bswap(uint32_t a)
+{
+       return ( ( a >> 24 ) & 0x000000ff) |
+              ( ( a >> 8  ) & 0x0000ff00) |
+              ( ( a << 8  ) & 0x00ff0000) |
+              ( ( a << 24 ) & 0xff000000);
+}
+
+/********************************************************
+  Extensions for TCG-enabled BIOS
+ *******************************************************/
+
+typedef struct {
+       struct acpi_20_tcpa *tcpa_ptr;
+       unsigned char       *lasa_last_ptr;
+       uint16_t            entry_count;
+       uint16_t            flags;
+} tcpa_acpi_t;
+
+static tcpa_acpi_t tcpa_acpi;
+
+
+/* low level driver implementation */
+static int tpm_driver_to_use = TPM_INVALID_DRIVER;
+
+static
+uint32_t MA_IsTPMPresent()
+{
+       uint32_t rc = 0;
+       unsigned int i;
+       for (i = 0; i < TPM_NUM_DRIVERS; i++) {
+               struct tpm_driver *td = &tpm_drivers[i];
+               if (td->probe(td->baseaddr) != 0) {
+                       tpm_driver_to_use = i;
+                       rc = 1;
+                       break;
+               }
+       }
+       return rc;
+}
+
+static
+uint32_t MA_InitTPM(uint16_t startupcode)
+{
+       uint32_t rc = 0;
+       /* low-level initialize the TPM */
+       unsigned char command[sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin)];
+       unsigned char response[10];
+       uint32_t response_size = sizeof(response);
+
+       memcpy(command,
+              CMD_TPM_Startup_0x01_IPB.tpmoperandin,
+              sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin));
+       command[10] = (startupcode >> 8) & 0xff;
+       command[11] = (startupcode >> 0) & 0xff;
+       rc = MA_Transmit(command, response, response_size);
+
+       return rc;
+}
+
+static
+uint32_t MA_Transmit(unsigned char *cmdbuffer,
+                     unsigned char *respbuffer,
+                     uint32_t respbufferlen)
+{
+       uint32_t rc = 0;
+       uint32_t irc;
+       struct tpm_driver *td;
+
+       if (tpm_driver_to_use == TPM_INVALID_DRIVER)
+               return TCG_FATAL_COM_ERROR;
+
+       td = &tpm_drivers[tpm_driver_to_use];
+
+       if (rc == 0) {
+               irc = td->activate(td->baseaddr);
+               if (irc == 0) {
+                       /* tpm could not be activated */
+                       rc = TCG_FATAL_COM_ERROR;
+               }
+       }
+
+       if (rc == 0) {
+               uint32_t *tmp = (uint32_t *)&cmdbuffer[2];
+               uint32_t len = bswap(*tmp);
+               irc = td->senddata(td->baseaddr,
+                                  cmdbuffer,
+                                  len);
+               if (irc != 0) {
+                       rc = TCG_FATAL_COM_ERROR;
+               }
+       }
+
+       if (rc == 0) {
+               irc = td->waitdatavalid(td->baseaddr);
+               if (irc != 0) {
+                       rc = TCG_FATAL_COM_ERROR;
+               }
+       }
+
+       if (rc == 0) {
+               irc = td->waitrespready(td->baseaddr, 2000);
+               if (irc != 0) {
+                       rc = TCG_FATAL_COM_ERROR;
+               }
+       }
+
+       if (rc == 0) {
+               irc = td->readresp(td->baseaddr,
+                                  respbuffer,
+                                  respbufferlen);
+               if (irc != 0) {
+                       rc = TCG_FATAL_COM_ERROR;
+               }
+       }
+
+       if (rc == 0) {
+               irc = td->ready(td->baseaddr);
+       }
+
+       return rc;
+}
+
+
+static
+uint8_t acpi_validate_entry(struct acpi_header *hdr)
+{
+       uint8_t sum = 0;
+       unsigned int length = hdr->length;
+       unsigned int ctr;
+       unsigned char *addr = (unsigned char *)hdr;
+
+       for (ctr = 0; ctr < length; ctr++)
+               sum += addr[ctr];
+
+       return sum;
+}
+
+
+void tcpa_acpi_init(void)
+{
+       struct acpi_20_rsdt *rsdt;
+       uint32_t length;
+       struct acpi_20_tcpa *tcpa;
+       uint16_t found = 0;
+       uint16_t rsdp_off;
+       uint16_t off;
+       struct acpi_20_rsdp *rsdp;
+
+       if (MA_IsTPMPresent() == 0) {
+               return;
+       }
+
+       /* scan memory in steps of  16 bytes in the ACPI_SEGMENT segment */
+       found = 0;
+       for (rsdp_off = 0; rsdp_off < 0xfff0; rsdp_off += 0x10) {
+               char *_rsdp = (char *)(ACPI_SEGMENT << 4);
+               /* check for expected string */
+               if (!strncmp( &_rsdp[rsdp_off], "RSD PTR ", 8)) {
+                       found = 1;
+                       rsdp = (struct acpi_20_rsdp *)&_rsdp[rsdp_off];
+                       break;
+               }
+       }
+
+       if (rsdp) {
+               uint32_t ctr = 0;
+               /* get RSDT from RSDP */
+               rsdt   = (struct acpi_20_rsdt *)rsdp->rsdt_address;
+               /* rsdt may be anywhere in 32bit space */
+               length = rsdt->header.length;
+               off = 36;
+               while ((off + 3) < length) {
+                       /* try all pointers to structures */
+                       tcpa = (struct acpi_20_tcpa *)rsdt->entry[ctr];
+                       /* valid TCPA ACPI table ? */
+                       if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature &&
+                           acpi_validate_entry(&tcpa->header) == 0) {
+                               found = 1;
+                               break;
+                       }
+                       off += 4;
+                       ctr++;
+               }
+       }
+
+       if (found == 0) {
+               printf("TCPA ACPI was NOT found!\n");
+               tcpa = 0;
+       }
+
+       /* initialize the TCPA part of the EBDA with our data */
+       tcpa_acpi.tcpa_ptr = tcpa;
+       tcpa_acpi.lasa_last_ptr = 0;
+       tcpa_acpi.entry_count = 0;
+       tcpa_acpi.flags = 0;
+       tcpa_reset_acpi_log();
+}
+
+/* clear the ACPI log */
+static void tcpa_reset_acpi_log(void)
+{
+       unsigned char *lasa = tcpa_get_lasa_base_ptr();
+       if (lasa)
+               memset(lasa, 0x0, tcpa_get_laml());
+}
+
+
+uint32_t tcpa_extend_acpi_log(uint32_t entry_ptr)
+{
+       uint32_t res = 0;
+       unsigned char *lasa_last = tcpa_get_lasa_last_ptr();
+       unsigned char *lasa_base = tcpa_get_lasa_base_ptr();
+       uint32_t size;
+       uint16_t entry_count = tcpa_acpi.entry_count;
+       struct pcpes *pcpes = (struct pcpes *)entry_ptr;
+
+       if (lasa_last == 0) {
+               lasa_last = lasa_base;
+       } else {
+               struct pcpes *pcpes = (struct pcpes *)lasa_last;
+               /* skip the last entry in the log */
+               size = pcpes->eventdatasize;
+               size += 32;
+               lasa_last += size;
+       }
+
+       if (lasa_last == 0) {
+               res = ((uint32_t)TCG_PC_LOGOVERFLOW << 16);
+       }
+
+       if (res == 0) {
+               uint32_t laml = tcpa_get_laml();
+               size = pcpes->eventdatasize;
+               size += 32;
+               if ((lasa_last + size - lasa_base) > laml) {
+                       res = (TCG_PC_LOGOVERFLOW << 16);
+               }
+       }
+
+       if (res == 0) {
+               /* copy the log entry into the ACPI log */
+               memcpy((char *)lasa_last, (char *)entry_ptr, size);
+               /*
+                * update the pointers and entry counter that were modified
+                * due to the new entry in the log
+                */
+               tcpa_acpi.lasa_last_ptr = lasa_last;
+               entry_count++;
+               tcpa_acpi.entry_count = entry_count;
+
+               res = entry_count;
+       }
+       return res;
+}
+
+static
+unsigned char *tcpa_get_lasa_last_ptr(void)
+{
+       return tcpa_acpi.lasa_last_ptr;
+}
+
+static
+unsigned char *tcpa_get_lasa_base_ptr(void)
+{
+       unsigned char *lasa = 0;
+       struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
+       if (tcpa != 0) {
+               uint32_t class = tcpa->platform_class;
+               if (class == TCPA_ACPI_CLASS_CLIENT) {
+                       /* client type */
+                       lasa = (unsigned char *)(long)tcpa->u.client.lasa;
+               } else if (class == TCPA_ACPI_CLASS_SERVER) {
+                       /* server type */
+                       lasa = (unsigned char *)(long)tcpa->u.server.lasa;
+               }
+       }
+       return lasa;
+}
+
+static
+uint32_t tcpa_get_laml(void)
+{
+       uint32_t laml = 0;
+       struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
+       if (tcpa != 0) {
+               uint32_t class = tcpa->platform_class;
+               if (class == TCPA_ACPI_CLASS_CLIENT) {
+                       /* client type */
+                       laml = tcpa->u.client.laml;
+               } else if (class == TCPA_ACPI_CLASS_SERVER) {
+                       laml = tcpa->u.server.laml;
+               }
+       }
+       return laml;
+}
+
+
+
+/*
+ * Add a measurement to the log; the data at data_seg:data/length are
+ * appended to the TCG_PCClientPCREventStruct
+ *
+ * Input parameters:
+ *  pcrIndex   : which PCR to extend
+ *  event_type : type of event; specs 10.4.1
+ *  event_id   : (unused)
+ *  data       : pointer to the data (i.e., string) to be added to the log
+ *  length     : length of the data
+ */
+static uint16_t
+tcpa_add_measurement_to_log(uint32_t pcrIndex,
+                            uint32_t event_type,
+                            uint32_t event_id,
+                            const char *data_ptr,
+                            uint32_t length)
+{
+       uint32_t rc = 0;
+       struct hleei_short hleei;
+       struct hleeo hleeo;
+       uint8_t _pcpes[32+400];
+       struct pcpes *pcpes = (struct pcpes *)_pcpes;
+       uint8_t *data = (uint8_t *)data_ptr;
+
+       if (length < sizeof(_pcpes)-32) {
+               memset(pcpes, 0x0, 32);
+               pcpes->pcrindex   = pcrIndex;
+               pcpes->eventtype = event_type;
+               pcpes->eventdatasize = length;
+               memcpy(&_pcpes[32], data, length);
+
+               hleei.ipblength = 0x18;
+               hleei.reserved  = 0x0;
+               hleei.hashdataptr = (uint32_t)&_pcpes[32];
+               hleei.hashdatalen = length;
+               hleei.pcrindex    = pcrIndex;
+               hleei.logdataptr  = (uint32_t)_pcpes;
+               hleei.logdatalen  = length + 32;
+               rc = HashLogExtendEvent32(&hleei,
+                                         &hleeo,
+                                         TCG_MAGIC,
+                                         0x0,
+                                         0x0);
+       } else {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_GENERAL_ERROR << 16));
+       }
+
+       return rc;
+}
+
+static
+uint16_t tcpa_add_pcpes_to_log(struct pcpes *pcpes)
+{
+       uint32_t rc = 0;
+       struct hleei_short hleei;
+       struct hleeo hleeo;
+
+       hleei.ipblength = 0x18;
+       hleei.reserved  = 0x0;
+       hleei.hashdataptr = 0;
+       hleei.hashdatalen = 0;
+       hleei.pcrindex    = pcpes->pcrindex;
+       hleei.logdataptr  = (uint32_t)pcpes;
+       hleei.logdatalen  = sizeof(pcpes);
+
+       rc = HashLogExtendEvent32(&hleei,
+                                 &hleeo,
+                                 TCG_MAGIC,
+                                 0x0,
+                                 0x0);
+
+       return rc;
+}
+
+
+/*
+ * Add a measurement to the log; further description of the data
+ * that are to be hashed are NOT appended to the TCG_PCClientPCREventStruc.
+ * Input parameters:
+ *  pcrIndex   : PCR to extend
+ *  event_type : type of event; specs 10.4.1
+ *  ptr        : 32 bit pointer to the data to be hashed
+ *  length     : length of the data to be hashed
+ *
+ * Returns lower 16 bit of return code of TCG_HashLogExtendEvent. '0' means
+ * success, otherwise an error is indicated.
+ */
+static
+uint16_t tcpa_add_measurement_to_log_simple(uint32_t pcrIndex,
+                                            uint16_t event_type,
+                                            uint8_t *ptr, uint32_t length)
+{
+       uint32_t rc = 0;
+       struct hleei_short hleei;
+       struct hleeo hleeo;
+       struct pcpes pcpes;
+
+       memset(&pcpes, 0x0, sizeof(pcpes));
+       pcpes.pcrindex = pcrIndex;
+       pcpes.eventtype = event_type;
+       pcpes.eventdatasize = length;
+
+       hleei.ipblength = 0x18;
+       hleei.reserved  = 0x0;
+       hleei.hashdataptr = (uint32_t)ptr;
+       hleei.hashdatalen = length;
+       hleei.pcrindex = pcrIndex;
+       hleei.logdataptr = (uint32_t)&pcpes;
+       hleei.logdatalen = 32;
+
+       rc = HashLogExtendEvent32(&hleei,
+                                 &hleeo,
+                                 TCG_MAGIC,
+                                 0x0,
+                                 0x0);
+       return rc;
+}
+
+/* table of event types according to 10.4.1 / table 11 */
+static const char ev_action[][23] = {
+  /*  0 */ "Calling INT 19h",
+           "Returned INT 19h",
+           "Returned via INT 18h",
+           "",
+           "",
+  /*  5 */ "",
+           "",
+           "",
+           "",
+           "",
+  /* 10 */ "",
+           "",
+           "",
+           "",
+           "Start Option ROM Scan"
+};
+
+
+static char evt_separator[] = "---------------";
+static char wake_event_1[]    = "Wake Event 1";
+
+
+/*
+ * Add a measurement to the list of measurements
+ * pcrIndex   : PCR to be extended
+ * event_type : type of event; specs 10.4.1
+ * data       : additional parameter; used as parameter for 10.4.3
+ *              'action index'
+ */
+void tcpa_add_measurement(uint32_t pcrIndex,
+                          uint16_t event_type,
+                          uint32_t data)
+{
+       const char *string;
+
+       switch (event_type) {
+       case EV_SEPARATOR:
+               tcpa_add_measurement_to_log(pcrIndex,
+                                           event_type,
+                                           0,
+                                           evt_separator,
+                                           strlen(evt_separator));
+       break;
+       case EV_ACTION:
+               string = ev_action[data /* event_id */];
+               tcpa_add_measurement_to_log(pcrIndex,
+                                           event_type,
+                                           data,
+                                           string,
+                                           strlen(string));
+
+       break;
+       }
+}
+
+
+/*
+ * Add measurement to log about call of int 19h
+ */
+void tcpa_calling_int19h()
+{
+       tcpa_add_measurement(4, EV_ACTION, 0);
+}
+
+/*
+ * Add measurement to log about retuning from int 19h
+ */
+void tcpa_returned_int19h()
+{
+       tcpa_add_measurement(4, EV_ACTION, 1);
+}
+
+/*
+ * Add event separators for PCRs 0 to 7; specs 8.2.3
+ */
+void tcpa_add_event_separators()
+{
+       uint32_t pcrIndex = 0;
+       while (pcrIndex <= 7) {
+               tcpa_add_measurement(pcrIndex, EV_SEPARATOR, 0);
+               pcrIndex ++;
+       }
+}
+
+
+/*
+ * Add a wake event to the log
+ */
+void tcpa_wake_event()
+{
+       tcpa_add_measurement_to_log(6,
+                                   EV_ACTION,
+                                   10,
+                                   wake_event_1,
+                                   strlen(wake_event_1));
+}
+
+/*
+ * add the boot device to the measurement log
+ */
+void tcpa_add_bootdevice(uint32_t bootcd, uint32_t bootdrv)
+{
+       char *string;
+       if (bootcd == 0) {
+               if (bootdrv == 0) {
+                       string = "Booting BCV device 00h (Floppy)";
+               } else if (bootdrv == 0x80) {
+                       string = "Booting BCV device 80h (HDD)";
+               } else {
+                       string = "Booting unknown device";
+               }
+       } else {
+               string = "Booting from CD ROM device";
+       }
+       tcpa_add_measurement_to_log(4, 5, 0,
+                                   string, strlen(string));
+}
+
+/*
+ * Add measurement to the log about option rom scan
+ * 10.4.3 : action 14
+ */
+void tcpa_start_option_rom_scan()
+{
+       tcpa_add_measurement(2, EV_ACTION, 14);
+}
+
+
+/*
+ * Add measurement to the log about an option rom
+ */
+void tcpa_option_rom(uint32_t seg)
+{
+       uint32_t len = read_byte(seg, 2) << 9;
+       uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
+       char append[32]; /* TCG_PCClientTaggedEventStruct and
+                            OptionROMExecuteStructure; specs 10.4.2.1 */
+       struct hai hai;   /* HashAll Input Block; specs 12.10 */
+
+       memset(append, 0x0, sizeof(append));
+
+       append[0] = 7; /* Option ROM Execute */
+       append[4] = 24;/* size of OptionROMExecute Structure */
+       /* leave the rest to '0' */
+
+       /* 12.10 table 21 */
+       hai.ipblength   = 0x10;
+       hai.reserved    = 0;
+       hai.hashdataptr = (uint32_t)addr;
+       hai.hashdatalen = len;
+       hai.algorithmid = TPM_ALG_SHA;
+
+       HashAll32(&hai,
+                 (unsigned char *)append+12,
+                 TCG_MAGIC,
+                 0,
+                 0);
+
+       tcpa_add_measurement_to_log(2,
+                                   EV_EVENT_TAG,
+                                   0,
+                                   append,
+                                   32);
+}
+
+/*
+ * Add a measurement to the log in support of 8.2.5.3
+ * Creates two log entries
+ *
+ * Input parameter:
+ *  seg    : segment where the IPL data are located
+ */
+void tcpa_ipl(Bit32u seg)
+{
+       /* specs: 8.2.5.3 */
+       uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
+       /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */
+       tcpa_add_measurement_to_log_simple(4,
+                                          EV_IPL,
+                                          addr,
+                                          0x1b8);
+       /* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */
+       tcpa_add_measurement_to_log_simple(5,
+                                          EV_IPL_PARTITION_DATA,
+                                          addr + 0x1b8,
+                                          0x48);
+}
+
+void tcpa_measure_post(Bit32u from, Bit32u to)
+{
+       struct pcpes pcpes; /* PCClientPCREventStruc */
+       memset(&pcpes, 0x0, sizeof(pcpes));
+       int len = to - from;
+
+       if (len > 0) {
+               sha1((unsigned char *)from,
+                    to-from,
+                    (unsigned char *)&pcpes.digest);
+
+               pcpes.eventtype = EV_POST_CODE;
+               pcpes.eventdatasize = 0;
+               pcpes.pcrindex = 0;
+               tcpa_add_pcpes_to_log(&pcpes);
+       }
+}
+
+static
+uint32_t SendCommand32(uint32_t idx,
+                     struct pttto *pttto,
+                     uint32_t size_ptto)
+{
+       uint32_t rc = 0;
+       struct pttti *pttti = (struct pttti *)TCG_CommandList[idx];
+       uint8_t _pttto[30];
+
+       if (size_ptto > 0 && size_ptto < 14) {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
+       }
+
+       if (rc == 0) {
+               if (size_ptto == 0) {
+                       pttto = (struct pttto *)_pttto;
+                       size_ptto = sizeof(_pttto);
+               }
+               pttti->opblength = size_ptto;
+       }
+
+       if (rc == 0) {
+               if (pttti->opblength > size_ptto) {
+                       rc = (TCG_PC_TPMERROR |
+                             ((uint32_t)TCG_OUTPUT_BUFFER_TOO_SHORT << 16));
+               }
+       }
+
+       if (rc == 0) {
+               rc = PassThroughToTPM32(pttti,
+                                       pttto,
+                                       TCG_MAGIC,
+                                       0x0,
+                                       0x0);
+       }
+
+       return rc;
+}
+
+
+uint32_t tcpa_initialize_tpm(uint32_t physpres)
+{
+       uint32_t rc = 0;
+       uint8_t _pttto[40];
+       struct pttto *pttto = (struct pttto *)_pttto;
+       uint32_t pttto_size = sizeof(_pttto);
+
+       if (rc == 0) {
+               rc = SendCommand32(IDX_CMD_TPM_Startup_0x01, pttto, pttto_size);
+       }
+
+       if (rc == 0 && physpres != 0) {
+               rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x20,
+                                  pttto, pttto_size);
+       }
+
+       if (rc == 0 && physpres != 0) {
+               rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x08,
+                                  pttto, pttto_size);
+       }
+
+       if (rc == 0 && physpres != 0) {
+               rc = SendCommand32(IDX_CMD_TPM_PhysicalEnable,
+                                  pttto, pttto_size);
+       }
+
+       if (rc == 0 && physpres != 0) {
+               rc = SendCommand32(IDX_CMD_TPM_PhysicalSetDeactivated_0x00,
+                                  pttto, pttto_size);
+       }
+
+       if (rc == 0) {
+               rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x100,
+                                  pttto, pttto_size);
+       }
+
+       if (rc == 0) {
+               rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x10,
+                                  pttto, pttto_size);
+       }
+       return rc;
+}
+
+
+uint16_t TCG_IsShutdownPreBootInterface(void)
+{
+       return tcpa_acpi.flags & STATUS_FLAG_SHUTDOWN;
+}
+
+
+static
+uint32_t _TCG_TPM_Extend(unsigned char *hash, uint32_t pcrindex)
+{
+       uint32_t rc;
+       uint8_t _pttti[8+34];
+       uint8_t _pttto[4+30];
+       struct pttti *pttti = (struct pttti*)&_pttti;
+       struct pttto *pttto = (struct pttto*)&_pttto;
+
+       pttti->ipblength = 8 + 34;
+       pttti->reserved  = 0;
+       pttti->opblength = 4 + 30;
+       pttti->reserved2 = 0;
+
+       _pttti[8 + 0] = 0x0;
+       _pttti[8 + 1] = 0xc1;
+       *(uint32_t *)&_pttti[8 + 2] = bswap(34);
+       *(uint32_t *)&_pttti[8 + 6] = bswap(0x14);
+       *(uint32_t *)&_pttti[8 + 10]= bswap(pcrindex);
+       memcpy(&_pttti[8+14], hash, 20);
+
+       rc = PassThroughToTPM32(pttti,
+                               pttto,
+                               TCG_MAGIC,
+                               0x0,
+                               0x0);
+       /* sanity check of result */
+       if (_pttto[4] != 0x00 || _pttto[5] != 0xc4) {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_FATAL_COM_ERROR << 16));
+       }
+
+       if (rc != 0) {
+               /*
+                  Invalidate the log since system did not process this
+                  extend properly.
+                */
+               tcpa_reset_acpi_log();
+               memset(&tcpa_acpi, 0x0, sizeof(tcpa_acpi));
+               TCG_ShutdownPreBootInterface(0);
+       }
+       return rc;
+}
+
+
+static
+uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
+                            struct hleeo *hleeo,
+                            uint32_t magic,
+                            uint32_t ecx,
+                            uint32_t edx)
+{
+       uint32_t rc = 0;
+       uint16_t size;
+       struct hlei hlei ; /* HashLogEventInput block */
+       struct hleo hleo;  /* HashLogEventOutput block */
+       struct hleei_long *hleei_l = (struct hleei_long *)hleei_s;
+       int sh;
+       uint32_t logdataptr;
+
+       if (TCG_IsShutdownPreBootInterface() != 0) {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+       }
+
+       if (rc == 0) {
+               /* short or long version? */
+               size = hleei_s->ipblength;
+               if (size == 0x18) {
+                       /* short */
+                       sh = 1;
+               } else if (size == 0x1c) {
+                       /* long */
+                       sh = 0;
+               } else {
+                       /* bad input block */
+                       rc = TCG_PC_TPMERROR |
+                            ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
+               }
+       }
+
+       if (rc == 0) {
+               uint32_t hashdataptr;
+               uint32_t hashdatalen;
+               uint32_t pcrindex;
+               uint32_t logeventtype;
+               uint32_t logdatalen;
+               uint32_t eventnumber;
+               uint8_t hash[20];
+               struct pcpes *pcpes;
+
+               hashdataptr = hleei_s->hashdataptr;
+               hashdatalen = hleei_s->hashdatalen;
+               pcrindex    = hleei_s->pcrindex;
+               if (sh) {
+                       logdataptr = hleei_s->logdataptr;
+                       logdatalen = hleei_s->logdatalen;
+               } else {
+                       logdataptr = hleei_l->logdataptr;
+                       logdatalen = hleei_l->logdatalen;
+               }
+
+               pcpes = (struct pcpes *)logdataptr;
+               logeventtype = pcpes->eventtype;
+
+               /* fill out HashLogEventInput block 'hlie' */
+               hlei.ipblength = 0x1c;
+               hlei.reserved = 0;
+               hlei.hashdataptr = hashdataptr;
+               hlei.hashdatalen = hashdatalen;
+               hlei.pcrindex    = pcrindex;
+               hlei.logeventtype= logeventtype;
+               hlei.logdataptr  = logdataptr;
+               hlei.logdatalen  = logdatalen;
+
+               rc = HashLogEvent32(&hlei,
+                                   &hleo,
+                                   TCG_MAGIC,
+                                   0x0,
+                                   0x0);
+               eventnumber = hleo.eventnumber;
+
+               hleeo->opblength = 8 + 20;
+               hleeo->reserved  = 0;
+               hleeo->eventnumber = eventnumber;
+
+               memcpy(hash, (unsigned char *)logdataptr + 0x8, 20);
+               _TCG_TPM_Extend(hash, pcrindex);
+       }
+
+       if (rc != 0) {
+               hleeo->opblength = 4;
+               hleeo->reserved  = 0;
+       }
+       return rc;
+
+}
+
+
+static
+uint32_t PassThroughToTPM32(struct pttti *pttti,
+                          struct pttto *pttto,
+                          uint32_t magic,
+                          uint32_t ecx,
+                          uint32_t edx)
+{
+       uint32_t rc = 0;
+       uint8_t *cmd32;
+       uint32_t resbuflen;
+
+       if (TCG_IsShutdownPreBootInterface() != 0) {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+       }
+
+       if (rc == 0) {
+               if (pttti->ipblength < 0x8 + 10) {
+                       rc = TCG_PC_TPMERROR |
+                            ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
+               }
+       }
+
+       if (rc == 0) {
+               if (pttti->opblength < 0x4) {
+                       rc = TCG_PC_TPMERROR |
+                            ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
+               }
+       }
+
+       if (rc == 0) {
+               uint8_t *resbuf32;
+
+               cmd32 = &pttti->tpmoperandin[0];
+               resbuflen = pttti->opblength - 4;
+               resbuf32  = &pttto->tpmoperandout[0];
+
+               rc = MA_Transmit(cmd32, resbuf32, resbuflen);
+       }
+
+       if (rc == 0) {
+               pttto->opblength = resbuflen+4;
+               pttto->reserved  = 0;
+       }
+
+       if (rc != 0) {
+               pttto->opblength = 0;
+               pttto->reserved = 0;
+       }
+
+       return rc;
+}
+
+
+static
+uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx)
+{
+       uint32_t rc = 0;
+       if (TCG_IsShutdownPreBootInterface() == 0) {
+               tcpa_acpi.flags |= STATUS_FLAG_SHUTDOWN;
+       } else {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+       }
+       return rc;
+}
+
+
+static
+uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
+                      uint32_t ebx,
+                      uint32_t ecx,
+                      uint32_t edx)
+{
+       uint32_t rc = 0;
+       uint16_t size;
+       uint32_t logdataptr;
+       uint32_t logdatalen;
+       uint32_t hashdataptr;
+       uint32_t hashdatalen;
+
+       if (TCG_IsShutdownPreBootInterface() != 0) {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+       }
+
+       if (rc == 0) {
+               size = hlei->ipblength;
+               if (size != 0x1c) {
+                       rc = (TCG_PC_TPMERROR |
+                             ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
+               }
+       }
+
+       if (rc == 0) {
+               struct pcpes *pcpes;
+               logdataptr = hlei->logdataptr;
+               logdatalen = hlei->logdatalen;
+               pcpes = (struct pcpes *)logdataptr;
+               if (pcpes->pcrindex != hlei->pcrindex) {
+                       rc = (TCG_PC_TPMERROR |
+                             ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
+               }
+       }
+
+       if (rc == 0) {
+               struct pcpes *pcpes= (struct pcpes *)logdataptr;
+               if (pcpes->eventtype != hlei->logeventtype) {
+                       rc = (TCG_PC_TPMERROR |
+                             ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
+               }
+       }
+
+       if (rc == 0) {
+               uint32_t entry;
+               hashdataptr = hlei->hashdataptr;
+               hashdatalen = hlei->hashdatalen;
+
+               if ((hashdataptr != 0) | (hashdatalen != 0)) {
+                       uint8_t hash[20];
+                       struct hai hai; /* HashAll Input Block */
+                       hai.ipblength = 0x10;
+                       hai.reserved  = 0x0;
+                       hai.hashdataptr = hashdataptr;
+                       hai.hashdatalen = hashdatalen;
+                       hai.algorithmid = TPM_ALG_SHA;
+                       rc = HashAll32(&hai,
+                                      hash,
+                                      TCG_MAGIC,
+                                      0x0,
+                                      0x0);
+
+                       if (rc == 0) {
+                               /* hashing was done ok */
+                               memcpy((unsigned char *)logdataptr + 8,
+                                      hash,
+                                      20);
+                       }
+               }
+
+               if (rc == 0) {
+                       /* extend the log with this event */
+                       entry = tcpa_extend_acpi_log(logdataptr);
+                       if ((uint16_t)entry == 0) {
+                               /* upper 16 bits hold error code */
+                               rc = (entry >> 16);
+                       }
+               }
+
+               if (rc == 0) {
+                       /* updating the log was fine */
+                       hleo->opblength = 8;
+                       hleo->reserved  = 0;
+                       hleo->eventnumber = entry;
+               }
+       }
+
+       if (rc != 0) {
+               hleo->opblength = 2;
+               hleo->reserved = 0;
+       }
+
+       return rc;
+}
+
+static
+uint32_t HashAll32(struct hai *hai, unsigned char *hash,
+                 uint32_t magic,
+                 uint32_t ecx,
+                 uint32_t edx)
+{
+       uint32_t rc = 0;
+
+       if (TCG_IsShutdownPreBootInterface() != 0) {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+       }
+
+       if (rc == 0) {
+               if (hai->ipblength != 0x10) {
+                       rc = (TCG_PC_TPMERROR |
+                             ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
+               }
+       }
+
+       if (rc == 0) {
+               if (hai->algorithmid != TPM_ALG_SHA) {
+                       rc = (TCG_PC_TPMERROR |
+                            ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
+               }
+       }
+
+       if (rc == 0) {
+               uint8_t *hashdataptr32;
+               uint32_t hashdatalen32;
+
+               hashdataptr32 = (uint8_t *)hai->hashdataptr;
+               hashdatalen32 = hai->hashdatalen;
+
+               sha1(hashdataptr32,
+                    hashdatalen32,
+                    hash);
+       }
+
+       return rc;
+}
+
+
+static
+uint32_t TSS32(struct ti *ti, struct to *to,
+             uint32_t ebx,
+             uint32_t ecx,
+             uint32_t edx)
+{
+       uint32_t rc = 0;
+       if (TCG_IsShutdownPreBootInterface() == 0) {
+               rc = TCG_PC_UNSUPPORTED;
+       } else {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+       }
+
+       if (rc != 0) {
+               to->opblength = 4;
+               to->reserved  = 0;
+       }
+
+       return rc;
+}
+
+static
+uint32_t CompactHashLogExtendEvent32(unsigned char *buffer,
+                                   uint32_t info,
+                                   uint32_t magic,
+                                   uint32_t length,
+                                   uint32_t pcrindex,
+                                   uint32_t *edx_ptr)
+{
+       uint32_t rc = 0;
+       struct hleeo hleeo;
+
+       if (TCG_IsShutdownPreBootInterface() != 0) {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+       }
+
+       if (buffer == 0) {
+               rc = (TCG_PC_TPMERROR |
+                     ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
+       }
+
+       if (rc == 0) {
+               struct hleei_short hleei;
+               struct pcpes pcpes;
+               uint8_t *logdataptr;
+               uint8_t *hashdataptr;
+
+               logdataptr = (uint8_t*)&pcpes;
+               hashdataptr = buffer;
+
+               hleei.ipblength = 0x18;
+               hleei.reserved  = 0x0;
+               hleei.hashdataptr = (uint32_t)hashdataptr;
+               hleei.hashdatalen = length;
+               hleei.pcrindex = pcrindex;
+               hleei.logdataptr = (uint32_t)logdataptr;
+               hleei.logdatalen = 32;
+
+               memset(&pcpes, 0x0, 32);
+               pcpes.pcrindex = pcrindex;
+               pcpes.eventtype = 12; /* EV_COMPACT_HASH */
+               pcpes.eventdatasize = 4;
+               pcpes.event = info;
+
+               rc = HashLogExtendEvent32(&hleei,
+                                         &hleeo,
+                                         TCG_MAGIC,
+                                         0x0,
+                                         0x0);
+       }
+
+       if (rc == 0) {
+               *edx_ptr = hleeo.eventnumber;
+       }
+
+       return rc;
+}
+
+
+
+/*******************************************************************
+  Calculation of SHA1 in SW
+
+  See: RFC3174, Wikipedia's SHA1 alogrithm description
+ ******************************************************************/
+typedef struct _sha1_ctx {
+       uint32_t h[5];
+} sha1_ctx;
+
+
+static inline uint32_t rol(val, rol)
+  uint32_t val;
+  uint16_t rol;
+{
+       return (val << rol) | (val >> (32 - rol));
+}
+
+static const uint32_t sha_ko[4] = { 0x5a827999,
+                                    0x6ed9eba1,
+                                    0x8f1bbcdc,
+                                    0xca62c1d6 };
+
+
+static void sha1_block(uint32_t *w, sha1_ctx *ctx)
+{
+       uint32_t i;
+       uint32_t a,b,c,d,e,f;
+       uint32_t tmp;
+       uint32_t idx;
+
+       /* change endianess of given data */
+       for (i = 0; i < 16; i++) {
+               w[i] = bswap(w[i]);
+       }
+
+       for (i = 16; i <= 79; i++) {
+               tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
+               w[i] = rol(tmp,1);
+       }
+
+       a = ctx->h[0];
+       b = ctx->h[1];
+       c = ctx->h[2];
+       d = ctx->h[3];
+       e = ctx->h[4];
+
+       for (i = 0; i <= 79; i++) {
+               if (i <= 19) {
+                       f = (b & c) | ((b ^ 0xffffffff) & d);
+                       idx = 0;
+               } else if (i <= 39) {
+                       f = b ^ c ^ d;
+                       idx = 1;
+               } else if (i <= 59) {
+                       f = (b & c) | (b & d) | (c & d);
+                       idx = 2;
+               } else {
+                       f = b ^ c ^ d;
+                       idx = 3;
+               }
+
+               tmp = rol(a, 5) +
+                     f +
+                     e +
+                     sha_ko[idx] +
+                     w[i];
+               e = d;
+               d = c;
+               c = rol(b, 30);
+               b = a;
+               a = tmp;
+       }
+
+       ctx->h[0] += a;
+       ctx->h[1] += b;
+       ctx->h[2] += c;
+       ctx->h[3] += d;
+       ctx->h[4] += e;
+}
+
+static
+void sha1_do(sha1_ctx *ctx, const unsigned char *data32, uint32_t length)
+{
+       uint32_t offset;
+       uint16_t num;
+       uint32_t bits = 0;
+       uint32_t w[80];
+       uint32_t tmp;
+
+       /* treat data in 64-byte chunks */
+       for (offset = 0; length - offset >= 64; offset += 64) {
+               /* copy into the 'w' array */
+               memcpy(w, data32 + offset, 64);
+               /* hash the block in the 'w' array */
+               sha1_block((uint32_t *)w, ctx);
+               bits += (64 * 8);
+       }
+
+       /* last block with less than 64 bytes */
+       num = length - offset;
+       bits += (num << 3);
+
+       memset(w, 0x0, 64);
+       memcpy(w, data32 + offset, num);
+       ((uint8_t *)w)[num] = 0x80;
+
+       if (num >= 56) {
+               /* cannot append number of bits here */
+               sha1_block((uint32_t *)w, ctx);
+               memset(w, 0x0, 60);
+       }
+
+       /* write number of bits to end of block */
+       tmp = bswap(bits);
+       memcpy(&w[15], &tmp, 4);
+
+       sha1_block(w, ctx);
+
+       /* need to switch result's endianess */
+       for (num = 0; num < 5; num++)
+               ctx->h[num] = bswap(ctx->h[num]);
+}
+
+/* sha1 initialization constants */
+static const uint32_t sha_const[5] = {
+       0x67452301,
+       0xefcdab89,
+       0x98badcfe,
+       0x10325476,
+       0xc3d2e1f0
+};
+
+static
+void sha1(const unsigned char *data, uint32_t length, unsigned char *hash)
+{
+       sha1_ctx ctx;
+
+       memcpy(&ctx.h[0], sha_const, 20);
+       sha1_do(&ctx, data, length);
+       memcpy(hash, &ctx.h[0], 20);
+}
+
+
+uint32_t TCGInterruptHandler(pushad_regs_t *regs, uint32_t esds, uint32_t 
flags_ptr)
+{
+       uint16_t DS = esds >> 16;
+       uint16_t ES = esds & 0xffff;
+       uint16_t *FLAGS = (uint16_t *)flags_ptr;
+
+       switch(regs->u.r8.al) {
+       case 0x00:
+               if (MA_IsTPMPresent() == 0) {
+                       /* no TPM available */
+                       regs->u.r32.eax = TCG_PC_TPMERROR |
+                            ((uint32_t)(TCG_PC_TPM_NOT_PRESENT) << 16);
+               } else {
+                       regs->u.r32.eax = MA_InitTPM(TPM_ST_CLEAR);
+                       if (regs->u.r32.eax == 0) {
+                               regs->u.r32.ebx = TCG_MAGIC;
+                               regs->u.r8.ch = TCG_VERSION_MAJOR;
+                               regs->u.r8.cl = TCG_VERSION_MINOR;
+                               regs->u.r32.edx = 0x0;
+                               regs->u.r32.esi =
+                                            (Bit32u)tcpa_get_lasa_base_ptr();
+                               regs->u.r32.edi =
+                                            (Bit32u)tcpa_get_lasa_last_ptr();
+                               CLEAR_CF();
+                       }
+               }
+               break;
+
+       case 0x01:
+               regs->u.r32.eax =
+                       HashLogExtendEvent32((struct hleei_short*)
+                                               ADDR_FROM_SEG_OFF(ES,
+                                                     regs->u.r16.di),
+                                           (struct hleeo*)
+                                               ADDR_FROM_SEG_OFF(DS,
+                                                     regs->u.r16.si),
+                                           regs->u.r32.ebx,
+                                           regs->u.r32.ecx,
+                                           regs->u.r32.edx);
+               CLEAR_CF();
+               break;
+       case 0x02:
+               regs->u.r32.eax =
+                       PassThroughToTPM32((struct pttti *)
+                                               ADDR_FROM_SEG_OFF(ES,
+                                                     regs->u.r16.di),
+                                          (struct pttto *)
+                                               ADDR_FROM_SEG_OFF(DS,
+                                                     regs->u.r16.si),
+                                          regs->u.r32.ebx,
+                                          regs->u.r32.ecx,
+                                          regs->u.r32.edx);
+               CLEAR_CF();
+               break;
+       case 0x03:
+               regs->u.r32.eax =
+                       TCG_ShutdownPreBootInterface(regs->u.r32.ebx);
+               CLEAR_CF();
+               break;
+       case 0x04:
+               regs->u.r32.eax =
+                       HashLogEvent32((struct hlei*)
+                                               ADDR_FROM_SEG_OFF(ES,
+                                                     regs->u.r16.di),
+                                      (struct hleo*)
+                                               ADDR_FROM_SEG_OFF(DS,
+                                                     regs->u.r16.si),
+                                          regs->u.r32.ebx,
+                                          regs->u.r32.ecx,
+                                          regs->u.r32.edx);
+               CLEAR_CF();
+               break;
+       case 0x05:
+               regs->u.r32.eax =
+                       HashAll32((struct hai*)
+                                       ADDR_FROM_SEG_OFF(ES,
+                                                         regs->u.r16.di),
+                                (unsigned char *)
+                                       ADDR_FROM_SEG_OFF(DS,
+                                                         regs->u.r16.si),
+                                  regs->u.r32.ebx,
+                                  regs->u.r32.ecx,
+                                  regs->u.r32.edx);
+               CLEAR_CF();
+               break;
+       case 0x06:
+               regs->u.r32.eax =
+                       TSS32((struct ti*)ADDR_FROM_SEG_OFF(ES,
+                                                           regs->u.r16.di),
+                             (struct to*)ADDR_FROM_SEG_OFF(DS,
+                                                           regs->u.r16.si),
+                             regs->u.r32.ebx,
+                             regs->u.r32.ecx,
+                             regs->u.r32.edx);
+               CLEAR_CF();
+               break;
+       case 0x07:
+               regs->u.r32.eax =
+                 CompactHashLogExtendEvent32((unsigned char *)
+                                                 ADDR_FROM_SEG_OFF(ES,
+                                                       regs->u.r16.di),
+                                             regs->u.r32.esi,
+                                             regs->u.r32.ebx,
+                                             regs->u.r32.ecx,
+                                             regs->u.r32.edx,
+                                             &regs->u.r32.edx);
+               CLEAR_CF();
+               break;
+       default:
+               SET_CF();
+       }
+
+       return 0;
+}
diff -r 480436ef6255 -r c07326324f8d 
tools/firmware/rombios/32bit/tcgbios/tcgbios.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.h    Fri Jan 26 16:38:32 
2007 +0000
@@ -0,0 +1,288 @@
+#ifndef TCGBIOS_H
+#define TCGBIOS_H
+
+
+/* TCPA ACPI definitions */
+#define TCPA_ACPI_CLASS_CLIENT          0
+#define TCPA_ACPI_CLASS_SERVER          1
+
+/* Define for section 12.3 */
+#define TCG_PC_OK                       0x0
+#define TCG_PC_TPMERROR                 0x1
+#define TCG_PC_LOGOVERFLOW              0x2
+#define TCG_PC_UNSUPPORTED              0x3
+
+#define TPM_ALG_SHA                     0x4
+
+#define TCG_MAGIC                       0x41504354L
+#define TCG_VERSION_MAJOR               1
+#define TCG_VERSION_MINOR               2
+
+#define TPM_OK                          0x0
+#define TPM_RET_BASE                    0x1
+#define TCG_GENERAL_ERROR               (TPM_RET_BASE + 0x0)
+#define TCG_TPM_IS_LOCKED               (TPM_RET_BASE + 0x1)
+#define TCG_NO_RESPONSE                 (TPM_RET_BASE + 0x2)
+#define TCG_INVALID_RESPONSE            (TPM_RET_BASE + 0x3)
+#define TCG_INVALID_ACCESS_REQUEST      (TPM_RET_BASE + 0x4)
+#define TCG_FIRMWARE_ERROR              (TPM_RET_BASE + 0x5)
+#define TCG_INTEGRITY_CHECK_FAILED      (TPM_RET_BASE + 0x6)
+#define TCG_INVALID_DEVICE_ID           (TPM_RET_BASE + 0x7)
+#define TCG_INVALID_VENDOR_ID           (TPM_RET_BASE + 0x8)
+#define TCG_UNABLE_TO_OPEN              (TPM_RET_BASE + 0x9)
+#define TCG_UNABLE_TO_CLOSE             (TPM_RET_BASE + 0xa)
+#define TCG_RESPONSE_TIMEOUT            (TPM_RET_BASE + 0xb)
+#define TCG_INVALID_COM_REQUEST         (TPM_RET_BASE + 0xc)
+#define TCG_INVALID_ADR_REQUEST         (TPM_RET_BASE + 0xd)
+#define TCG_WRITE_BYTE_ERROR            (TPM_RET_BASE + 0xe)
+#define TCG_READ_BYTE_ERROR             (TPM_RET_BASE + 0xf)
+#define TCG_BLOCK_WRITE_TIMEOUT         (TPM_RET_BASE + 0x10)
+#define TCG_CHAR_WRITE_TIMEOUT          (TPM_RET_BASE + 0x11)
+#define TCG_CHAR_READ_TIMEOUT           (TPM_RET_BASE + 0x12)
+#define TCG_BLOCK_READ_TIMEOUT          (TPM_RET_BASE + 0x13)
+#define TCG_TRANSFER_ABORT              (TPM_RET_BASE + 0x14)
+#define TCG_INVALID_DRV_FUNCTION        (TPM_RET_BASE + 0x15)
+#define TCG_OUTPUT_BUFFER_TOO_SHORT     (TPM_RET_BASE + 0x16)
+#define TCG_FATAL_COM_ERROR             (TPM_RET_BASE + 0x17)
+#define TCG_INVALID_INPUT_PARA          (TPM_RET_BASE + 0x18)
+#define TCG_TCG_COMMAND_ERROR           (TPM_RET_BASE + 0x19)
+#define TCG_INTERFACE_SHUTDOWN          (TPM_RET_BASE + 0x20)
+//define TCG_PC_UNSUPPORTED             (TPM_RET_BASE + 0x21)
+#define TCG_PC_TPM_NOT_PRESENT          (TPM_RET_BASE + 0x22)
+#define TCG_PC_TPM_DEACTIVATED          (TPM_RET_BASE + 0x23)
+
+
+#define TPM_INVALID_ADR_REQUEST          TCG_INVALID_ADR_REQUEST
+#define TPM_IS_LOCKED                    TCG_TPM_IS_LOCKED
+#define TPM_INVALID_DEVICE_ID            TCG_INVALID_DEVICE_ID
+#define TPM_INVALID_VENDOR_ID            TCG_INVALID_VENDOR_ID
+//define TPM_RESERVED_REG_INVALID
+#define TPM_FIRMWARE_ERROR               TCG_FIRMWARE_ERROR
+#define TPM_UNABLE_TO_OPEN               TCG_UNABLE_TO_OPEN
+#define TPM_UNABLE_TO_CLOSE              TCG_UNABLE_TO_CLOSE
+#define TPM_INVALID_RESPONSE             TCG_INVALID_RESPONSE
+#define TPM_RESPONSE_TIMEOUT             TCG_RESPONSE_TIMEOUT
+#define TPM_INVALID_ACCESS_REQUEST       TCG_INVALID_ACCESS_REQUEST
+#define TPM_TRANSFER_ABORT               TCG_TRANSFER_ABORT
+#define TPM_GENERAL_ERROR                TCG_GENERAL_ERROR
+
+#define TPM_ST_CLEAR                      0x0
+#define TPM_ST_STATE                      0x1
+#define TPM_ST_DEACTIVATED                0x2
+
+/* event types: 10.4.1 / table 11 */
+#define EV_POST_CODE             1
+#define EV_SEPARATOR             4
+#define EV_ACTION                5
+#define EV_EVENT_TAG             6
+#define EV_COMPACT_HASH         12
+#define EV_IPL                  13
+#define EV_IPL_PARTITION_DATA   14
+
+
+// MA Driver defines
+#define CODE_MAInitTPM                    0x01
+#define CODE_MAHashAllExtendTPM           0x02
+#define CODE_MAPhysicalPresenceTPM        0x03
+/* vendor specific ones */
+#define CODE_MAIsTPMPresent               0x80
+#define CODE_MAHashAll                    0x81
+#define CODE_MATransmit                   0x82
+
+/*
+  indices for commands to be sent via proprietary
+   _TCG_SendCommand function
+ */
+#define IDX_CMD_TPM_Startup_0x01                0
+#define IDX_CMD_TSC_PhysicalPresence_0x20       1
+#define IDX_CMD_TSC_PhysicalPresence_0x08       2
+#define IDX_CMD_TSC_PhysicalPresence_0x100      3
+#define IDX_CMD_TSC_PhysicalPresence_0x10       4
+#define IDX_CMD_TPM_PhysicalEnable              5
+#define IDX_CMD_TPM_PhysicalSetDeactivated_0x00 6
+#define IDX_CMD_TPM_SHA1Start                   7
+
+
+/* hardware registers for TPM TIS */
+#define TPM_ACCESS                 0x0
+#define TPM_INT_ENABLE             0x8
+#define TPM_INT_VECTOR             0xc
+#define TPM_INT_STATUS             0x10
+#define TPM_INTF_CAPABILITY        0x14
+#define TPM_STS                    0x18
+#define TPM_DATA_FIFO              0x24
+#define TPM_DID_VID                0xf00
+#define TPM_RID                    0xf04
+
+/* address of locality 0 (TIS) */
+#define TPM_TIS_BASE_ADDRESS        0xfed40000
+
+#define ASCII32(a,b,c,d)     ((((Bit32u)a) <<  0) | (((Bit32u)b) <<  8) | \
+                              (((Bit32u)c) << 16) | (((Bit32u)d) << 24)  )
+#define ACPI_2_0_TCPA_SIGNATURE ASCII32('T','C','P','A') /* "TCPA" */
+
+
+#define STATUS_FLAG_SHUTDOWN                (1 << 0)
+
+#define ACPI_SEGMENT    0xE000
+
+/* Input and Output blocks for the TCG BIOS commands */
+
+struct hleei_short
+{
+       uint16_t   ipblength;
+       uint16_t   reserved;
+       uint32_t   hashdataptr;
+       uint32_t   hashdatalen;
+       uint32_t   pcrindex;
+       uint32_t   logdataptr;
+       uint32_t   logdatalen;
+} __attribute__((packed));
+
+struct hleei_long
+{
+       uint16_t   ipblength;
+       uint16_t   reserved;
+       uint32_t   hashdataptr;
+       uint32_t   hashdatalen;
+       uint32_t   pcrindex;
+       uint32_t   reserved2;
+       uint32_t   logdataptr;
+       uint32_t   logdatalen;
+} __attribute__((packed));
+
+struct hleeo
+{
+       uint16_t    opblength;
+       uint16_t    reserved;
+       uint32_t    eventnumber;
+       uint8_t     hashvalue[20];
+} __attribute__((packed));
+
+
+
+struct pttti
+{
+       uint16_t    ipblength;
+       uint16_t    reserved;
+       uint16_t    opblength;
+       uint16_t    reserved2;
+       uint8_t     tpmoperandin[0];
+} __attribute__((packed));
+
+struct pttto
+{
+       uint16_t    opblength;
+       uint16_t    reserved;
+       uint8_t     tpmoperandout[0];
+};
+
+
+struct hlei
+{
+       uint16_t    ipblength;
+       uint16_t    reserved;
+       uint32_t    hashdataptr;
+       uint32_t    hashdatalen;
+       uint32_t    pcrindex;
+       uint32_t    logeventtype;
+       uint32_t    logdataptr;
+       uint32_t    logdatalen;
+} __attribute__((packed));
+
+struct hleo
+{
+       uint16_t    opblength;
+       uint16_t    reserved;
+       uint32_t    eventnumber;
+} __attribute__((packed));
+
+struct hai
+{
+       uint16_t    ipblength;
+       uint16_t    reserved;
+       uint32_t    hashdataptr;
+       uint32_t    hashdatalen;
+       uint32_t    algorithmid;
+} __attribute__((packed));
+
+struct ti
+{
+       uint16_t    ipblength;
+       uint16_t    reserved;
+        uint16_t    opblength;
+        uint16_t    reserved2;
+        uint8_t     tssoperandin[0];
+} __attribute__((packed));
+
+struct to
+{
+       uint16_t    opblength;
+       uint16_t    reserved;
+       uint8_t     tssoperandout[0];
+} __attribute__((packed));
+
+
+struct pcpes
+{
+       uint32_t    pcrindex;
+       uint32_t    eventtype;
+       uint8_t     digest[20];
+       uint32_t    eventdatasize;
+       uint32_t    event;
+} __attribute__((packed));
+
+
+struct acpi_header
+{
+       uint32_t signature;
+       uint32_t length;
+       uint8_t  revision;
+       uint8_t  checksum;
+       uint8_t  oem_id[6];
+       uint64_t oem_table_id;
+       uint32_t oem_revision;
+       uint32_t creator_id;
+       uint32_t creator_revision;
+} __attribute__((packed));
+
+struct acpi_20_rsdt {
+       struct acpi_header header;
+       uint32_t entry[1];
+} __attribute__((packed));
+
+struct acpi_20_rsdp {
+       uint64_t signature;
+       uint8_t  checksum;
+       uint8_t  oem_id[6];
+       uint8_t  revision;
+       uint32_t rsdt_address;
+       uint32_t length;
+       uint64_t xsdt_address;
+       uint8_t  extended_checksum;
+       uint8_t  reserved[3];
+} __attribute__((packed));
+
+struct acpi_20_tcpa_client {
+       uint32_t laml;
+       uint64_t lasa;
+} __attribute__((packed));
+
+struct acpi_20_tcpa_server {
+       uint16_t reserved;
+       uint32_t laml;
+       uint64_t lasa;
+       /* more here */
+} __attribute__((packed));
+
+struct acpi_20_tcpa {
+       struct acpi_header header;
+       uint16_t platform_class;
+       union {
+               struct acpi_20_tcpa_client client;
+               struct acpi_20_tcpa_server server;
+       } u;
+} __attribute__((packed));
+
+
+#endif
diff -r 480436ef6255 -r c07326324f8d 
tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c        Fri Jan 26 
16:38:32 2007 +0000
@@ -0,0 +1,180 @@
+/*
+ *  Implementation of the TCG BIOS extension according to the specification
+ *  described in
+ *  
https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Author: Stefan Berger <stefanb@xxxxxxxxxx>
+ */
+#include "rombios_compat.h"
+#include "util.h"
+
+#include "tpm_drivers.h"
+#include "tcgbios.h"
+
+static uint32_t tis_wait_sts(uint8_t *addr, uint32_t time,
+                             uint8_t mask, uint8_t expect)
+{
+       uint32_t rc = 0;
+       while (time > 0) {
+               uint8_t sts = addr[TPM_STS];
+               if ((sts & mask) == expect) {
+                       rc = 1;
+                       break;
+               }
+               mssleep(1);
+               time--;
+       }
+       return rc;
+}
+
+static uint32_t tis_activate(uint32_t baseaddr)
+{
+       uint32_t rc = 0;
+       uint8_t *tis_addr = (uint8_t*)baseaddr;
+       uint8_t acc;
+       /* request access to locality */
+       tis_addr[TPM_ACCESS] = 0x2;
+
+       acc = tis_addr[TPM_ACCESS];
+       if ((acc & 0x20) != 0) {
+               tis_addr[TPM_STS] = 0x40;
+               rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40);
+       }
+       return rc;
+}
+
+uint32_t tis_ready(uint32_t baseaddr)
+{
+       uint32_t rc = 0;
+       uint8_t *tis_addr = (uint8_t*)baseaddr;
+
+       tis_addr[TPM_STS] = 0x40;
+       rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40);
+
+       return rc;
+}
+
+uint32_t tis_senddata(uint32_t baseaddr, unsigned char *data, uint32_t len)
+{
+       uint32_t rc = 0;
+       uint8_t *tis_addr = (uint8_t*)baseaddr;
+       uint32_t offset = 0;
+       uint32_t end = 0;
+
+       do {
+               uint16_t burst = 0;
+               uint32_t ctr = 0;
+               while (burst == 0 && ctr < 2000) {
+                       burst = (((uint16_t)tis_addr[TPM_STS+1])     ) +
+                               (((uint16_t)tis_addr[TPM_STS+2]) << 8);
+                       if (burst == 0) {
+                               mssleep(1);
+                               ctr++;
+                       }
+               }
+
+               if (burst == 0) {
+                       rc = TCG_RESPONSE_TIMEOUT;
+                       break;
+               }
+
+               while (1) {
+                       tis_addr[TPM_DATA_FIFO] = data[offset];
+                       offset++;
+                       burst--;
+
+                       if (burst == 0 || offset == len) {
+                               break;
+                       }
+               }
+
+               if (offset == len) {
+                       end = 1;
+               }
+       } while (end == 0);
+
+       return rc;
+}
+
+uint32_t tis_readresp(uint32_t baseaddr, unsigned char *buffer, uint32_t len)
+{
+       uint32_t rc = 0;
+       uint32_t offset = 0;
+       uint8_t *tis_addr = (uint8_t*)baseaddr;
+       uint32_t sts;
+
+       while (offset < len) {
+               buffer[offset] = tis_addr[TPM_DATA_FIFO];
+               offset++;
+               sts = tis_addr[TPM_STS];
+               /* data left ? */
+               if ((sts & 0x10) == 0) {
+                       break;
+               }
+       }
+       return rc;
+}
+
+
+uint32_t tis_waitdatavalid(uint32_t baseaddr)
+{
+       uint8_t *tis_addr = (uint8_t*)baseaddr;
+       uint32_t rc = 0;
+       if (tis_wait_sts(tis_addr, 1000, 0x80, 0x80) == 0) {
+               rc = TCG_NO_RESPONSE;
+       }
+       return rc;
+}
+
+uint32_t tis_waitrespready(uint32_t baseaddr, uint32_t timeout)
+{
+       uint32_t rc = 0;
+       uint8_t *tis_addr = (uint8_t*)baseaddr;
+       tis_addr[TPM_STS] = 0x20;
+       if (tis_wait_sts(tis_addr, timeout, 0x10, 0x10) == 0) {
+               rc = TCG_NO_RESPONSE;
+       }
+       return rc;
+}
+
+/* if device is not there, return '0', '1' otherwise */
+uint32_t tis_probe(uint32_t baseaddr)
+{
+       uint32_t rc = 0;
+       uint8_t *tis_addr = (uint8_t*)baseaddr;
+       uint32_t didvid = *(uint32_t*)&tis_addr[TPM_DID_VID];
+       if ((didvid != 0) && (didvid != 0xffffffff)) {
+               rc = 1;
+       }
+       return rc;
+}
+
+
+struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = {
+       {
+               .baseaddr      = TPM_TIS_BASE_ADDRESS,
+               .activate      = tis_activate,
+               .ready         = tis_ready,
+               .senddata      = tis_senddata,
+               .readresp      = tis_readresp,
+               .waitdatavalid = tis_waitdatavalid,
+               .waitrespready = tis_waitrespready,
+               .probe         = tis_probe,
+       },
+};
diff -r 480436ef6255 -r c07326324f8d 
tools/firmware/rombios/32bit/tcgbios/tpm_drivers.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.h        Fri Jan 26 
16:38:32 2007 +0000
@@ -0,0 +1,18 @@
+#ifndef TPM_DRIVER_H
+/* low level driver implementation */
+struct tpm_driver {
+       uint32_t baseaddr;
+       uint32_t (*activate)(uint32_t baseaddr);
+       uint32_t (*ready)(uint32_t baseaddr);
+       uint32_t (*senddata)(uint32_t baseaddr, unsigned char *data, uint32_t 
len);
+       uint32_t (*readresp)(uint32_t baseaddr, unsigned char *buffer, uint32_t 
len);
+       uint32_t (*waitdatavalid)(uint32_t baseaddr);
+       uint32_t (*waitrespready)(uint32_t baseaddr, uint32_t timeout);
+       uint32_t (*probe)(uint32_t baseaddr);
+};
+
+#define TPM_NUM_DRIVERS      1
+
+#define TPM_INVALID_DRIVER  -1
+
+#endif
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/util.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/util.c       Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,450 @@
+/*
+ * util.c: Helper library functions for HVMLoader.
+ *
+ * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
+ * Copyright (c) 2005, International Business Machines Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include <stdarg.h>
+#include <stdint.h>
+#include "util.h"
+
+static void putchar(char c);
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+
+void outb(uint16_t addr, uint8_t val)
+{
+    __asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(val) );
+}
+
+void outw(uint16_t addr, uint16_t val)
+{
+    __asm__ __volatile__ ( "outw %%ax, %%dx" :: "d"(addr), "a"(val) );
+}
+
+void outl(uint16_t addr, uint32_t val)
+{
+    __asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) );
+}
+
+uint8_t inb(uint16_t addr)
+{
+    uint8_t val;
+    __asm__ __volatile__ ( "inb %%dx,%%al" : "=a" (val) : "d" (addr) );
+    return val;
+}
+
+uint16_t inw(uint16_t addr)
+{
+    uint16_t val;
+    __asm__ __volatile__ ( "inw %%dx,%%ax" : "=a" (val) : "d" (addr) );
+    return val;
+}
+
+uint32_t inl(uint16_t addr)
+{
+    uint32_t val;
+    __asm__ __volatile__ ( "inl %%dx,%%eax" : "=a" (val) : "d" (addr) );
+    return val;
+}
+
+char *itoa(char *a, unsigned int i)
+{
+    unsigned int _i = i, x = 0;
+
+    do {
+        x++;
+        _i /= 10;
+    } while ( _i != 0 );
+
+    a += x;
+    *a-- = '\0';
+
+    do {
+        *a-- = (i % 10) + '0';
+        i /= 10;
+    } while ( i != 0 );
+
+    return a + 1;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+    signed char res;
+
+    while ( ((res = *cs - *ct++) == 0) && (*cs++ != '\0') )
+        continue;
+
+    return res;
+}
+
+int strncmp(const char *s1, const char *s2, uint32_t n)
+{
+       uint32_t ctr;
+       for (ctr = 0; ctr < n; ctr++)
+               if (s1[ctr] != s2[ctr])
+                       return (int)(s1[ctr] - s2[ctr]);
+       return 0;
+}
+
+void *memcpy(void *dest, const void *src, unsigned n)
+{
+    int t0, t1, t2;
+
+    __asm__ __volatile__ (
+        "cld\n"
+        "rep; movsl\n"
+        "testb $2,%b4\n"
+        "je 1f\n"
+        "movsw\n"
+        "1: testb $1,%b4\n"
+        "je 2f\n"
+        "movsb\n"
+        "2:"
+        : "=&c" (t0), "=&D" (t1), "=&S" (t2)
+        : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
+        : "memory" );
+    return dest;
+}
+
+void *memmove(void *dest, const void *src, unsigned n)
+{
+    if ( (long)dest > (long)src )
+    {
+        n--;
+        while ( n > 0 )
+        {
+            ((char *)dest)[n] = ((char *)src)[n];
+            n--;
+        }
+    }
+    else
+    {
+        memcpy(dest, src, n);
+    }
+    return dest;
+}
+
+char *
+strcpy(char *dest, const char *src)
+{
+    char *p = dest;
+    while ( *src )
+        *p++ = *src++;
+    *p = 0;
+    return dest;
+}
+
+char *
+strncpy(char *dest, const char *src, unsigned n)
+{
+    int i = 0;
+    char *p = dest;
+
+    /* write non-NUL characters from src into dest until we run
+       out of room in dest or encounter a NUL in src */
+    while ( (i < n) && *src )
+    {
+        *p++ = *src++;
+        i++;
+    }
+
+    /* pad remaining bytes of dest with NUL bytes */
+    while ( i < n )
+    {
+        *p++ = 0;
+        i++;
+    }
+
+    return dest;
+}
+
+unsigned
+strlen(const char *s)
+{
+    int i = 0;
+    while ( *s++ )
+        i++;
+    return i;
+}
+
+void *
+memset(void *s, int c, unsigned n)
+{
+    uint8_t b = (uint8_t) c;
+    uint8_t *p = (uint8_t *)s;
+    int i;
+    for ( i = 0; i < n; i++ )
+        *p++ = b;
+    return s;
+}
+
+int
+memcmp(const void *s1, const void *s2, unsigned n)
+{
+    unsigned i;
+    uint8_t *p1 = (uint8_t *) s1;
+    uint8_t *p2 = (uint8_t *) s2;
+
+    for ( i = 0; i < n; i++ )
+    {
+        if ( p1[i] < p2[i] )
+            return -1;
+        else if ( p1[i] > p2[i] )
+            return 1;
+    }
+
+    return 0;
+}
+
+void
+cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+{
+    __asm__ __volatile__ (
+        "cpuid"
+        : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
+        : "0" (idx) );
+}
+
+/* Write a two-character hex representation of 'byte' to digits[].
+   Pre-condition: sizeof(digits) >= 2 */
+void
+byte_to_hex(char *digits, uint8_t byte)
+{
+    uint8_t nybbel = byte >> 4;
+
+    if ( nybbel > 9 )
+        digits[0] = 'a' + nybbel-10;
+    else
+        digits[0] = '0' + nybbel;
+
+    nybbel = byte & 0x0f;
+    if ( nybbel > 9 )
+        digits[1] = 'a' + nybbel-10;
+    else
+        digits[1] = '0' + nybbel;
+}
+
+/* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID
+   string.
+
+   Pre-condition: sizeof(dest) >= 37 */
+void
+uuid_to_string(char *dest, uint8_t *uuid)
+{
+    int i = 0;
+    char *p = dest;
+
+    for ( i = 0; i < 4; i++ )
+    {
+        byte_to_hex(p, uuid[i]);
+        p += 2;
+    }
+    *p++ = '-';
+    for ( i = 4; i < 6; i++ )
+    {
+        byte_to_hex(p, uuid[i]);
+        p += 2;
+    }
+    *p++ = '-';
+    for ( i = 6; i < 8; i++ )
+    {
+        byte_to_hex(p, uuid[i]);
+        p += 2;
+    }
+    *p++ = '-';
+    for ( i = 8; i < 10; i++ )
+    {
+        byte_to_hex(p, uuid[i]);
+        p += 2;
+    }
+    *p++ = '-';
+    for ( i = 10; i < 16; i++ )
+    {
+        byte_to_hex(p, uuid[i]);
+        p += 2;
+    }
+    *p = '\0';
+}
+
+static char *printnum(char *p, unsigned long num, int base)
+{
+    unsigned long n;
+
+    if ( (n = num/base) > 0 )
+        p = printnum(p, n, base);
+    *p++ = "0123456789abcdef"[(int)(num % base)];
+    *p = '\0';
+    return p;
+}
+
+static void _doprint(void (*put)(char), char const *fmt, va_list ap)
+{
+    register char *str, c;
+    int lflag, zflag, nflag;
+    char buffer[17];
+    unsigned value;
+    int i, slen, pad;
+
+    for ( ; *fmt != '\0'; fmt++ )
+    {
+        if ( *fmt != '%' )
+        {
+            put(*fmt);
+            continue;
+        }
+
+        pad = zflag = nflag = lflag = 0;
+        c = *++fmt;
+        if ( (c == '-') || isdigit(c) )
+        {
+            if ( c == '-' )
+            {
+                nflag = 1;
+                c = *++fmt;
+            }
+            zflag = c == '0';
+            for ( pad = 0; isdigit(c); c = *++fmt )
+                pad = (pad * 10) + c - '0';
+        }
+        if ( c == 'l' ) /* long extension */
+        {
+            lflag = 1;
+            c = *++fmt;
+        }
+        if ( (c == 'd') || (c == 'u') || (c == 'o') || (c == 'x') )
+        {
+            if ( lflag )
+                value = va_arg(ap, unsigned);
+            else
+                value = (unsigned) va_arg(ap, unsigned int);
+            str = buffer;
+            printnum(str, value,
+                     c == 'o' ? 8 : (c == 'x' ? 16 : 10));
+            goto printn;
+        }
+        else if ( (c == 'O') || (c == 'D') || (c == 'X') )
+        {
+            value = va_arg(ap, unsigned);
+            str = buffer;
+            printnum(str, value,
+                     c == 'O' ? 8 : (c == 'X' ? 16 : 10));
+        printn:
+            slen = strlen(str);
+            for ( i = pad - slen; i > 0; i-- )
+                put(zflag ? '0' : ' ');
+            while ( *str )
+                put(*str++);
+        }
+        else if ( c == 's' )
+        {
+            str = va_arg(ap, char *);
+            slen = strlen(str);
+            if ( nflag == 0 )
+                for ( i = pad - slen; i > 0; i-- )
+                    put(' ');
+            while ( *str )
+                put(*str++);
+            if ( nflag )
+                for ( i = pad - slen; i > 0; i-- )
+                    put(' ');
+        }
+        else if ( c == 'c' )
+        {
+            put(va_arg(ap, int));
+        }
+        else
+        {
+            put(*fmt);
+        }
+    }
+}
+
+static void putchar(char c)
+{
+    outb(0xe9, c);
+}
+
+int printf(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    _doprint(putchar, fmt, ap);
+    va_end(ap);
+
+    return 0;
+}
+
+int vprintf(const char *fmt, va_list ap)
+{
+    _doprint(putchar, fmt, ap);
+    return 0;
+}
+
+
+/*
+ * sleep by synchronizing with the PIT on channel 2
+ * http://bochs.sourceforge.net/techspec/intel-82c54-timer.pdf.gz
+ */
+#define PIT_CTR2       0x80
+#define PIT_CTR1       0x40
+#define PIT_CTR0       0x00
+
+#define PIT_RW_LSB     0x10
+
+#define PIT_MODE0      0x0
+
+#define PIT_CTR_16BIT  0x0
+
+#define PIT_CMD_LATCH  0x0
+
+#define PORT_PIT_CMD     0x43
+#define PORT_PIT_CTR2    0x42
+#define PORT_PIT_CTR1    0x41
+#define PORT_PIT_CTR0    0x40
+
+#define PIT_FREQ         1193182 /* Hz */
+
+#define PORT_PPI         0x61
+
+void mssleep(uint32_t waittime)
+{
+       long int timeout = 0;
+       uint8_t last = 0x0;
+       uint8_t old_ppi = inb(PORT_PPI);
+
+       /* use ctr2; ctr0 is used by the Bochs BIOS */
+       /* ctr2 drives speaker -- turn it off */
+       outb(PORT_PPI, old_ppi & 0xfc);
+
+       outb(PORT_PIT_CMD, PIT_CTR2 | PIT_RW_LSB | PIT_MODE0 | PIT_CTR_16BIT);
+       outb(PORT_PIT_CTR2, last);         /* start countdown */
+
+       while (timeout < (waittime * PIT_FREQ / 1000)) {
+               uint8_t cur, delta;
+               outb(PORT_PIT_CMD, PIT_CTR2 | PIT_CMD_LATCH);
+               cur = inb(PORT_PIT_CTR2);
+               delta = last - cur;
+               timeout += delta;
+               last = cur;
+       }
+       /* turn ctr2 off */
+       outb(PORT_PIT_CMD, PIT_CTR2 | PIT_RW_LSB | PIT_MODE0 | PIT_CTR_16BIT);
+       outb(PORT_PIT_CTR2, 0xff); /* start countdown */
+       outb(PORT_PIT_CTR2, 0x0);  /* stop */
+
+       outb(PORT_PPI, old_ppi);
+}
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/util.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/util.h       Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,28 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+void outb(uint16_t addr, uint8_t val);
+void outw(uint16_t addr, uint16_t val);
+void outl(uint16_t addr, uint32_t val);
+uint8_t inb(uint16_t addr);
+uint16_t inw(uint16_t addr);
+uint32_t inl(uint16_t addr);
+void mssleep(uint32_t time);
+
+char *itoa(char *a, unsigned int i);
+int strcmp(const char *cs, const char *ct);
+int strncmp(const char *s1, const char *s2, uint32_t n);
+void *memcpy(void *dest, const void *src, unsigned n);
+void *memmove(void *dest, const void *src, unsigned n);
+char *strcpy(char *dest, const char *src);
+char *strncpy(char *dest, const char *src, unsigned n);
+unsigned strlen(const char *s);
+void * memset(void *s, int c, unsigned n);
+int memcmp(const void *s1, const void *s2, unsigned n);
+void cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t 
*edx);
+void byte_to_hex(char *digits, uint8_t byte);
+void uuid_to_string(char *dest, uint8_t *uuid);
+int printf(const char *fmt, ...);
+
+
+#endif
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bitgateway.c
--- a/tools/firmware/rombios/32bitgateway.c     Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/32bitgateway.c     Fri Jan 26 16:38:32 2007 +0000
@@ -484,3 +484,5 @@ test_gateway()
                printf("working correctly\n");
        }
 }
+
+#include "tcgbios.c"
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bitprotos.h
--- a/tools/firmware/rombios/32bitprotos.h      Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/32bitprotos.h      Fri Jan 26 16:38:32 2007 +0000
@@ -1,11 +1,29 @@
 #ifndef PROTOS_HIGHBIOS
 #define PROTOS_HIGHBIOS
 
+
+/* shared include file for bcc and gcc */
+
 /* bcc does not like 'enum' */
-#define IDX_MULTIPLY   0
-#define IDX_ADD        1
-#define IDX_SET_STATIC 2
-#define IDX_LAST       3 /* keep last! */
+#define IDX_MULTIPLY                       0
+#define IDX_ADD                            1
+#define IDX_SET_STATIC                     2
+
+#define IDX_TCGINTERRUPTHANDLER            3
+#define IDX_TCPA_ACPI_INIT                 4
+#define IDX_TCPA_EXTEND_ACPI_LOG           5
+#define IDX_TCPA_CALLING_INT19H            6
+#define IDX_TCPA_RETURNED_INT19H           7
+#define IDX_TCPA_ADD_EVENT_SEPARATORS      8
+#define IDX_TCPA_WAKE_EVENT                9
+#define IDX_TCPA_ADD_BOOTDEVICE            10
+#define IDX_TCPA_START_OPTION_ROM_SCAN     11
+#define IDX_TCPA_OPTION_ROM                12
+#define IDX_TCPA_IPL                       13
+#define IDX_TCPA_INITIALIZE_TPM            14
+#define IDX_TCPA_MEASURE_POST              15
+
+#define IDX_LAST                           16 /* keep last! */
 
 
 #ifdef GCC_PROTOS
@@ -19,4 +37,19 @@ Bit32u add( PARMS(Bit32u a, Bit32u b) );
 Bit32u add( PARMS(Bit32u a, Bit32u b) );
 Bit32u set_static( PARMS(Bit32u) );
 
+Bit32u TCGInterruptHandler( PARMS(pushad_regs_t *regs, Bit32u esds, Bit32u 
flags_ptr));
+
+void tcpa_acpi_init( PARMS(void) );
+Bit32u tcpa_extend_acpi_log( PARMS(Bit32u entry_ptr) );
+void tcpa_calling_int19h( PARMS(void) );
+void tcpa_returned_int19h( PARMS(void) );
+void tcpa_add_event_separators( PARMS(void) );
+void tcpa_wake_event( PARMS(void) );
+void tcpa_add_bootdevice( PARMS(Bit32u bootcd, Bit32u bootdrv) );
+void tcpa_start_option_rom_scan( PARMS(void) );
+void tcpa_option_rom( PARMS(Bit32u seg) );
+void tcpa_ipl( PARMS(Bit32u seg) );
+void tcpa_measure_post( PARMS(Bit32u from, Bit32u to) );
+Bit32u tcpa_initialize_tpm( PARMS(Bit32u physpres) );
+
 #endif
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/Makefile
--- a/tools/firmware/rombios/Makefile   Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/Makefile   Fri Jan 26 16:38:32 2007 +0000
@@ -12,7 +12,7 @@ clean:
        rm -f  rombios*.txt rombios*.sym usage biossums
        rm -f  BIOS-bochs-*
 
-BIOS-bochs-latest: rombios.c biossums 32bitgateway.c
+BIOS-bochs-latest: rombios.c biossums 32bitgateway.c tcgbios.c
        gcc -DBX_SMP_PROCESSORS=1 -E -P $< > _rombios_.c
        bcc -o rombios.s -C-c -D__i86__ -0 -S _rombios_.c
        sed -e 's/^\.text//' -e 's/^\.data//' rombios.s > _rombios_.s
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c  Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/rombios.c  Fri Jan 26 16:38:32 2007 +0000
@@ -153,6 +153,8 @@
 
 #define BX_USE_ATADRV    1
 #define BX_ELTORITO_BOOT 1
+
+#define BX_TCGBIOS       0              /* main switch for TCG BIOS ext. */
 
 #define BX_MAX_ATA_INTERFACES   4
 #define BX_MAX_ATA_DEVICES      (BX_MAX_ATA_INTERFACES*2)
@@ -1854,6 +1856,9 @@ print_bios_banner()
 {
   printf(BX_APPNAME" BIOS, %d cpu%s, ", BX_SMP_PROCESSORS, 
BX_SMP_PROCESSORS>1?"s":"");
   printf("%s %s\n", bios_cvs_version_string, bios_date_string);
+#if BX_TCGBIOS
+  printf("TCG-enabled BIOS.\n");
+#endif
   printf("\n");
   test_gateway();
 }
@@ -5717,6 +5722,10 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, 
     BX_INFO("int13_cdemu: function %02x, emulation not active for DL= %02x\n", 
GET_AH(), GET_DL());
     goto int13_fail;
     }
+
+#if BX_TCGBIOS
+  tcpa_ipl((Bit32u)bootseg);               /* specs: 8.2.3 steps 4 and 5 */
+#endif
   
   switch (GET_AH()) {
 
@@ -9504,6 +9513,9 @@ rom_scan:
   ;;   2         ROM length in 512-byte blocks
   ;;   3         ROM initialization entry point (FAR CALL)
 
+#if BX_TCGBIOS
+  call _tcpa_start_option_rom_scan    /* specs: 3.2.3.3 + 10.4.3 */
+#endif
   mov  cx, #0xc000
 rom_scan_loop:
   mov  ds, cx
@@ -9522,6 +9534,20 @@ rom_scan_loop:
   add  al, #0x04
 block_count_rounded:
 
+#if BX_TCGBIOS
+  push ax
+  push ds
+  push ecx
+  xor ax, ax
+  mov ds, ax
+  and ecx, #0xffff
+  push ecx       ;; segment where option rom is located at
+  call _tcpa_option_rom                   /* specs: 3.2.3.3 */
+  add sp, #4    ;; pop segment
+  pop ecx      ;; original ecx
+  pop ds
+  pop ax
+#endif
   xor  bx, bx   ;; Restore DS back to 0000:
   mov  ds, bx
   push ax       ;; Save AX
@@ -9827,6 +9853,16 @@ post_default_ints:
   in   al, 0x71
   mov  0x0410, ax
 
+#if BX_TCGBIOS
+  call _tcpa_acpi_init
+
+  push dword #0
+  call _tcpa_initialize_tpm
+  add sp, #4
+
+  call _tcpa_do_measure_POSTs
+  call _tcpa_wake_event     /* specs: 3.2.3.7 */
+#endif
 
   ;; Parallel setup
   SET_INT_VECTOR(0x0F, #0xF000, #dummy_iret_handler)
@@ -9949,9 +9985,16 @@ post_default_ints:
   ;;
 #endif // BX_ELTORITO_BOOT
  
+#if BX_TCGBIOS
+  call _tcpa_calling_int19h          /* specs: 8.2.3 step 1 */
+  call _tcpa_add_event_separators    /* specs: 8.2.3 step 2 */
+#endif
   int  #0x19
   //JMP_EP(0x0064) ; INT 19h location
 
+#if BX_TCGBIOS
+  call _tcpa_returned_int19h         /* specs: 8.2.3 step 3/7 */
+#endif
 
 .org 0xe2c3 ; NMI Handler Entry Point
 nmi:
@@ -10434,6 +10477,21 @@ db 0x00    ;; base  23:16
 ;----------
 .org 0xfe6e ; INT 1Ah Time-of-day Service Entry Point
 int1a_handler:
+#if BX_TCGBIOS
+  cmp  ah, #0xbb
+  jne  no_tcg
+  pushf
+  push ds
+  push es
+  pushad
+  call _int1a_function32
+  popad
+  pop es
+  pop ds
+  popf
+  iret
+no_tcg:
+#endif
 #if BX_PCIBIOS
   cmp  ah, #0xb1
   jne  int1a_normal
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/tcgbios.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/tcgbios.c  Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,263 @@
+/*
+ * Implementation of stub functions for calls to the TCG BIOS
+ * extension in 32bit memory area.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Author: Stefan Berger <stefanb@xxxxxxxxxx>
+ */
+
+/*******************************************************************
+  Support for TCPA ACPI logging
+ ******************************************************************/
+
+/*
+ * Extend the ACPI log with the given entry by copying the
+ * entry data into the log.
+ * Input
+ *  Pointer to the structure to be copied into the log
+ *
+ * Output:
+ *  lower 16 bits of return code contain entry number
+ *  if entry number is '0', then upper 16 bits contain error code.
+ */
+Bit32u tcpa_extend_acpi_log(entry_ptr)
+    Bit32u entry_ptr;
+{
+       ASM_START
+       DoUpcall IDX_TCPA_EXTEND_ACPI_LOG
+       ASM_END
+}
+
+
+/*
+   initialize the TCPA ACPI subsystem; find the ACPI tables and determine
+   where the TCPA table is.
+ */
+ void
+tcpa_acpi_init()
+{
+       ASM_START
+       DoUpcall IDX_TCPA_ACPI_INIT
+       ASM_END
+}
+
+
+/*
+ * Add measurement to log about call of int 19h
+ */
+ void
+tcpa_calling_int19h()
+{
+       ASM_START
+       DoUpcall IDX_TCPA_CALLING_INT19H
+       ASM_END
+}
+
+/*
+ * Add measurement to log about retuning from int 19h
+ */
+ void
+tcpa_returned_int19h()
+{
+       ASM_START
+       DoUpcall IDX_TCPA_RETURNED_INT19H
+       ASM_END
+}
+
+/*
+ * Add event separators for PCRs 0 to 7; specs 8.2.3
+ */
+ void
+tcpa_add_event_separators()
+{
+       ASM_START
+       DoUpcall IDX_TCPA_ADD_EVENT_SEPARATORS
+       ASM_END
+}
+
+
+/*
+ * Add a wake event to the log
+ */
+ void
+tcpa_wake_event()
+{
+       ASM_START
+       DoUpcall IDX_TCPA_WAKE_EVENT
+       ASM_END
+}
+
+
+/*
+ * Add measurement to the log about option rom scan
+ * 10.4.3 : action 14
+ */
+ void
+tcpa_start_option_rom_scan()
+{
+       ASM_START
+       DoUpcall IDX_TCPA_START_OPTION_ROM_SCAN
+       ASM_END
+}
+
+
+/*
+ * Add measurement to the log about an option rom
+ */
+ void
+tcpa_option_rom(seg)
+    Bit32u seg;
+{
+       ASM_START
+       DoUpcall IDX_TCPA_OPTION_ROM
+       ASM_END
+}
+
+/*
+ * Add a measurement regarding the boot device (CDRom, Floppy, HDD) to
+ * the list of measurements.
+ */
+void
+ tcpa_add_bootdevice(bootcd, bootdrv)
+  Bit32u bootcd;
+  Bit32u bootdrv;
+{
+       ASM_START
+       DoUpcall IDX_TCPA_ADD_BOOTDEVICE
+       ASM_END
+}
+
+/*
+ * Add a measurement to the log in support of 8.2.5.3
+ * Creates two log entries
+ *
+ * Input parameter:
+ *  seg    : segment where the IPL data are located
+ */
+ void
+tcpa_ipl(seg)
+    Bit32u seg;
+{
+       ASM_START
+       DoUpcall IDX_TCPA_IPL
+       ASM_END
+}
+
+
+Bit32u
+tcpa_initialize_tpm(physpres)
+  Bit32u physpres;
+{
+       ASM_START
+       DoUpcall IDX_TCPA_INITIALIZE_TPM
+       ASM_END
+}
+
+void
+tcpa_measure_post(from, to)
+   Bit32u from;
+   Bit32u to;
+{
+       ASM_START
+       DoUpcall IDX_TCPA_MEASURE_POST
+       ASM_END
+}
+
+ASM_START
+MACRO POST_MEASURE
+       push word #0x000f
+       push #?2
+       push word #0x000f
+       push #?1
+       call _tcpa_measure_post
+       add sp, #8
+MEND
+ASM_END
+
+void
+tcpa_do_measure_POSTs()
+{
+       ASM_START
+
+       POST_MEASURE post, nmi
+       POST_MEASURE floppy_drive_post, hard_drive_post
+       POST_MEASURE hard_drive_post, ebda_post
+       POST_MEASURE ebda_post, eoi_jmp_post
+       POST_MEASURE eoi_jmp_post, timer_tick_post
+       POST_MEASURE timer_tick_post, int76_handler
+
+       ret
+       ASM_END
+}
+
+Bit32u
+TCGInterruptHandler(regs_ptr, es, ds, flags_ptr)
+   Bit32u regs_ptr;
+   Bit16u es;
+   Bit16u ds;
+   Bit32u flags_ptr;
+{
+       ASM_START
+       DoUpcall IDX_TCGINTERRUPTHANDLER
+       ASM_END
+}
+
+/*
+ * C-dispatcher for the TCG BIOS functions
+ */
+#define TCG_MAGIC 0x41504354L
+  void
+int1a_function32(regs, ES, DS, FLAGS)
+  pushad_regs_t regs;
+  Bit16u ES, DS, FLAGS;
+{
+       Bit16u rc;
+
+       switch (regs.u.r8.ah) {
+       case 0xbb:
+               /*
+                * all functions except for TCG_StatusCheck need to have the
+                * TCG_MAGIC in 'ebx'.
+                */
+               if (regs.u.r8.al != 0 &&
+                   regs.u.r32.ebx != TCG_MAGIC) {
+                   SET_CF();
+                   return;
+               }
+               switch(regs.u.r8.al) {
+               case 0x00:
+               case 0x01:
+               case 0x02:
+               case 0x03:
+               case 0x04:
+               case 0x05:
+               case 0x06:
+               case 0x07:
+                       TCGInterruptHandler(((Bit32u)get_SS() << 4) + 
(Bit32u)&regs,
+                                           ES, DS,
+                                           ((Bit32u)get_SS() << 4) + 
(Bit32u)&FLAGS);
+                       break;
+
+               default:
+                       SET_CF();
+               }
+       default:
+               SET_CF();
+               break;
+       }
+}

_______________________________________________
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] [HVM] Add TCG BIOS extensions to the high memory area along with, Xen patchbot-unstable <=