This patch provides ACPI support for the TPM device. It probes for the TPM
device and only if a TPM device is found then the TPM's SSDT and TCPA table
are created. This patch also connects them to the RSDT.

Since the logging area in the TCPA table requires 64kb, the memory reserved
for ACPI tables (config.h) is increased to 96kb in case CONFIG_TCGBIOS
is enabled.

This patch requires the subsequent patch for it to compile and work.

The IRQ description in the TPM's SSDT is commented since it will be
'safer' to run the TPM in polling mode - the Linux TPM TIS driver for example
has too many issues when run in interrupt mode.

The description of the TCPA (client) table can be found here:

http://www.trustedcomputinggroup.org/resources/server_work_group_acpi_general_specification_version_10

The compiled SSDT description is also part of this patch.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>

---
 Makefile              |    9 ++++++++-
 src/acpi-tpm-ssdt.dsl |   22 ++++++++++++++++++++++
 src/acpi-tpm-ssdt.hex |   34 ++++++++++++++++++++++++++++++++++
 src/acpi.c            |   41 +++++++++++++++++++++++++++++++++++++++++
 src/acpi.h            |   20 ++++++++++++++++++++
 src/config.h          |    6 +++++-
 6 files changed, 130 insertions(+), 2 deletions(-)

Index: seabios/src/acpi-tpm-ssdt.dsl
===================================================================
--- /dev/null
+++ seabios/src/acpi-tpm-ssdt.dsl
@@ -0,0 +1,22 @@
+DefinitionBlock (
+    "acpi-tpm-ssdt.aml",// Output Filename
+    "SSDT",             // Signature
+    0x01,               // SSDT Compliance Revision
+    "BXPC",             // OEMID
+    "BXSSDT",           // TABLE ID
+    0x1                 // OEM Revision
+    )
+{
+    /* TPM with emulated TPM TIS interface */
+    Device (TPM) {
+        Name (_HID, EisaID ("PNP0C31"))
+        Name (_CRS, ResourceTemplate ()
+        {
+                Memory32Fixed (ReadWrite, 0xFED40000, 0x00005000)
+                //IRQNoFlags () {11}
+        })
+        Method (_STA, 0, NotSerialized) {
+            Return (0x0F)
+        }
+    }
+}
Index: seabios/src/acpi-tpm-ssdt.hex
===================================================================
--- /dev/null
+++ seabios/src/acpi-tpm-ssdt.hex
@@ -0,0 +1,34 @@
+/*
+ * 
+ * Intel ACPI Component Architecture
+ * ASL Optimizing Compiler version 20101013-64 [Nov 21 2010]
+ * Copyright (c) 2000 - 2010 Intel Corporation
+ * 
+ * Compilation of "out/.dsl.i" - Sun Mar 13 20:44:32 2011
+ * 
+ * C source code output
+ * AML code block contains 0x93 bytes
+ *
+ */
+unsigned char AmlCode_TPM[] =
+{
+    0x53,0x53,0x44,0x54,0x93,0x00,0x00,0x00,  /* 00000000    "SSDT...." */
+    0x01,0xC3,0x42,0x58,0x50,0x43,0x00,0x00,  /* 00000008    "..BXPC.." */
+    0x42,0x58,0x53,0x53,0x44,0x54,0x00,0x00,  /* 00000010    "BXSSDT.." */
+    0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
+    0x13,0x10,0x10,0x20,0x5B,0x82,0x4D,0x06,  /* 00000020    "... [.M." */
+    0x54,0x50,0x4D,0x5F,0x08,0x5F,0x48,0x49,  /* 00000028    "TPM_._HI" */
+    0x44,0x0C,0x41,0xD0,0x0C,0x31,0x08,0x5F,  /* 00000030    "D.A..1._" */
+    0x53,0x54,0x52,0x11,0x33,0x0A,0x30,0x45,  /* 00000038    "STR.3.0E" */
+    0x00,0x6D,0x00,0x75,0x00,0x6C,0x00,0x61,  /* 00000040    ".m.u.l.a" */
+    0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x20,  /* 00000048    ".t.e.d. " */
+    0x00,0x54,0x00,0x50,0x00,0x4D,0x00,0x20,  /* 00000050    ".T.P.M. " */
+    0x00,0x54,0x00,0x49,0x00,0x53,0x00,0x20,  /* 00000058    ".T.I.S. " */
+    0x00,0x64,0x00,0x65,0x00,0x76,0x00,0x69,  /* 00000060    ".d.e.v.i" */
+    0x00,0x63,0x00,0x65,0x00,0x00,0x00,0x08,  /* 00000068    ".c.e...." */
+    0x5F,0x43,0x52,0x53,0x11,0x14,0x0A,0x11,  /* 00000070    "_CRS...." */
+    0x86,0x09,0x00,0x01,0x00,0x00,0xD4,0xFE,  /* 00000078    "........" */
+    0x00,0x50,0x00,0x00,0x22,0x00,0x08,0x79,  /* 00000080    ".P.."..y" */
+    0x00,0x14,0x09,0x5F,0x53,0x54,0x41,0x00,  /* 00000088    "..._STA." */
+    0xA4,0x0A,0x0F                            /* 00000090    "..."      */
+};
Index: seabios/Makefile
===================================================================
--- seabios.orig/Makefile
+++ seabios/Makefile
@@ -192,13 +192,20 @@ $(OUT)vgabios.bin: $(OUT)vgabios.bin.raw
 	$(Q)./tools/buildrom.py $< $@
 
 ####### dsdt build rules
+src/acpi-tpm-ssdt.hex: src/acpi-tpm-ssdt.dsl
+	@echo "Compiling TPM SSDT"
+	$(Q)cpp -P $< > $(OUT)$*.dsl.i
+	$(Q)iasl -tc -p $(OUT)$* $(OUT)$*.dsl.i
+	$(Q)cp $(OUT)$*.hex $@
+	$(Q)sed -i 's/AmlCode/AmlCode_TPM/' $@
+
 src/%.hex: src/%.dsl
 	@echo "Compiling DSDT"
 	$(Q)cpp -P $< > $(OUT)$*.dsl.i
 	$(Q)iasl -tc -p $(OUT)$* $(OUT)$*.dsl.i
 	$(Q)cp $(OUT)$*.hex $@
 
-$(OUT)ccode32flat.o: src/acpi-dsdt.hex
+$(OUT)ccode32flat.o: src/acpi-dsdt.hex src/acpi-tpm-ssdt.hex
 
 ####### Kconfig rules
 export HOSTCC             := $(CC)
Index: seabios/src/acpi.c
===================================================================
--- seabios.orig/src/acpi.c
+++ seabios/src/acpi.c
@@ -13,6 +13,8 @@
 #include "pci_regs.h" // PCI_INTERRUPT_LINE
 #include "paravirt.h"
 #include "dev-i440fx.h" // piix4_fadt_init
+#include "acpi-tpm-ssdt.hex"
+#include "tcgbios.h" // has_working_tpm
 
 /****************************************************/
 /* ACPI tables init */
@@ -586,6 +588,39 @@ static const struct pci_device_id acpi_f
     PCI_DEVICE_END,
 };
 
+
+static u32 add_tpm_device(void **tpm_addr, void **tcpa_addr)
+{
+    struct tcpa_descriptor_rev2 *tcpa;
+
+    *tpm_addr = NULL;
+    *tcpa_addr = NULL;
+
+    if (has_working_tpm()) {
+        u32 laml = 64 * 1024;
+        *tpm_addr = malloc_high(sizeof(AmlCode_TPM));
+
+        tcpa = malloc_high(sizeof(*tcpa) + laml);
+        if (!tcpa || !*tpm_addr) {
+            warn_noalloc();
+            return 1;
+        }
+
+        if (*tpm_addr)
+            memcpy(*tpm_addr, AmlCode_TPM, sizeof(AmlCode_TPM));
+
+        memset(tcpa, 0x0, sizeof(*tcpa) + laml);
+        u64 lasa = (u32)tcpa + sizeof(*tcpa);
+
+        tcpa->laml = laml;
+        tcpa->lasa = lasa;
+        build_header((void*)tcpa, TCPA_SIGNATURE, sizeof(*tcpa), 2);
+
+        *tcpa_addr = tcpa;
+    }
+    return 0;
+}
+
 struct rsdp_descriptor *RsdpAddr;
 
 #define MAX_ACPI_TABLES 20
@@ -642,6 +677,12 @@ acpi_bios_init(void)
         }
     }
 
+    void *tcpa, *tpm;
+    if (add_tpm_device(&tpm, &tcpa))
+        return;
+    ACPI_INIT_TABLE(tpm);
+    ACPI_INIT_TABLE(tcpa);
+
     struct rsdt_descriptor_rev1 *rsdt;
     size_t rsdt_len = sizeof(*rsdt) + sizeof(u32) * tbl_idx;
     rsdt = malloc_high(rsdt_len);
Index: seabios/src/acpi.h
===================================================================
--- seabios.orig/src/acpi.h
+++ seabios/src/acpi.h
@@ -98,4 +98,24 @@ struct fadt_descriptor_rev1
 #endif
 } PACKED;
 
+
+struct rsdt_descriptor {
+    ACPI_TABLE_HEADER_DEF
+    u32 entry[1];
+} PACKED;
+
+#define TCPA_SIGNATURE 0x41504354
+struct tcpa_descriptor_rev2
+{
+    ACPI_TABLE_HEADER_DEF
+    u16  platform_class;
+    u32  laml;
+    u64  lasa;
+} PACKED;
+
+/* TCPA ACPI definitions */
+#define TCPA_ACPI_CLASS_CLIENT          0
+#define TCPA_ACPI_CLASS_SERVER          1
+
+
 #endif // acpi.h
Index: seabios/src/config.h
===================================================================
--- seabios.orig/src/config.h
+++ seabios/src/config.h
@@ -26,7 +26,11 @@
 // Space to reserve in f-segment for dynamic allocations
 #define CONFIG_MAX_BIOSTABLE 2048
 // Space to reserve in high-memory for tables
-#define CONFIG_MAX_HIGHTABLE (64*1024)
+#if CONFIG_TCGBIOS
+# define CONFIG_MAX_HIGHTABLE (96*1024)
+#else
+# define CONFIG_MAX_HIGHTABLE (64*1024)
+#endif
 // Largest supported externaly facing drive id
 #define CONFIG_MAX_EXTDRIVE 16
 


