Index: seabios/Makefile
===================================================================
--- seabios.orig/Makefile
+++ seabios/Makefile
@@ -20,7 +20,7 @@ SRC16=$(SRCBOTH) system.c disk.c font.c
 SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
       acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
       lzmadecode.c bootsplash.c jpeg.c usb-hub.c paravirt.c dev-i440fx.c \
-      pci_region.c tcgbios.c tpm_drivers.c sha1.c
+      pci_region.c tcgbios.c tpm_drivers.c sha1.c tis_test.c
 SRC32SEG=util.c output.c pci.c pcibios.c apm.c stacks.c
 
 cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
Index: seabios/src/tcgbios.c
===================================================================
--- seabios.orig/src/tcgbios.c
+++ seabios/src/tcgbios.c
@@ -18,6 +18,9 @@
 #include "sha1.h"  // sha1
 #include "smbios.h" // get_smbios_entry_point
 
+#if CONFIG_TIS_TEST
+#include "tis_test.h"
+#endif
 
 static const u8 Startup_ST_CLEAR[2] = { 0x00, TPM_ST_CLEAR };
 static const u8 Startup_ST_STATE[2] = { 0x00, TPM_ST_STATE };
@@ -697,6 +700,9 @@ pass_through_to_tpm(struct pttti *pttti,
     iovec[1].data   = NULL;
     iovec[1].length = 0;
 
+    if (CONFIG_TIS_TEST)
+        locty = pttti->reserved;
+
     rc = transmit(locty, iovec, pttto->tpmopout, &resbuflen);
     if (rc)
         goto err_exit;
@@ -1732,26 +1738,29 @@ err_exit:
 }
 
 
-static void
+static int
 show_tpm_state(void)
 {
+    int state = 0;
     struct tpm_permanent_flags pf;
     u8 has_owner;
 
     if (read_permanent_flags((char *)&pf, sizeof(pf)) ||
         read_has_owner(&has_owner))
-        return;
+        return ~0;
 
     printf("TPM is ");
 
-    if (pf.flags[PERM_FLAG_IDX_DISABLE])
+    if (pf.flags[PERM_FLAG_IDX_DISABLE]) {
         printf("disabled");
-    else
+        state |= 1 << PERM_FLAG_IDX_DISABLE;
+    } else
         printf("enabled");
 
-    if (pf.flags[PERM_FLAG_IDX_DEACTIVATED])
+    if (pf.flags[PERM_FLAG_IDX_DEACTIVATED]) {
         printf(", deactivated");
-    else
+        state |= 1 << PERM_FLAG_IDX_DEACTIVATED;
+    } else
         printf(", active");
 
     if (has_owner)
@@ -1764,6 +1773,7 @@ show_tpm_state(void)
             printf("and an owner cannot be installed.\n");
     }
 
+    return state;
 }
 
 
@@ -1822,7 +1832,7 @@ tcpa_menu(void)
         return;
 
     int show_menu = 1;
-    int scan_code;
+    int scan_code, state;
     u32 rc;
     tpm_bios_cfg_t cfg = {
         .op  = 0,
@@ -1841,9 +1851,12 @@ tcpa_menu(void)
                    "5. Clear ownership\n"
                    "6. Allow installation of owner\n"
                    "7. Prevent installation of owner\n"
+#if CONFIG_TIS_TEST
+                   "8. TIS test\n"
+#endif
                    "Escape for previous menu.\n");
             show_menu = 0;
-            show_tpm_state();
+            state = show_tpm_state();
         }
 
         cfg.op = 0;
@@ -1857,6 +1870,10 @@ tcpa_menu(void)
         case 2 ... 8:
             cfg.op = scan_code - 1;
             break;
+#if CONFIG_TIS_TEST
+        case 9:
+            tis_test(state);
+#endif
         default:
             continue;
         }
Index: seabios/src/tis_test.c
===================================================================
--- /dev/null
+++ seabios/src/tis_test.c
@@ -0,0 +1,846 @@
+/*
+ *  TIS interface tests
+ *
+ *  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,2011
+ *
+ * Author: Stefan Berger <stefanb@us.ibm.com>
+ */
+#include "config.h"
+
+#include "types.h"
+#include "util.h" /* read{b,l}, write{b,l} */
+#include "tcgbios.h"
+#include "tpm_drivers.h"
+#include "tis_test.h"
+
+
+static int
+tis_check_reg(u32 reg, u8 locty, u32 mask, u32 exp, u32 timeout)
+{
+    u32 val;
+    u32 now = 0;
+
+    while (now <= timeout) {
+        val = readl(TIS_REG(locty, reg));
+
+        if ((val & mask) == exp)
+            return 0;
+
+        msleep(10);
+
+        now += 10;
+    }
+
+    return 1;
+}
+
+static int
+tis_check_status(u8 locty, u32 mask, u32 exp, u32 timeout)
+{
+    return tis_check_reg(TIS_REG_STS, locty, mask, exp, timeout);
+}
+
+static int
+tis_check_access(u8 locty, u32 mask, u32 exp, u32 timeout)
+{
+    return tis_check_reg(TIS_REG_ACCESS, locty, mask, exp, timeout);
+}
+
+static void
+wait_for_keystroke(void)
+{
+    printf("Press escape to continue.\n");
+    while (1) {
+        switch (get_keystroke(1000)) {
+        case 1:
+            return;
+        }
+    }
+}
+
+static void
+check_access(u8 locty, u8 mask, u8 exp,
+             const char *succ_msg,
+             const char *fail_msg)
+{
+    u8 acc = readb(TIS_REG(locty, TIS_REG_ACCESS));
+    u8 res = acc & mask;
+
+    if (res == exp)
+        printf("%s  -- access reg : %02x\n", succ_msg, acc);
+    else {
+        printf("ERROR: %s\n"
+               "value = %02x, mask = %02x, exp = %02x, actual = %02x, "
+               "bad = %02x\n",
+               fail_msg, acc, mask, exp, res, res ^ exp );
+        wait_for_keystroke();
+    }
+}
+
+static void
+tis_activate_locality(u8 new_locty)
+{
+    int locty;
+
+    /* release locality in use top-downwards */
+    for (locty = 4; locty >= 0; locty--)
+        writeb(TIS_REG(locty, TIS_REG_ACCESS),
+               TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_BEEN_SEIZED);
+
+    printf("Requesting access to locality %d\n", new_locty);
+
+    writeb(TIS_REG(new_locty, TIS_REG_ACCESS),
+           TIS_ACCESS_REQUEST_USE);
+
+    check_access(new_locty,
+                 TIS_ACCESS_ACTIVE_LOCALITY,
+                 TIS_ACCESS_ACTIVE_LOCALITY,
+                 "Switch to the locality",
+                 "Could not get the locality");
+}
+
+/*
+ * Test getting access to localities using the
+ * TIS_ACCESS_ACTIVATE_LOCALITY flag
+ * The test ends with locality 0 being active.
+ */
+static void
+test_active_locality_flag(void)
+{
+    printf("Requesting access to locality 0\n");
+
+    writeb(TIS_REG(0, TIS_REG_ACCESS),
+           TIS_ACCESS_REQUEST_USE|TIS_ACCESS_BEEN_SEIZED);
+
+    check_access(0,
+                 TIS_ACCESS_TPM_ESTABLISHMENT,
+                 TIS_ACCESS_TPM_ESTABLISHMENT,
+                 "Valid TPM Establishment flag in locality 0",
+                 "Invalid TPM Establishment flag in locality 0");
+
+    check_access(0,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY | TIS_ACCESS_BEEN_SEIZED,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY,
+                 "Got locality 0",
+                 "Could not get locality 0");
+
+    printf("Giving up locality 0\n");
+    writeb(TIS_REG(0, TIS_REG_ACCESS), TIS_ACCESS_ACTIVE_LOCALITY);
+
+    check_access(0,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY,
+                 0x80,
+                 "Successfully released locality 0",
+                 "Still have locality 0");
+
+    printf("Requesting access to locality 1\n");
+
+    writeb(TIS_REG(1, TIS_REG_ACCESS), TIS_ACCESS_REQUEST_USE);
+
+    check_access(1,
+                 TIS_ACCESS_ACTIVE_LOCALITY,
+                 TIS_ACCESS_ACTIVE_LOCALITY,
+                 "Got locality 1",
+                 "Could not get locality 1");
+
+    printf("Requesting access to locality 2; seizing locality.\n");
+
+    writeb(TIS_REG(2, TIS_REG_ACCESS), TIS_ACCESS_SEIZE);
+
+    check_access(1,
+                 0x80 | TIS_ACCESS_BEEN_SEIZED | TIS_ACCESS_ACTIVE_LOCALITY,
+                 0x80 | TIS_ACCESS_BEEN_SEIZED,
+                 "Access to locality 1 has been seized",
+                 "Access to locality 1 has not been properly seized");
+
+    check_access(2,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY,
+                 "Got locality 2",
+                 "Could not get locality 2");
+
+    printf("Setting request to use by locality 1\n");
+
+    writeb(TIS_REG(1, TIS_REG_ACCESS), TIS_ACCESS_REQUEST_USE);
+
+    check_access(2,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY| TIS_ACCESS_PENDING_REQUEST,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY| TIS_ACCESS_PENDING_REQUEST,
+                 "Locality 2 sees pending request by locality 1",
+                 "Locality 2 does not see pending request by locality 1");
+
+    check_access(1,
+                 0x80 | TIS_ACCESS_REQUEST_USE | TIS_ACCESS_ACTIVE_LOCALITY,
+                 0x80 | TIS_ACCESS_REQUEST_USE,
+                 "Locality 1 has request pending",
+                 "Locality 1 does not have request pending");
+
+    printf("Setting request to use by locality 0\n");
+
+    writeb(TIS_REG(0, TIS_REG_ACCESS), TIS_ACCESS_REQUEST_USE);
+
+    check_access(0,
+                 0x80 | TIS_ACCESS_REQUEST_USE | TIS_ACCESS_ACTIVE_LOCALITY,
+                 0x80 | TIS_ACCESS_REQUEST_USE,
+                 "Locality 0 has request pending",
+                 "Locality 0 does not have request pending");
+
+    check_access(2,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 "Locality 2 sees pending request by locality 1",
+                 "Locality 2 does not see pending request by locality 1");
+
+    printf("Setting request to use by locality 3\n");
+
+    writeb(TIS_REG(3, TIS_REG_ACCESS), TIS_ACCESS_REQUEST_USE);
+
+    check_access(3,
+                 0x80 | TIS_ACCESS_REQUEST_USE | TIS_ACCESS_ACTIVE_LOCALITY,
+                 0x80 | TIS_ACCESS_REQUEST_USE,
+                 "Locality 3 has request pending",
+                 "Locality 3 does not have request pending");
+
+    check_access(2,
+                 0x80|TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 0x80|TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 "Locality 2 sees pending request by localities 0, 1 & 3",
+                 "Locality 2 does not see pending request by localities "
+                 "0, 1 & 3");
+
+    printf("Releasing use by locality 2\n");
+
+    writeb(TIS_REG(2, TIS_REG_ACCESS), TIS_ACCESS_ACTIVE_LOCALITY);
+
+    check_access(2,
+                 0x80 | TIS_ACCESS_PENDING_REQUEST|TIS_ACCESS_ACTIVE_LOCALITY,
+                 0x80 | TIS_ACCESS_PENDING_REQUEST,
+                 "Locality 2 successfully relased usage",
+                 "Locality 2 did not completely release usage");
+
+    check_access(3,
+                 0x80|TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 0x80|TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 "Locality 3 is active and sees pending request by localities "
+                 "0 & 1",
+                 "Locality 3 does not see proper flags");
+
+    check_access(0,
+                 0x80|TIS_ACCESS_REQUEST_USE|TIS_ACCESS_PENDING_REQUEST|
+                      TIS_ACCESS_ACTIVE_LOCALITY,
+                 0x80|TIS_ACCESS_REQUEST_USE|TIS_ACCESS_PENDING_REQUEST,
+                 "Locality 0 has request pending and sees other pending request",
+                 "Locality 0 does not have request pending");
+
+    printf("Locality 1 drops request\n");
+
+    writeb(TIS_REG(1, TIS_REG_ACCESS), TIS_ACCESS_ACTIVE_LOCALITY);
+
+    printf("Releasing use by locality 3\n");
+
+    writeb(TIS_REG(3, TIS_REG_ACCESS), TIS_ACCESS_ACTIVE_LOCALITY);
+
+    check_access(3,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 0x80,
+                 "Locality 3 successfully relased usage",
+                 "Locality 3 did not completely release usage");
+
+    check_access(1,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 0x80,
+                 "Locality 1 successfully relased usage",
+                 "Locality 1 did not completely release usage");
+
+    check_access(0,
+                 0x80|TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 0x80|TIS_ACCESS_ACTIVE_LOCALITY,
+                 "Locality 0 is active",
+                 "Locality 0 is not avtive");
+}
+
+/*
+ * Test the seize flag. It is assumed that locality 0 is active.
+ * The test ends with locality 2 being active
+ */
+static void
+test_seize_locality_flag(void)
+{
+    printf("Requesting use by locality 1 using the SEIZE bit\n");
+
+    writeb(TIS_REG(1, TIS_REG_ACCESS), TIS_ACCESS_SEIZE);
+
+    check_access(0,
+                 0x80 | TIS_ACCESS_BEEN_SEIZED|TIS_ACCESS_ACTIVE_LOCALITY,
+                 0x80 | TIS_ACCESS_BEEN_SEIZED,
+                 "Access to locality 0 has been seized",
+                 "Access to locality 0 has not been properly seized");
+
+    check_access(1,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY,
+                 "Locality 1 successfully seized usage",
+                 "Locality 1 did not seize usage");
+
+    printf("Requesting use by locality 2 using the SEIZE bit\n");
+
+    writeb(TIS_REG(2, TIS_REG_ACCESS), TIS_ACCESS_SEIZE);
+
+    check_access(1,
+                 0x80 | TIS_ACCESS_BEEN_SEIZED | TIS_ACCESS_ACTIVE_LOCALITY,
+                 0x80 | TIS_ACCESS_BEEN_SEIZED,
+                 "Access to locality 1 has been seized",
+                 "Access to locality 1 has not been properly seized");
+
+    check_access(2,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 0x80 | TIS_ACCESS_ACTIVE_LOCALITY,
+                 "Locality 2 successfully seized usage",
+                 "Locality 1 did not seize usage");
+}
+
+#define ENABLED(L4,L3,L2,L1,L0) \
+  ((L4) << 4 | (L3) << 3 | (L2) << 2 | (L1) << 1 | (L0))
+
+static const u8 pcr_resets[] = {
+     ENABLED(1,1,1,1,1), /* PCR 16 */
+     ENABLED(1,0,0,0,0),
+     ENABLED(1,0,0,0,0),
+     ENABLED(1,0,0,0,0),
+     ENABLED(1,0,1,0,0),
+     ENABLED(0,0,1,0,0),
+     ENABLED(0,0,1,0,0),
+     ENABLED(1,1,1,1,1),
+};
+
+static const u8 pcr_extends[] = {
+     ENABLED(1,1,1,1,1), /* PCR 16 */
+     ENABLED(1,1,1,0,0),
+     ENABLED(1,1,1,0,0),
+     ENABLED(0,1,1,0,0),
+     ENABLED(0,1,1,1,0),
+     ENABLED(0,0,1,0,0),
+     ENABLED(0,0,1,0,0),
+     ENABLED(1,1,1,1,1),
+};
+
+
+static u32
+do_pcr_read(u32 pcrindex, u8 *result, u8 locty)
+{
+    u32 rc;
+
+    struct pttto_pcrread pttto;
+    struct pttti_pcrread pttti = {
+        .pttti = {
+            .reserved = locty,
+            .ipblength = sizeof(struct pttti_pcrread),
+            .opblength = sizeof(struct pttto_pcrread),
+        },
+        .req = {
+            .tag      = htons(0xc1),
+            .totlen   = htonl(sizeof(pttti.req)),
+            .ordinal  = htonl(TPM_ORD_PcrRead),
+            .pcrindex = htonl(pcrindex),
+        },
+    };
+    struct bregs regs;
+    regs.es  = FLATPTR_TO_SEG   (&pttti);
+    regs.edi = FLATPTR_TO_OFFSET(&pttti);
+    regs.ds  = FLATPTR_TO_SEG   (&pttto);
+    regs.esi = FLATPTR_TO_OFFSET(&pttto);
+    regs.eax = TCG_PassThroughToTPM;
+
+    tcpa_interrupt_handler32(&regs);
+
+    rc = regs.eax;
+
+    if (rc == 0) {
+        if ((pttto.pttto.opblength < TPM_RSP_HEADER_SIZE) ||
+            ntohs(pttto.rsp.tag) != 0xc4) {
+            rc = TCG_FATAL_COM_ERROR;
+        }
+    }
+
+    if (rc == 0)
+       memcpy(result, pttto.rsp.digest, sizeof(pttto.rsp.digest));
+
+    return rc;
+}
+
+
+static u32
+do_pcr_extend(u8 *hash, u32 pcrindex, u8 locty)
+{
+    u32 rc;
+
+    struct pttto_extend pttto;
+    struct pttti_extend pttti = {
+        .pttti = {
+            .reserved = locty,
+            .ipblength = sizeof(struct pttti_extend),
+            .opblength = sizeof(struct pttto_extend),
+        },
+        .req = {
+            .tag      = htons(0xc1),
+            .totlen   = htonl(sizeof(pttti.req)),
+            .ordinal  = htonl(TPM_ORD_Extend),
+            .pcrindex = htonl(pcrindex),
+        },
+    };
+    struct bregs regs;
+    regs.es  = FLATPTR_TO_SEG(&pttti);
+    regs.edi = FLATPTR_TO_OFFSET(&pttti);
+    regs.ds  = FLATPTR_TO_SEG(&pttto);
+    regs.esi = FLATPTR_TO_OFFSET(&pttto);
+    regs.eax = TCG_PassThroughToTPM;
+
+    memcpy(pttti.req.digest, hash, sizeof(pttti.req.digest));
+
+    tcpa_interrupt_handler32(&regs);
+
+    rc = regs.eax;
+
+    if (rc == 0) {
+        if ((pttto.pttto.opblength < TPM_RSP_HEADER_SIZE) ||
+            ntohs(pttto.rsp.tag) != 0xc4) {
+            rc = TCG_FATAL_COM_ERROR;
+        }
+    }
+
+    return rc;
+}
+
+
+static u32
+do_pcr_reset(u32 pcrindex, u8 locty)
+{
+    u32 rc;
+
+    struct pttto_pcrreset pttto;
+    struct pttti_pcrreset pttti = {
+        .pttti = {
+            .reserved  = locty,
+            .ipblength = sizeof(struct pttti_pcrreset),
+            .opblength = sizeof(struct pttto_pcrreset),
+        },
+        .req = {
+            .tag          = htons(0xc1),
+            .totlen       = htonl(sizeof(pttti.req)),
+            .ordinal      = htonl(TPM_ORD_PCR_Reset),
+            .sizeOfSelect = htons(3),
+        },
+    };
+    struct bregs regs;
+    regs.es  = FLATPTR_TO_SEG(&pttti);
+    regs.edi = FLATPTR_TO_OFFSET(&pttti);
+    regs.ds  = FLATPTR_TO_SEG(&pttto);
+    regs.esi = FLATPTR_TO_OFFSET(&pttto);
+    regs.eax = TCG_PassThroughToTPM;
+
+    pttti.req.pcrSelect[pcrindex >> 3] = 1 << (pcrindex & 0x7);
+
+    tcpa_interrupt_handler32(&regs);
+
+    rc = regs.eax;
+
+    if (rc == 0) {
+        if ((pttto.pttto.opblength < TPM_RSP_HEADER_SIZE) ||
+            ntohs(pttto.rsp.tag) != 0xc4) {
+            rc = TCG_FATAL_COM_ERROR;
+        }
+    }
+
+    return rc;
+}
+
+
+static void
+test_pcr_test(void)
+{
+    u32 pcr_num, res;
+    u8 locty;
+    u8 value_a[20], value_b[20], value_c[20];
+    u8 reset_pcr_0s[20] = { /* all PCRs; 17-22 if TOSPresent = true */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    };
+    u8 reset_pcr_1s[20] = { /* 17-22 if TOSPresent = false */
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    };
+    u8 value_ext[20] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+    int extended;
+    int tos_present = !readb(TIS_REG(0, TIS_REG_ACCESS)) &
+                            TIS_ACCESS_TPM_ESTABLISHMENT;
+
+    printf("Testing PCR Extend and Reset\n");
+
+    for (pcr_num = 16; pcr_num <= 23; pcr_num++) {
+
+        printf("PCR %d: ",pcr_num);
+
+        for (locty = 0; locty <= 4; locty++) {
+            if ((res = do_pcr_read(pcr_num, value_a, locty))) {
+                printf("!F0[%d] = 0x%08x", locty, res);
+                continue;
+            }
+            if ((res = do_pcr_extend(value_ext, pcr_num, locty))) {
+                printf("!F1[%d] = 0x%08x", locty, res);
+                continue;
+            }
+            if ((res = do_pcr_read(pcr_num, value_b, locty))) {
+                printf("!F2[%d] = 0x%08x", locty, res);
+                continue;
+            }
+            /* did the PCR change? */
+            if (memcmp(value_a, value_b, sizeof(value_a)) != 0) {
+                /* extend worked */
+                extended = 1;
+                if ((pcr_extends[pcr_num-16] & (1 << locty)) == 0)
+                    printf("!F3[%d] ", locty);
+                else
+                    printf(" P1[%d] ", locty);
+            } else {
+                extended = 0;
+                /* extend did not work */
+                if (pcr_extends[pcr_num-16] & (1 << locty))
+                    printf("!F4[%d] ", locty);
+                else
+                    printf(" P2[%d] ", locty);
+            }
+
+            if (!extended) {
+                /* Need to extend using locality 2; this always works */
+                if ((res = do_pcr_extend(value_ext, pcr_num, 2))) {
+                    printf("!F5[%d] = 0x%08x", locty, res);
+                    continue;
+                }
+            }
+
+            if ((res = do_pcr_reset(pcr_num, locty))) {
+                printf("!F6[%d] = 0x%08x", locty, res);
+                continue;
+            }
+            if (do_pcr_read(pcr_num, value_c, locty)) {
+                printf("!F7[%d] = 0x%08x", locty, res);
+                continue;
+            }
+            /* did reset work? */
+            if ((( pcr_num <= 16 ||
+                   pcr_num == 23 ||
+                  (pcr_num >= 17 && pcr_num <= 22 && tos_present)
+                 ) &&
+                  memcmp(value_c, reset_pcr_0s, sizeof(value_c)) == 0
+                ) ||
+                ( pcr_num >= 17 && pcr_num <= 22 && !tos_present &&
+                  memcmp(value_c, reset_pcr_1s, sizeof(value_c)) == 0
+                )
+               ) {
+                /* reset worked */
+                if ((pcr_resets[pcr_num-16] & (1 << locty)) == 0)
+                    printf("!F8[%d] ", locty);
+                else
+                    printf(" P3[%d] ", locty);
+            } else {
+                /* reset did not work */
+                if ((pcr_resets[pcr_num-16] & (1 << locty)))
+                    printf("!F9[%d] ", locty);
+                else
+                    printf(" P4[%d] ", locty);
+            }
+        }
+        printf("\n");
+    }
+}
+
+
+/* send a command to the TPM without waiting for the response;
+   the caller must have activate the given locality */
+static int
+send_command(u8 locty, const unsigned char *command, u32 cmd_length)
+{
+    u32 c;
+    u32 burst;
+
+    writeb(TIS_REG(locty, TIS_REG_STS), TIS_STS_COMMAND_READY);
+
+    if (tis_check_status(locty,
+                         TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY, 1000)) {
+        printf("Error: Could not bring the TPM "
+               "into ready state in locality %d\n", locty);
+        wait_for_keystroke();
+        return 1;
+    }
+
+    burst = readl(TIS_REG(locty, TIS_REG_STS)) >> 8;
+
+    for (c = 0; c < cmd_length && burst > 0; c++) {
+        writeb(TIS_REG(locty, TIS_REG_DATA_FIFO), command[c]);
+        burst--;
+    }
+
+    if (c != cmd_length) {
+        printf("Error: Could not write data into locality %d FIFO\n", locty);
+        wait_for_keystroke();
+        return 1;
+    }
+
+    writeb(TIS_REG(locty, TIS_REG_STS), TIS_STS_TPM_GO);
+
+    return 0;
+}
+
+
+unsigned char pcr_read_cmd[] = {
+    0x00, 0xc1, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
+    0x00, 0x15, 0x00, 0x00, 0x00, 0x0a
+};
+
+static void
+test_cmd_aborts(void)
+{
+    printf("Testing command aborts\n");
+
+    /* abort using COMMAND_READY flag */
+
+    tis_activate_locality(0);
+
+    if (send_command(0, pcr_read_cmd, sizeof(pcr_read_cmd))) {
+        printf("Error: Sending command did not work.\n");
+        wait_for_keystroke();
+    } else {
+        writeb(TIS_REG(0, TIS_REG_STS), TIS_STS_COMMAND_READY);
+
+        if (tis_check_status(0,
+                             TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY,
+                             1000)) {
+            printf("After abort, locality %d did not become ready in time.\n",
+                   0);
+        }
+    }
+
+    /* abort using the Seize flag by a higher locality */
+
+    writeb(TIS_REG(0, TIS_REG_ACCESS), TIS_ACCESS_BEEN_SEIZED);
+
+    if (send_command(0, pcr_read_cmd, sizeof(pcr_read_cmd))) {
+        printf("Error: Sending command did not work.\n");
+        wait_for_keystroke();
+    } else {
+        writeb(TIS_REG(1, TIS_REG_ACCESS), TIS_ACCESS_SEIZE);
+
+        if (tis_check_access(1,
+                             TIS_ACCESS_ACTIVE_LOCALITY,
+                             TIS_ACCESS_ACTIVE_LOCALITY,
+                             1000)) {
+            printf("Error: Aborting of locality %d command by locality %d "
+                   "using the SEIZE flag did not work.\n",
+                   0, 1);
+            wait_for_keystroke();
+        } else {
+            check_access(0,
+                         TIS_ACCESS_BEEN_SEIZED|TIS_ACCESS_ACTIVE_LOCALITY,
+                         TIS_ACCESS_BEEN_SEIZED,
+                         "Access to locality 0 has been seized",
+                         "Access to locality 0 has not been properly seized");
+
+            check_access(1,
+                         TIS_ACCESS_ACTIVE_LOCALITY,
+                         TIS_ACCESS_ACTIVE_LOCALITY,
+                         "Got locality 1",
+                         "Could not get locality 1");
+        }
+    }
+
+    /* abort using ACTIVE_LOCALITY flag */
+    tis_activate_locality(1);
+
+    /* put in request by locality 0 */
+    writeb(TIS_REG(0, TIS_REG_ACCESS), TIS_ACCESS_REQUEST_USE);
+
+    check_access(1,
+                 TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 TIS_ACCESS_ACTIVE_LOCALITY|TIS_ACCESS_PENDING_REQUEST,
+                 "Locality 1 sees pending request",
+                 "Locality 1 does not see pending request");
+
+    if (send_command(1, pcr_read_cmd, sizeof(pcr_read_cmd))) {
+        printf("Error: Sending command did not work.\n");
+        wait_for_keystroke();
+    } else {
+        writeb(TIS_REG(1, TIS_REG_ACCESS), TIS_ACCESS_ACTIVE_LOCALITY);
+
+        if (tis_check_access(0,
+                             TIS_ACCESS_ACTIVE_LOCALITY,
+                             TIS_ACCESS_ACTIVE_LOCALITY,
+                             1000)) {
+            printf("Error: Aborting of locality %d command "
+                   "using the ACTIVE_LOCALITY flag did not work.\n",
+                   1);
+            printf("access[0] : %02x\n", readb(TIS_REG(0, TIS_REG_ACCESS)));
+            printf("access[1] : %02x\n", readb(TIS_REG(1, TIS_REG_ACCESS)));
+            wait_for_keystroke();
+        } else {
+            check_access(1,
+                         TIS_ACCESS_ACTIVE_LOCALITY,
+                         0,
+                         "Access to locality 1 relinquished",
+                         "Access to locality 1 not relinquished");
+
+            check_access(0,
+                         TIS_ACCESS_ACTIVE_LOCALITY,
+                         TIS_ACCESS_ACTIVE_LOCALITY,
+                         "Got locality 0",
+                         "Could not get locality 0");
+        }
+    }
+}
+
+
+static int
+test_various(u8 locty)
+{
+    int i;
+
+    tis_activate_locality(locty);
+
+    printf("Putting locality %d in ready state.\n", locty);
+
+    writeb(TIS_REG(locty, TIS_REG_STS), TIS_STS_COMMAND_READY);
+
+    if (tis_check_status(locty,
+                         TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY, 1000)) {
+        printf("Error: Could not bring the TPM "
+               "into ready state in locality %d\n",locty);
+        wait_for_keystroke();
+        return 1;
+    }
+
+    printf("Reading data from FIFO. Expecting 0xff.\n");
+
+    if (readb(TIS_REG(locty, TIS_REG_DATA_FIFO)) != 0xff) {
+        printf("Error: Expected to 0xff from FIFO\n");
+        wait_for_keystroke();
+    }
+
+    printf("Writing a byte into the FIFO.\n");
+
+    writeb(TIS_REG(locty, TIS_REG_DATA_FIFO), pcr_read_cmd[0]);
+
+    if (tis_check_status(locty,
+                         TIS_STS_EXPECT, TIS_STS_EXPECT, 0)) {
+        printf("Error: TIS is not expecting data in locality %d\n",locty);
+        wait_for_keystroke();
+        return 1;
+    }
+
+    printf("Sending single byte to be processed.\n");
+
+    /* tpm will process the single byte */
+    writeb(TIS_REG(locty, TIS_REG_STS), TIS_STS_TPM_GO);
+
+    if (tis_check_status(locty,
+                         TIS_STS_EXPECT, 0, 0)) {
+        printf("Error: TIS is still expecting data in locality %d [2nd]\n",
+               locty);
+        wait_for_keystroke();
+        return 1;
+    }
+
+    printf("Checking for result.\n");
+
+    if (tis_check_status(locty,
+                         TIS_STS_DATA_AVAILABLE, TIS_STS_DATA_AVAILABLE,
+                         1000)) {
+        printf("Error: No data available in locality %d [2nd]\n",
+               locty);
+        wait_for_keystroke();
+        return 1;
+    }
+
+    printf("Putting locality %d in ready state.\n", locty);
+
+    writeb(TIS_REG(locty, TIS_REG_STS), TIS_STS_COMMAND_READY);
+
+    printf("Writing TPM_PcrRead command into FIFO.\n");
+
+    for (i = 0; i < sizeof(pcr_read_cmd); i++) {
+        if (i > 0 && tis_check_status(0, TIS_STS_EXPECT, TIS_STS_EXPECT, 0)) {
+            printf("Error: TIS is not expecting data anymore [%d/%d].\n",
+                   i,sizeof(pcr_read_cmd)-1);
+            readb(TIS_REG(locty, 0xf90));
+            wait_for_keystroke();
+        }
+        writeb(TIS_REG(locty, TIS_REG_DATA_FIFO), pcr_read_cmd[i]);
+    }
+
+    printf("Checking whether the TPM is still expecting data. "
+           "It should not.\n");
+
+    if (tis_check_status(locty,
+                         TIS_STS_EXPECT, 0, 0)) {
+        printf("Error: TIS is still expecting data in locality %d\n",
+               locty);
+        wait_for_keystroke();
+        return 1;
+    }
+
+    printf("Sending command to put locality %d into ready state.\n", locty);
+
+    writeb(TIS_REG(locty, TIS_REG_STS), TIS_STS_COMMAND_READY);
+
+    printf("Checking that locality %d is in ready state.\n", locty);
+
+    if (tis_check_status(locty,
+                         TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY, 1000)) {
+        printf("Error: Could not bring the TPM "
+               "into ready state in locality %d [2nd]\n", locty);
+        wait_for_keystroke();
+        return 1;
+    }
+
+    return 0;
+}
+
+
+void
+tis_test(int tpm_state)
+{
+    if (!CONFIG_TIS_TEST)
+        return;
+
+    test_active_locality_flag();
+
+    /* locality 0 is active */
+
+    test_seize_locality_flag();
+
+    /* locality 2 is active */
+
+    if (tpm_state == 0)
+        test_pcr_test();
+
+    test_cmd_aborts();
+
+    test_various(0);
+
+    tis_activate_locality(0);
+
+    printf("END OF TEST.\n");
+    wait_for_keystroke();
+}
Index: seabios/src/tis_test.h
===================================================================
--- /dev/null
+++ seabios/src/tis_test.h
@@ -0,0 +1,52 @@
+#ifndef TIS_TEST
+#define TIS_TEST
+
+#include "tcgbios.h"
+
+#define TPM_ORD_PCR_Reset       0x000000c8
+#define TPM_ORD_PcrRead         0x00000015
+
+void tis_test(int tpm_state);
+
+struct tpm_req_pcrread {
+    TPM_REQ_HEADER
+    u32    pcrindex;
+} PACKED;
+
+struct tpm_rsp_pcrread {
+    TPM_RSP_HEADER
+    u8     digest[SHA1_BUFSIZE];
+} PACKED;
+
+struct pttti_pcrread {
+    struct pttti pttti;
+    struct tpm_req_pcrread req;
+} PACKED;
+
+struct pttto_pcrread {
+    struct pttto pttto;
+    struct tpm_rsp_pcrread rsp;
+} PACKED;
+
+
+struct tpm_req_pcrreset {
+    TPM_REQ_HEADER
+    u16     sizeOfSelect;
+    u8      pcrSelect[3];
+} PACKED;
+
+struct tpm_rsp_pcrreset {
+    TPM_RSP_HEADER
+} PACKED;
+
+struct pttti_pcrreset {
+    struct pttti pttti;
+    struct tpm_req_pcrreset req;
+} PACKED;
+
+struct pttto_pcrreset {
+    struct pttto pttto;
+    struct tpm_rsp_pcrreset rsp;
+} PACKED;
+
+#endif /* TIS_TEST */
Index: seabios/src/Kconfig
===================================================================
--- seabios.orig/src/Kconfig
+++ seabios/src/Kconfig
@@ -330,6 +330,13 @@ menu "BIOS interfaces"
             Either you may use the TPM for SHA1 calculations or
             use the internal sha1 algorithm to do it (faster).
 
+    config TIS_TEST
+        depends on TCGBIOS
+        bool "TPM TIS test"
+        default n
+        help
+            Test cases for the TPM TIS interface
+
 endmenu
 
 menu "BIOS Tables"
