[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [HVM] Add TCG BIOS extensions to the high memory area along with



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.