# 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
|