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

[Xen-changelog] [xen-unstable] [HVMLOADER][VTPM] Add support for a TCG ACPI table.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID d19b8542865b61ae884f49340ca5dbaddadc2973
# Parent  ca9b569ffb634604e6da477ab0b7a26004fe26bf
[HVMLOADER][VTPM] Add support for a TCG ACPI table.

The ACPI table is generated if the probing for the TIS interface
succeeds. I cleaned up the ACPI signatures in acpi2_0.h to be more
readable.

The specification for the layout of these ACPI tables can be found here:
https://www.trustedcomputinggroup.org/groups/server/TCG_ACPIGeneralSpecification_1-00_1-00_FINAL.pdf

Extensions to the Bochs BIOS that use these ACPI extensions will follow.

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>
---
 tools/firmware/hvmloader/acpi/acpi2_0.h |   34 +++-
 tools/firmware/hvmloader/acpi_utils.c   |  219 +++++++++++++++++++++-----------
 tools/firmware/hvmloader/util.c         |   51 +++++++
 tools/firmware/hvmloader/util.h         |    4 
 4 files changed, 230 insertions(+), 78 deletions(-)

diff -r ca9b569ffb63 -r d19b8542865b tools/firmware/hvmloader/acpi/acpi2_0.h
--- a/tools/firmware/hvmloader/acpi/acpi2_0.h   Fri Nov 17 10:05:12 2006 +0000
+++ b/tools/firmware/hvmloader/acpi/acpi2_0.h   Fri Nov 17 10:24:22 2006 +0000
@@ -34,6 +34,11 @@ typedef   signed long int64_t;
 
 #include <xen/xen.h>
 
+#define ASCII32(a,b,c,d)         \
+    (((a) <<  0) | ((b) <<  8) | ((c) << 16) | ((d) << 24))
+#define ASCII64(a,b,c,d,e,f,g,h) \
+    (((uint64_t)ASCII32(a,b,c,d)) | (((uint64_t)ASCII32(e,f,g,h)) << 32))
+
 #pragma pack (1)
 
 /*
@@ -52,7 +57,7 @@ struct acpi_header {
 };
 
 #define ACPI_OEM_ID             {'I','N','T','E','L',' '}
-#define ACPI_OEM_TABLE_ID       0x544244   /* "TBD" */
+#define ACPI_OEM_TABLE_ID       ASCII32(' ','T','B','D')
 #define ACPI_OEM_REVISION       0x00000002
 #define ACPI_CREATOR_ID         0x00       /* TBD */
 #define ACPI_CREATOR_REVISION   0x00000002
@@ -126,6 +131,20 @@ struct acpi_20_xsdt {
     uint64_t entry[ACPI_MAX_NUM_TABLES];
 };
 #define ACPI_2_0_XSDT_REVISION 0x01
+
+/*
+ * TCG Hardware Interface Table (TCPA)
+ */
+
+typedef struct _ACPI_2_0_TCPA_CLIENT {
+    struct acpi_header header;
+    uint16_t PlatformClass;
+    uint32_t LAML;
+    uint64_t LASA;
+} ACPI_2_0_TCPA_CLIENT;
+
+#define ACPI_2_0_TCPA_REVISION 0x02
+#define ACPI_2_0_TCPA_LAML_SIZE (64*1024)
 
 /*
  * Fixed ACPI Description Table Structure (FADT).
@@ -297,12 +316,13 @@ struct acpi_20_madt {
 /*
  * Table Signatures.
  */
-#define ACPI_2_0_RSDP_SIGNATURE 0x2052545020445352LL /* "RSD PTR " */
-#define ACPI_2_0_FACS_SIGNATURE 0x53434146 /* "FACS" */
-#define ACPI_2_0_FADT_SIGNATURE 0x50434146 /* "FADT" */
-#define ACPI_2_0_MADT_SIGNATURE 0x43495041 /* "APIC" */
-#define ACPI_2_0_RSDT_SIGNATURE 0x54445352 /* "RSDT" */
-#define ACPI_2_0_XSDT_SIGNATURE 0x54445358 /* "XSDT" */
+#define ACPI_2_0_RSDP_SIGNATURE ASCII64('R','S','D',' ','P','T','R',' ')
+#define ACPI_2_0_FACS_SIGNATURE ASCII32('F','A','C','S')
+#define ACPI_2_0_FADT_SIGNATURE ASCII32('F','A','C','P')
+#define ACPI_2_0_MADT_SIGNATURE ASCII32('A','P','I','C')
+#define ACPI_2_0_RSDT_SIGNATURE ASCII32('R','S','D','T')
+#define ACPI_2_0_XSDT_SIGNATURE ASCII32('X','S','D','T')
+#define ACPI_2_0_TCPA_SIGNATURE ASCII32('T','C','P','A')
 
 #pragma pack ()
 
diff -r ca9b569ffb63 -r d19b8542865b tools/firmware/hvmloader/acpi_utils.c
--- a/tools/firmware/hvmloader/acpi_utils.c     Fri Nov 17 10:05:12 2006 +0000
+++ b/tools/firmware/hvmloader/acpi_utils.c     Fri Nov 17 10:24:22 2006 +0000
@@ -23,8 +23,11 @@
 #include "acpi/acpi2_0.h"
 #include "acpi_utils.h"
 #include "util.h"
+#include <xen/hvm/e820.h>
 
 static int acpi_rsdt_add_entry_pointer(unsigned char *acpi_start,
+                                       unsigned char *entry);
+static int acpi_xsdt_add_entry_pointer(unsigned char *acpi_start,
                                        unsigned char *entry);
 static unsigned char *acpi_xsdt_add_entry(unsigned char *acpi_start,
                                           unsigned char **freemem,
@@ -34,45 +37,78 @@ static unsigned char *acpi_xsdt_add_entr
 
 void set_checksum(void *start, int checksum_offset, int len)
 {
-       unsigned char sum = 0;
-       unsigned char *ptr;
-
-       ptr = start;
-       ptr[checksum_offset] = 0;
-       while (len--)
-               sum += *ptr++;
-
-       ptr = start;
-       ptr[checksum_offset] = -sum;
+    unsigned char sum = 0;
+    unsigned char *ptr;
+
+    ptr = start;
+    ptr[checksum_offset] = 0;
+    while ( len-- )
+        sum += *ptr++;
+
+    ptr = start;
+    ptr[checksum_offset] = -sum;
 }
 
 
 #include "acpi_ssdt_tpm.h"
-static int acpi_tpm_tis_probe(unsigned char *acpi_start,
-                              unsigned char **freemem,
-                              unsigned char *limit)
-{
-       int success = 1; /* not successful means 'out of memory' */
-       unsigned char *addr;
-       /* check TPM_DID, TPM_VID, TPM_RID in ioemu/hw/tpm_tis.c */
-       uint16_t tis_did_vid_rid[] = {0x0001, 0x0001, 0x0001};
-
-       /* probe for TIS interface ... */
-       if (memcmp((char *)(0xFED40000 + 0xF00),
-                  tis_did_vid_rid,
-                  sizeof(tis_did_vid_rid)) == 0) {
-               puts("TIS is available\n");
-               addr = acpi_xsdt_add_entry(acpi_start, freemem, limit,
-                                          AmlCode_TPM, sizeof(AmlCode_TPM));
-               if (addr == NULL)
-                       success = 0;
-               else {
-                       /* legacy systems need an RSDT entry */
-                       acpi_rsdt_add_entry_pointer(acpi_start,
-                                                   addr);
-               }
-       }
-       return success;
+static void acpi_tpm_tis_probe(unsigned char *acpi_start,
+                               unsigned char **freemem,
+                               unsigned char *limit)
+{
+    unsigned char *addr;
+    ACPI_2_0_TCPA_CLIENT *tcpa;
+    /* check TPM_DID, TPM_VID, TPM_RID in ioemu/hw/tpm_tis.c */
+    uint16_t tis_did_vid_rid[] = {0x0001, 0x0001, 0x0001};
+    static const ACPI_2_0_TCPA_CLIENT Tcpa = {
+        .header = {
+            .signature = ACPI_2_0_TCPA_SIGNATURE,
+            .length    = sizeof(ACPI_2_0_TCPA_CLIENT),
+            .revision  = ACPI_2_0_TCPA_REVISION,
+            .oem_id    = {'I', 'B', 'M', ' ', ' ', ' '},
+            .oem_table_id = ASCII64(' ', ' ', ' ', ' ', ' ', 'x', 'e', 'n'),
+            .oem_revision = 1,
+            .creator_id   = ASCII32('I', 'B', 'M', ' '),
+            .creator_revision = 1,
+        }
+    };
+
+    /* probe for TIS interface ... */
+    if ( memcmp((char *)(0xFED40000 + 0xF00),
+                tis_did_vid_rid,
+                sizeof(tis_did_vid_rid)) != 0 )
+        return;
+
+    puts("TIS is available\n");
+    addr = acpi_xsdt_add_entry(acpi_start, freemem, limit,
+                               AmlCode_TPM, sizeof(AmlCode_TPM));
+    if ( addr == NULL )
+        return;
+
+    /* legacy systems need an RSDT entry */
+    acpi_rsdt_add_entry_pointer(acpi_start, addr);
+
+    /* add ACPI TCPA table */
+    addr = acpi_xsdt_add_entry(acpi_start, freemem, limit,
+                               (unsigned char *)&Tcpa,
+                               sizeof(Tcpa));
+    if ( addr == NULL )
+        return;
+
+    tcpa = (ACPI_2_0_TCPA_CLIENT *)addr;
+    tcpa->LASA = e820_malloc(
+        ACPI_2_0_TCPA_LAML_SIZE, E820_RESERVED, (uint32_t)~0);
+    if ( tcpa->LASA )
+    {
+        tcpa->LAML = ACPI_2_0_TCPA_LAML_SIZE;
+        memset((char *)(unsigned long)tcpa->LASA,
+               0x0,
+               tcpa->LAML);
+        set_checksum(tcpa,
+                     FIELD_OFFSET(struct acpi_header, checksum),
+                     tcpa->header.length);
+    }
+
+    acpi_rsdt_add_entry_pointer(acpi_start, addr);
 }
 
 
@@ -95,17 +131,20 @@ struct acpi_20_rsdt *acpi_rsdt_get(unsig
     struct acpi_20_rsdt *rsdt;
 
     rsdp = (struct acpi_20_rsdp *)(acpi_start + sizeof(struct acpi_20_facs));
-    if (rsdp->signature != ACPI_2_0_RSDP_SIGNATURE) {
+    if ( rsdp->signature != ACPI_2_0_RSDP_SIGNATURE )
+    {
         puts("Bad RSDP signature\n");
         return NULL;
     }
 
     rsdt = (struct acpi_20_rsdt *)
         (acpi_start + rsdp->rsdt_address - ACPI_PHYSICAL_ADDRESS);
-    if (rsdt->header.signature != ACPI_2_0_RSDT_SIGNATURE) {
+    if ( rsdt->header.signature != ACPI_2_0_RSDT_SIGNATURE )
+    {
         puts("Bad RSDT signature\n");
         return NULL;
     }
+
     return rsdt;
 }
 
@@ -119,17 +158,20 @@ static int acpi_rsdt_add_entry_pointer(u
     int found = 0;
     int i = 0;
 
-    /* get empty slot in the RSDT table */
-    while (i < ACPI_MAX_NUM_TABLES) {
-        if (rsdt->entry[i] == 0) {
-            found = 1;
-            break;
-        }
-        i++;
-    }
-
-    if (found) {
-        rsdt->entry[i] = (uint64_t)(long)entry;
+    /* Find an empty slot in the RSDT table. */
+    while ( i < ACPI_MAX_NUM_TABLES )
+    {
+        if ( rsdt->entry[i] == 0 )
+        {
+            found = 1;
+            break;
+        }
+        i++;
+    }
+
+    if ( found )
+    {
+        rsdt->entry[i] = (uint64_t)(unsigned long)entry;
         rsdt->header.length =
             sizeof(struct acpi_header) +
             (i + 1) * sizeof(uint64_t);
@@ -141,25 +183,62 @@ static int acpi_rsdt_add_entry_pointer(u
     return found;
 }
 
-/* Get the XSDT table */
+/* Get the XSDT table. */
 struct acpi_20_xsdt *acpi_xsdt_get(unsigned char *acpi_start)
 {
     struct acpi_20_rsdp *rsdp;
     struct acpi_20_xsdt *xsdt;
 
     rsdp = (struct acpi_20_rsdp *)(acpi_start + sizeof(struct acpi_20_facs));
-    if (rsdp->signature != ACPI_2_0_RSDP_SIGNATURE) {
+    if ( rsdp->signature != ACPI_2_0_RSDP_SIGNATURE )
+    {
         puts("Bad RSDP signature\n");
         return NULL;
     }
 
     xsdt = (struct acpi_20_xsdt *)
         (acpi_start + rsdp->xsdt_address - ACPI_PHYSICAL_ADDRESS);
-    if (xsdt->header.signature != ACPI_2_0_XSDT_SIGNATURE) {
+    if ( xsdt->header.signature != ACPI_2_0_XSDT_SIGNATURE )
+    {
         puts("Bad XSDT signature\n");
         return NULL;
     }
     return xsdt;
+}
+
+/*
+ * Add an entry to the XSDT table given the pointer to the entry.
+ */
+static int acpi_xsdt_add_entry_pointer(unsigned char *acpi_start,
+                                       unsigned char *entry)
+{
+    struct acpi_20_xsdt *xsdt = acpi_xsdt_get(acpi_start);
+    int found = 0;
+    int i = 0;
+
+    /* Find an empty slot in the XSDT table. */
+    while ( i < ACPI_MAX_NUM_TABLES )
+    {
+        if ( xsdt->entry[i] == 0 )
+        {
+            found = 1;
+            break;
+        }
+        i++;
+    }
+
+    if ( found )
+    {
+        xsdt->entry[i] = (uint64_t)(unsigned long)entry;
+        xsdt->header.length =
+            sizeof(struct acpi_header) +
+            (i + 1) * sizeof(uint64_t);
+        set_checksum(xsdt,
+                     FIELD_OFFSET(struct acpi_header, checksum),
+                     xsdt->header.length);
+    }
+
+    return found;
 }
 
 /*
@@ -177,31 +256,29 @@ static unsigned char *acpi_xsdt_add_entr
     int found = 0, i = 0;
     unsigned char *addr = NULL;
 
-    /* get empty slot in the Xsdt table */
-    while (i < ACPI_MAX_NUM_TABLES) {
-        if (xsdt->entry[i] == 0) {
-            found = 1;
-            break;
-        }
-        i++;
-    }
-
-    if (found) {
+    /* Check for an empty slot in the Xsdt table. */
+    while ( i < ACPI_MAX_NUM_TABLES )
+    {
+        if ( xsdt->entry[i] == 0 )
+        {
+            found = 1;
+            break;
+        }
+        i++;
+    }
+
+    if ( found )
+    {
         /* memory below hard limit ? */
         if (*freemem + table_size <= limit) {
             puts("Copying SSDT entry!\n");
             addr = *freemem;
             memcpy(addr, table, table_size);
-            xsdt->entry[i] = (uint64_t)(long)addr;
             *freemem += table_size;
-            /* update the XSDT table */
-            xsdt->header.length =
-                sizeof(struct acpi_header) +
-                (i + 1) * sizeof(uint64_t);
-            set_checksum(xsdt,
-                         FIELD_OFFSET(struct acpi_header, checksum),
-                         xsdt->header.length);
-        }
-    }
+
+            acpi_xsdt_add_entry_pointer(acpi_start, addr);
+        }
+    }
+
     return addr;
 }
diff -r ca9b569ffb63 -r d19b8542865b tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c   Fri Nov 17 10:05:12 2006 +0000
+++ b/tools/firmware/hvmloader/util.c   Fri Nov 17 10:24:22 2006 +0000
@@ -90,6 +90,23 @@ void *memcpy(void *dest, const void *src
        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;
+}
+
+
+
+
 void puts(const char *s)
 {
        while (*s)
@@ -229,3 +246,37 @@ uuid_to_string(char *dest, uint8_t *uuid
        }
        *p = 0;
 }
+
+#include <xen/hvm/e820.h>
+#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET)
+#define E820_MAP    ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET))
+uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask)
+{
+       uint64_t addr = 0;
+       int c = *E820_MAP_NR - 1;
+       struct e820entry *e820entry = (struct e820entry *)E820_MAP;
+
+       while (c >= 0) {
+               if (e820entry[c].type  == E820_RAM     &&
+                   (e820entry[c].addr & (~mask)) == 0 &&
+                   e820entry[c].size >= size) {
+                       addr = e820entry[c].addr;
+                       if (e820entry[c].size != size) {
+                               (*E820_MAP_NR)++;
+                               memmove(&e820entry[c+1],
+                                       &e820entry[c],
+                                       (*E820_MAP_NR - c) *
+                                           sizeof(struct e820entry));
+                               e820entry[c].size -= size;
+                               addr += e820entry[c].size;
+                               c++;
+                       }
+                       e820entry[c].addr = addr;
+                       e820entry[c].size = size;
+                       e820entry[c].type = type;
+                       break;
+               }
+               c--;
+       }
+        return addr;
+}
diff -r ca9b569ffb63 -r d19b8542865b tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h   Fri Nov 17 10:05:12 2006 +0000
+++ b/tools/firmware/hvmloader/util.h   Fri Nov 17 10:24:22 2006 +0000
@@ -22,6 +22,7 @@ unsigned strlen(const char *s);
 unsigned strlen(const char *s);
 int memcmp(const void *s1, const void *s2, unsigned n);
 void *memcpy(void *dest, const void *src, unsigned n);
+void *memmove(void *dest, const void *src, unsigned n);
 void *memset(void *s, int c, unsigned n);
 char *itoa(char *a, unsigned int i);
 
@@ -38,4 +39,7 @@ void uuid_to_string(char *dest, uint8_t 
 /* Debug output */
 void puts(const char *s);
 
+/* Allocate region of specified type in the e820 table. */
+uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask);
+
 #endif /* __HVMLOADER_UTIL_H__ */

_______________________________________________
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®.