direct-io.hg

changeset 12479:d19b8542865b

[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@us.ibm.com>
author kfraser@localhost.localdomain
date Fri Nov 17 10:24:22 2006 +0000 (2006-11-17)
parents ca9b569ffb63
children 6a26f49d3b16
files tools/firmware/hvmloader/acpi/acpi2_0.h tools/firmware/hvmloader/acpi_utils.c tools/firmware/hvmloader/util.c tools/firmware/hvmloader/util.h
line diff
     1.1 --- a/tools/firmware/hvmloader/acpi/acpi2_0.h	Fri Nov 17 10:05:12 2006 +0000
     1.2 +++ b/tools/firmware/hvmloader/acpi/acpi2_0.h	Fri Nov 17 10:24:22 2006 +0000
     1.3 @@ -34,6 +34,11 @@ typedef   signed long int64_t;
     1.4  
     1.5  #include <xen/xen.h>
     1.6  
     1.7 +#define ASCII32(a,b,c,d)         \
     1.8 +    (((a) <<  0) | ((b) <<  8) | ((c) << 16) | ((d) << 24))
     1.9 +#define ASCII64(a,b,c,d,e,f,g,h) \
    1.10 +    (((uint64_t)ASCII32(a,b,c,d)) | (((uint64_t)ASCII32(e,f,g,h)) << 32))
    1.11 +
    1.12  #pragma pack (1)
    1.13  
    1.14  /*
    1.15 @@ -52,7 +57,7 @@ struct acpi_header {
    1.16  };
    1.17  
    1.18  #define ACPI_OEM_ID             {'I','N','T','E','L',' '}
    1.19 -#define ACPI_OEM_TABLE_ID       0x544244   /* "TBD" */
    1.20 +#define ACPI_OEM_TABLE_ID       ASCII32(' ','T','B','D')
    1.21  #define ACPI_OEM_REVISION       0x00000002
    1.22  #define ACPI_CREATOR_ID         0x00       /* TBD */
    1.23  #define ACPI_CREATOR_REVISION   0x00000002
    1.24 @@ -128,6 +133,20 @@ struct acpi_20_xsdt {
    1.25  #define ACPI_2_0_XSDT_REVISION 0x01
    1.26  
    1.27  /*
    1.28 + * TCG Hardware Interface Table (TCPA)
    1.29 + */
    1.30 +
    1.31 +typedef struct _ACPI_2_0_TCPA_CLIENT {
    1.32 +    struct acpi_header header;
    1.33 +    uint16_t PlatformClass;
    1.34 +    uint32_t LAML;
    1.35 +    uint64_t LASA;
    1.36 +} ACPI_2_0_TCPA_CLIENT;
    1.37 +
    1.38 +#define ACPI_2_0_TCPA_REVISION 0x02
    1.39 +#define ACPI_2_0_TCPA_LAML_SIZE (64*1024)
    1.40 +
    1.41 +/*
    1.42   * Fixed ACPI Description Table Structure (FADT).
    1.43   */
    1.44  struct acpi_20_fadt {
    1.45 @@ -297,12 +316,13 @@ struct acpi_20_madt {
    1.46  /*
    1.47   * Table Signatures.
    1.48   */
    1.49 -#define ACPI_2_0_RSDP_SIGNATURE 0x2052545020445352LL /* "RSD PTR " */
    1.50 -#define ACPI_2_0_FACS_SIGNATURE 0x53434146 /* "FACS" */
    1.51 -#define ACPI_2_0_FADT_SIGNATURE 0x50434146 /* "FADT" */
    1.52 -#define ACPI_2_0_MADT_SIGNATURE 0x43495041 /* "APIC" */
    1.53 -#define ACPI_2_0_RSDT_SIGNATURE 0x54445352 /* "RSDT" */
    1.54 -#define ACPI_2_0_XSDT_SIGNATURE 0x54445358 /* "XSDT" */
    1.55 +#define ACPI_2_0_RSDP_SIGNATURE ASCII64('R','S','D',' ','P','T','R',' ')
    1.56 +#define ACPI_2_0_FACS_SIGNATURE ASCII32('F','A','C','S')
    1.57 +#define ACPI_2_0_FADT_SIGNATURE ASCII32('F','A','C','P')
    1.58 +#define ACPI_2_0_MADT_SIGNATURE ASCII32('A','P','I','C')
    1.59 +#define ACPI_2_0_RSDT_SIGNATURE ASCII32('R','S','D','T')
    1.60 +#define ACPI_2_0_XSDT_SIGNATURE ASCII32('X','S','D','T')
    1.61 +#define ACPI_2_0_TCPA_SIGNATURE ASCII32('T','C','P','A')
    1.62  
    1.63  #pragma pack ()
    1.64  
     2.1 --- a/tools/firmware/hvmloader/acpi_utils.c	Fri Nov 17 10:05:12 2006 +0000
     2.2 +++ b/tools/firmware/hvmloader/acpi_utils.c	Fri Nov 17 10:24:22 2006 +0000
     2.3 @@ -23,9 +23,12 @@
     2.4  #include "acpi/acpi2_0.h"
     2.5  #include "acpi_utils.h"
     2.6  #include "util.h"
     2.7 +#include <xen/hvm/e820.h>
     2.8  
     2.9  static int acpi_rsdt_add_entry_pointer(unsigned char *acpi_start,
    2.10                                         unsigned char *entry);
    2.11 +static int acpi_xsdt_add_entry_pointer(unsigned char *acpi_start,
    2.12 +                                       unsigned char *entry);
    2.13  static unsigned char *acpi_xsdt_add_entry(unsigned char *acpi_start,
    2.14                                            unsigned char **freemem,
    2.15                                            unsigned char *limit,
    2.16 @@ -34,45 +37,78 @@ static unsigned char *acpi_xsdt_add_entr
    2.17  
    2.18  void set_checksum(void *start, int checksum_offset, int len)
    2.19  {
    2.20 -	unsigned char sum = 0;
    2.21 -	unsigned char *ptr;
    2.22 +    unsigned char sum = 0;
    2.23 +    unsigned char *ptr;
    2.24  
    2.25 -	ptr = start;
    2.26 -	ptr[checksum_offset] = 0;
    2.27 -	while (len--)
    2.28 -		sum += *ptr++;
    2.29 +    ptr = start;
    2.30 +    ptr[checksum_offset] = 0;
    2.31 +    while ( len-- )
    2.32 +        sum += *ptr++;
    2.33  
    2.34 -	ptr = start;
    2.35 -	ptr[checksum_offset] = -sum;
    2.36 +    ptr = start;
    2.37 +    ptr[checksum_offset] = -sum;
    2.38  }
    2.39  
    2.40  
    2.41  #include "acpi_ssdt_tpm.h"
    2.42 -static int acpi_tpm_tis_probe(unsigned char *acpi_start,
    2.43 -                              unsigned char **freemem,
    2.44 -                              unsigned char *limit)
    2.45 +static void acpi_tpm_tis_probe(unsigned char *acpi_start,
    2.46 +                               unsigned char **freemem,
    2.47 +                               unsigned char *limit)
    2.48  {
    2.49 -	int success = 1; /* not successful means 'out of memory' */
    2.50 -	unsigned char *addr;
    2.51 -	/* check TPM_DID, TPM_VID, TPM_RID in ioemu/hw/tpm_tis.c */
    2.52 -	uint16_t tis_did_vid_rid[] = {0x0001, 0x0001, 0x0001};
    2.53 +    unsigned char *addr;
    2.54 +    ACPI_2_0_TCPA_CLIENT *tcpa;
    2.55 +    /* check TPM_DID, TPM_VID, TPM_RID in ioemu/hw/tpm_tis.c */
    2.56 +    uint16_t tis_did_vid_rid[] = {0x0001, 0x0001, 0x0001};
    2.57 +    static const ACPI_2_0_TCPA_CLIENT Tcpa = {
    2.58 +        .header = {
    2.59 +            .signature = ACPI_2_0_TCPA_SIGNATURE,
    2.60 +            .length    = sizeof(ACPI_2_0_TCPA_CLIENT),
    2.61 +            .revision  = ACPI_2_0_TCPA_REVISION,
    2.62 +            .oem_id    = {'I', 'B', 'M', ' ', ' ', ' '},
    2.63 +            .oem_table_id = ASCII64(' ', ' ', ' ', ' ', ' ', 'x', 'e', 'n'),
    2.64 +            .oem_revision = 1,
    2.65 +            .creator_id   = ASCII32('I', 'B', 'M', ' '),
    2.66 +            .creator_revision = 1,
    2.67 +        }
    2.68 +    };
    2.69  
    2.70 -	/* probe for TIS interface ... */
    2.71 -	if (memcmp((char *)(0xFED40000 + 0xF00),
    2.72 -	           tis_did_vid_rid,
    2.73 -	           sizeof(tis_did_vid_rid)) == 0) {
    2.74 -		puts("TIS is available\n");
    2.75 -		addr = acpi_xsdt_add_entry(acpi_start, freemem, limit,
    2.76 -		                           AmlCode_TPM, sizeof(AmlCode_TPM));
    2.77 -		if (addr == NULL)
    2.78 -			success = 0;
    2.79 -		else {
    2.80 -			/* legacy systems need an RSDT entry */
    2.81 -			acpi_rsdt_add_entry_pointer(acpi_start,
    2.82 -			                            addr);
    2.83 -		}
    2.84 -	}
    2.85 -	return success;
    2.86 +    /* probe for TIS interface ... */
    2.87 +    if ( memcmp((char *)(0xFED40000 + 0xF00),
    2.88 +                tis_did_vid_rid,
    2.89 +                sizeof(tis_did_vid_rid)) != 0 )
    2.90 +        return;
    2.91 +
    2.92 +    puts("TIS is available\n");
    2.93 +    addr = acpi_xsdt_add_entry(acpi_start, freemem, limit,
    2.94 +                               AmlCode_TPM, sizeof(AmlCode_TPM));
    2.95 +    if ( addr == NULL )
    2.96 +        return;
    2.97 +
    2.98 +    /* legacy systems need an RSDT entry */
    2.99 +    acpi_rsdt_add_entry_pointer(acpi_start, addr);
   2.100 +
   2.101 +    /* add ACPI TCPA table */
   2.102 +    addr = acpi_xsdt_add_entry(acpi_start, freemem, limit,
   2.103 +                               (unsigned char *)&Tcpa,
   2.104 +                               sizeof(Tcpa));
   2.105 +    if ( addr == NULL )
   2.106 +        return;
   2.107 +
   2.108 +    tcpa = (ACPI_2_0_TCPA_CLIENT *)addr;
   2.109 +    tcpa->LASA = e820_malloc(
   2.110 +        ACPI_2_0_TCPA_LAML_SIZE, E820_RESERVED, (uint32_t)~0);
   2.111 +    if ( tcpa->LASA )
   2.112 +    {
   2.113 +        tcpa->LAML = ACPI_2_0_TCPA_LAML_SIZE;
   2.114 +        memset((char *)(unsigned long)tcpa->LASA,
   2.115 +               0x0,
   2.116 +               tcpa->LAML);
   2.117 +        set_checksum(tcpa,
   2.118 +                     FIELD_OFFSET(struct acpi_header, checksum),
   2.119 +                     tcpa->header.length);
   2.120 +    }
   2.121 +
   2.122 +    acpi_rsdt_add_entry_pointer(acpi_start, addr);
   2.123  }
   2.124  
   2.125  
   2.126 @@ -95,17 +131,20 @@ struct acpi_20_rsdt *acpi_rsdt_get(unsig
   2.127      struct acpi_20_rsdt *rsdt;
   2.128  
   2.129      rsdp = (struct acpi_20_rsdp *)(acpi_start + sizeof(struct acpi_20_facs));
   2.130 -    if (rsdp->signature != ACPI_2_0_RSDP_SIGNATURE) {
   2.131 +    if ( rsdp->signature != ACPI_2_0_RSDP_SIGNATURE )
   2.132 +    {
   2.133          puts("Bad RSDP signature\n");
   2.134          return NULL;
   2.135      }
   2.136  
   2.137      rsdt = (struct acpi_20_rsdt *)
   2.138          (acpi_start + rsdp->rsdt_address - ACPI_PHYSICAL_ADDRESS);
   2.139 -    if (rsdt->header.signature != ACPI_2_0_RSDT_SIGNATURE) {
   2.140 +    if ( rsdt->header.signature != ACPI_2_0_RSDT_SIGNATURE )
   2.141 +    {
   2.142          puts("Bad RSDT signature\n");
   2.143          return NULL;
   2.144      }
   2.145 +
   2.146      return rsdt;
   2.147  }
   2.148  
   2.149 @@ -119,17 +158,20 @@ static int acpi_rsdt_add_entry_pointer(u
   2.150      int found = 0;
   2.151      int i = 0;
   2.152  
   2.153 -    /* get empty slot in the RSDT table */
   2.154 -    while (i < ACPI_MAX_NUM_TABLES) {
   2.155 -        if (rsdt->entry[i] == 0) {
   2.156 +    /* Find an empty slot in the RSDT table. */
   2.157 +    while ( i < ACPI_MAX_NUM_TABLES )
   2.158 +    {
   2.159 +        if ( rsdt->entry[i] == 0 )
   2.160 +        {
   2.161              found = 1;
   2.162              break;
   2.163          }
   2.164          i++;
   2.165      }
   2.166  
   2.167 -    if (found) {
   2.168 -        rsdt->entry[i] = (uint64_t)(long)entry;
   2.169 +    if ( found )
   2.170 +    {
   2.171 +        rsdt->entry[i] = (uint64_t)(unsigned long)entry;
   2.172          rsdt->header.length =
   2.173              sizeof(struct acpi_header) +
   2.174              (i + 1) * sizeof(uint64_t);
   2.175 @@ -141,21 +183,23 @@ static int acpi_rsdt_add_entry_pointer(u
   2.176      return found;
   2.177  }
   2.178  
   2.179 -/* Get the XSDT table */
   2.180 +/* Get the XSDT table. */
   2.181  struct acpi_20_xsdt *acpi_xsdt_get(unsigned char *acpi_start)
   2.182  {
   2.183      struct acpi_20_rsdp *rsdp;
   2.184      struct acpi_20_xsdt *xsdt;
   2.185  
   2.186      rsdp = (struct acpi_20_rsdp *)(acpi_start + sizeof(struct acpi_20_facs));
   2.187 -    if (rsdp->signature != ACPI_2_0_RSDP_SIGNATURE) {
   2.188 +    if ( rsdp->signature != ACPI_2_0_RSDP_SIGNATURE )
   2.189 +    {
   2.190          puts("Bad RSDP signature\n");
   2.191          return NULL;
   2.192      }
   2.193  
   2.194      xsdt = (struct acpi_20_xsdt *)
   2.195          (acpi_start + rsdp->xsdt_address - ACPI_PHYSICAL_ADDRESS);
   2.196 -    if (xsdt->header.signature != ACPI_2_0_XSDT_SIGNATURE) {
   2.197 +    if ( xsdt->header.signature != ACPI_2_0_XSDT_SIGNATURE )
   2.198 +    {
   2.199          puts("Bad XSDT signature\n");
   2.200          return NULL;
   2.201      }
   2.202 @@ -163,6 +207,41 @@ struct acpi_20_xsdt *acpi_xsdt_get(unsig
   2.203  }
   2.204  
   2.205  /*
   2.206 + * Add an entry to the XSDT table given the pointer to the entry.
   2.207 + */
   2.208 +static int acpi_xsdt_add_entry_pointer(unsigned char *acpi_start,
   2.209 +                                       unsigned char *entry)
   2.210 +{
   2.211 +    struct acpi_20_xsdt *xsdt = acpi_xsdt_get(acpi_start);
   2.212 +    int found = 0;
   2.213 +    int i = 0;
   2.214 +
   2.215 +    /* Find an empty slot in the XSDT table. */
   2.216 +    while ( i < ACPI_MAX_NUM_TABLES )
   2.217 +    {
   2.218 +        if ( xsdt->entry[i] == 0 )
   2.219 +        {
   2.220 +            found = 1;
   2.221 +            break;
   2.222 +        }
   2.223 +        i++;
   2.224 +    }
   2.225 +
   2.226 +    if ( found )
   2.227 +    {
   2.228 +        xsdt->entry[i] = (uint64_t)(unsigned long)entry;
   2.229 +        xsdt->header.length =
   2.230 +            sizeof(struct acpi_header) +
   2.231 +            (i + 1) * sizeof(uint64_t);
   2.232 +        set_checksum(xsdt,
   2.233 +                     FIELD_OFFSET(struct acpi_header, checksum),
   2.234 +                     xsdt->header.length);
   2.235 +    }
   2.236 +
   2.237 +    return found;
   2.238 +}
   2.239 +
   2.240 +/*
   2.241     add an entry to the xdst table entry pointers
   2.242     copy the given ssdt data to the current available memory at
   2.243     freemem, if it does not exceed the limit
   2.244 @@ -177,31 +256,29 @@ static unsigned char *acpi_xsdt_add_entr
   2.245      int found = 0, i = 0;
   2.246      unsigned char *addr = NULL;
   2.247  
   2.248 -    /* get empty slot in the Xsdt table */
   2.249 -    while (i < ACPI_MAX_NUM_TABLES) {
   2.250 -        if (xsdt->entry[i] == 0) {
   2.251 +    /* Check for an empty slot in the Xsdt table. */
   2.252 +    while ( i < ACPI_MAX_NUM_TABLES )
   2.253 +    {
   2.254 +        if ( xsdt->entry[i] == 0 )
   2.255 +        {
   2.256              found = 1;
   2.257              break;
   2.258          }
   2.259          i++;
   2.260      }
   2.261  
   2.262 -    if (found) {
   2.263 +    if ( found )
   2.264 +    {
   2.265          /* memory below hard limit ? */
   2.266          if (*freemem + table_size <= limit) {
   2.267              puts("Copying SSDT entry!\n");
   2.268              addr = *freemem;
   2.269              memcpy(addr, table, table_size);
   2.270 -            xsdt->entry[i] = (uint64_t)(long)addr;
   2.271              *freemem += table_size;
   2.272 -            /* update the XSDT table */
   2.273 -            xsdt->header.length =
   2.274 -                sizeof(struct acpi_header) +
   2.275 -                (i + 1) * sizeof(uint64_t);
   2.276 -            set_checksum(xsdt,
   2.277 -                         FIELD_OFFSET(struct acpi_header, checksum),
   2.278 -                         xsdt->header.length);
   2.279 +
   2.280 +            acpi_xsdt_add_entry_pointer(acpi_start, addr);
   2.281          }
   2.282      }
   2.283 +
   2.284      return addr;
   2.285  }
     3.1 --- a/tools/firmware/hvmloader/util.c	Fri Nov 17 10:05:12 2006 +0000
     3.2 +++ b/tools/firmware/hvmloader/util.c	Fri Nov 17 10:24:22 2006 +0000
     3.3 @@ -90,6 +90,23 @@ void *memcpy(void *dest, const void *src
     3.4  	return dest;
     3.5  }
     3.6  
     3.7 +void *memmove(void *dest, const void *src, unsigned n)
     3.8 +{
     3.9 +	if ((long)dest > (long)src) {
    3.10 +		n--;
    3.11 +		while (n > 0) {
    3.12 +			((char *)dest)[n] = ((char *)src)[n];
    3.13 +			n--;
    3.14 +		}
    3.15 +	} else {
    3.16 +		memcpy(dest, src, n);
    3.17 +	}
    3.18 +	return dest;
    3.19 +}
    3.20 +
    3.21 +
    3.22 +
    3.23 +
    3.24  void puts(const char *s)
    3.25  {
    3.26  	while (*s)
    3.27 @@ -229,3 +246,37 @@ uuid_to_string(char *dest, uint8_t *uuid
    3.28  	}
    3.29  	*p = 0;
    3.30  }
    3.31 +
    3.32 +#include <xen/hvm/e820.h>
    3.33 +#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET)
    3.34 +#define E820_MAP    ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET))
    3.35 +uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask)
    3.36 +{
    3.37 +	uint64_t addr = 0;
    3.38 +	int c = *E820_MAP_NR - 1;
    3.39 +	struct e820entry *e820entry = (struct e820entry *)E820_MAP;
    3.40 +
    3.41 +	while (c >= 0) {
    3.42 +		if (e820entry[c].type  == E820_RAM     &&
    3.43 +		    (e820entry[c].addr & (~mask)) == 0 &&
    3.44 +		    e820entry[c].size >= size) {
    3.45 +			addr = e820entry[c].addr;
    3.46 +			if (e820entry[c].size != size) {
    3.47 +				(*E820_MAP_NR)++;
    3.48 +				memmove(&e820entry[c+1],
    3.49 +				        &e820entry[c],
    3.50 +				        (*E820_MAP_NR - c) *
    3.51 +				            sizeof(struct e820entry));
    3.52 +				e820entry[c].size -= size;
    3.53 +				addr += e820entry[c].size;
    3.54 +				c++;
    3.55 +			}
    3.56 +			e820entry[c].addr = addr;
    3.57 +			e820entry[c].size = size;
    3.58 +			e820entry[c].type = type;
    3.59 +			break;
    3.60 +		}
    3.61 +		c--;
    3.62 +	}
    3.63 +        return addr;
    3.64 +}
     4.1 --- a/tools/firmware/hvmloader/util.h	Fri Nov 17 10:05:12 2006 +0000
     4.2 +++ b/tools/firmware/hvmloader/util.h	Fri Nov 17 10:24:22 2006 +0000
     4.3 @@ -22,6 +22,7 @@ char *strncpy(char *dest, const char *sr
     4.4  unsigned strlen(const char *s);
     4.5  int memcmp(const void *s1, const void *s2, unsigned n);
     4.6  void *memcpy(void *dest, const void *src, unsigned n);
     4.7 +void *memmove(void *dest, const void *src, unsigned n);
     4.8  void *memset(void *s, int c, unsigned n);
     4.9  char *itoa(char *a, unsigned int i);
    4.10  
    4.11 @@ -38,4 +39,7 @@ void uuid_to_string(char *dest, uint8_t 
    4.12  /* Debug output */
    4.13  void puts(const char *s);
    4.14  
    4.15 +/* Allocate region of specified type in the e820 table. */
    4.16 +uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask);
    4.17 +
    4.18  #endif /* __HVMLOADER_UTIL_H__ */