]> xenbits.xen.org Git - xenclient/xen.git/commitdiff
ACPI activation pass-through changes for HVM loader.
authorRoss Philipson <ross.philipson@citrix.com>
Tue, 20 Jan 2009 21:36:05 +0000 (16:36 -0500)
committerRoss Philipson <ross.philipson@citrix.com>
Tue, 20 Jan 2009 21:36:05 +0000 (16:36 -0500)
This is the first half of the update which processes ACPI pt
information for adding the OEM information and SLIC tables to
allow HVM activation of Vista.

 On branch master
 Changes to be committed:
modified:   tools/firmware/hvmloader/acpi/build.c
modified:   tools/firmware/hvmloader/util.c
modified:   tools/firmware/hvmloader/util.h
modified:   xen/include/public/hvm/hvm_info_table.h

tools/firmware/hvmloader/acpi/build.c
tools/firmware/hvmloader/util.c
tools/firmware/hvmloader/util.h
xen/include/public/hvm/hvm_info_table.h

index a77e992df83af3e53666eb36c9cfeebeaba6b585..8173ee6e6d44bf1ce630cb96762d7549c6fb02a4 100644 (file)
@@ -21,6 +21,7 @@
 #include "ssdt_pm.h"
 #include "../config.h"
 #include "../util.h"
+#include <xen/hvm/hvm_info_table.h>
 
 #define align16(sz)        (((sz) + 15) & ~15)
 #define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
@@ -98,7 +99,16 @@ static int construct_bios_info_table(uint8_t *buf)
     return align16(sizeof(*bios_info));
 }
 
-static int construct_madt(struct acpi_20_madt *madt)
+static void pt_update_acpi_tables(struct acpi_header *header, struct hvm_acinfo_table *va_ac)
+{
+    memcpy(header->oem_id, va_ac->oem_id, HVM_ACINFO_OEM_ID_SIZE);
+    memcpy(header->oem_table_id, va_ac->oem_table_id, HVM_ACINFO_OEM_TABLE_ID_SIZE);
+    header->oem_revision = va_ac->oem_revision;
+    header->creator_id   = ASCII32(va_ac->creator_id[0],va_ac->creator_id[1],va_ac->creator_id[2],va_ac->creator_id[3]);
+    header->creator_revision = va_ac->creator_revision;
+}
+
+static int construct_madt(struct acpi_20_madt *madt, struct hvm_acinfo_table *va_ac)
 {
     struct acpi_20_madt_intsrcovr *intsrcovr;
     struct acpi_20_madt_ioapic    *io_apic;
@@ -108,7 +118,14 @@ static int construct_madt(struct acpi_20_madt *madt)
     memset(madt, 0, sizeof(*madt));
     madt->header.signature    = ACPI_2_0_MADT_SIGNATURE;
     madt->header.revision     = ACPI_2_0_MADT_REVISION;
-    fixed_strcpy(madt->header.oem_id, ACPI_OEM_ID);
+    if (va_ac == NULL)
+    {
+        fixed_strcpy(madt->header.oem_id, ACPI_OEM_ID);
+    }
+    else
+    {
+        memcpy(madt->header.oem_id, va_ac->oem_id, HVM_ACINFO_OEM_ID_SIZE);       
+    }
     fixed_strcpy(madt->header.oem_table_id, ACPI_OEM_TABLE_ID);
     madt->header.oem_revision = ACPI_OEM_REVISION;
     madt->header.creator_id   = ACPI_CREATOR_ID;
@@ -175,14 +192,21 @@ static int construct_madt(struct acpi_20_madt *madt)
     return align16(offset);
 }
 
-static int construct_hpet(struct acpi_20_hpet *hpet)
+static int construct_hpet(struct acpi_20_hpet *hpet, struct hvm_acinfo_table *va_ac)
 {
     int offset;
 
     memset(hpet, 0, sizeof(*hpet));
     hpet->header.signature    = ACPI_2_0_HPET_SIGNATURE;
     hpet->header.revision     = ACPI_2_0_HPET_REVISION;
-    fixed_strcpy(hpet->header.oem_id, ACPI_OEM_ID);
+    if (va_ac == NULL)
+    {
+        fixed_strcpy(hpet->header.oem_id, ACPI_OEM_ID);        
+    }
+    else
+    {
+        memcpy(hpet->header.oem_id, va_ac->oem_id, HVM_ACINFO_OEM_ID_SIZE);
+    }
     fixed_strcpy(hpet->header.oem_table_id, ACPI_OEM_TABLE_ID);
     hpet->header.oem_revision = ACPI_OEM_REVISION;
     hpet->header.creator_id   = ACPI_CREATOR_ID;
@@ -197,7 +221,7 @@ static int construct_hpet(struct acpi_20_hpet *hpet)
     return offset;
 }
 
-static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
+static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs, struct hvm_acinfo_table *va_ac)
 {
     int offset = 0, nr_tables = 0;
     struct acpi_20_madt *madt;
@@ -210,7 +234,7 @@ static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
     if ( (get_vcpu_nr() > 1) || get_apic_mode() )
     {
         madt = (struct acpi_20_madt *)&buf[offset];
-        offset += construct_madt(madt);
+        offset += construct_madt(madt, va_ac);
         table_ptrs[nr_tables++] = (unsigned long)madt;
     }
 
@@ -218,7 +242,7 @@ static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
     if ( hpet_exists(ACPI_HPET_ADDRESS) )
     {
         hpet = (struct acpi_20_hpet *)&buf[offset];
-        offset += construct_hpet(hpet);
+        offset += construct_hpet(hpet, va_ac);
         table_ptrs[nr_tables++] = (unsigned long)hpet;
     }
 
@@ -229,6 +253,14 @@ static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
         offset += align16(sizeof(AmlCode_PM));
     }
 
+    /* SLIC */
+    if (va_ac != NULL)
+    {
+        table_ptrs[nr_tables++] = (unsigned long)&buf[offset];
+        memcpy(&buf[offset], (uint8_t*)va_ac + sizeof(struct hvm_acinfo_table), va_ac->slic_length);
+        offset += align16(va_ac->slic_length);
+    }
+
     /* TPM TCPA and SSDT. */
     tis_hdr = (uint16_t *)0xFED40F00;
     if ( (tis_hdr[0] == tis_signature[0]) &&
@@ -247,7 +279,14 @@ static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
         tcpa->header.signature = ACPI_2_0_TCPA_SIGNATURE;
         tcpa->header.length    = sizeof(*tcpa);
         tcpa->header.revision  = ACPI_2_0_TCPA_REVISION;
-        fixed_strcpy(tcpa->header.oem_id, ACPI_OEM_ID);
+        if (va_ac == NULL)
+        {
+            fixed_strcpy(tcpa->header.oem_id, ACPI_OEM_ID);            
+        }
+        else
+        {
+            memcpy(tcpa->header.oem_id, va_ac->oem_id, HVM_ACINFO_OEM_ID_SIZE);
+        }
         fixed_strcpy(tcpa->header.oem_table_id, ACPI_OEM_TABLE_ID);
         tcpa->header.oem_revision = ACPI_OEM_REVISION;
         tcpa->header.creator_id   = ACPI_CREATOR_ID;
@@ -278,6 +317,20 @@ static void __acpi_build_tables(uint8_t *buf, int *low_sz, int *high_sz)
     unsigned char       *dsdt;
     unsigned long        secondary_tables[16];
     int                  offset = 0, i;
+    struct hvm_acinfo_table *va_ac;
+    
+    /*
+     * First get the ACPI info structure that may be passed to the HVM loader. This will be used
+     * to pass through platform ACPI information if present.
+     */
+    va_ac = get_hvm_acinfo_table();
+    if (va_ac != NULL)
+    {
+        pt_update_acpi_tables(&Rsdt.header, va_ac);
+        pt_update_acpi_tables(&Xsdt.header, va_ac);
+        /* just the OEM ID for the FADT */
+        memcpy(Fadt.header.oem_id, va_ac->oem_id, HVM_ACINFO_OEM_ID_SIZE);
+    }
 
     /*
      * Fill in high-memory data structures, starting at @buf.
@@ -321,7 +374,7 @@ static void __acpi_build_tables(uint8_t *buf, int *low_sz, int *high_sz)
                  offsetof(struct acpi_header, checksum),
                  sizeof(struct acpi_20_fadt));
 
-    offset += construct_secondary_tables(&buf[offset], secondary_tables);
+    offset += construct_secondary_tables(&buf[offset], secondary_tables, va_ac);
 
     xsdt = (struct acpi_20_xsdt *)&buf[offset];
     memcpy(xsdt, &Xsdt, sizeof(struct acpi_header));
index 6a29d6beaf147d9db2102c2b46e11ced4e44bcf0..10fcb12e6cf5c56f9600424581aec6fbabfb1517 100644 (file)
@@ -543,25 +543,27 @@ void __bug(char *file, int line)
         asm volatile ( "ud2" );
 }
 
-static int validate_hvm_info(struct hvm_info_table *t)
+static int validate_hvm_info_table(uint8_t *table, uint32_t table_length, const char *table_sig, const char *sig, uint32_t sig_length)
 {
-    char signature[] = "HVM INFO";
-    uint8_t *ptr = (uint8_t *)t;
     uint8_t sum = 0;
     int i;
 
-    /* strncmp(t->signature, "HVM INFO", 8) */
-    for ( i = 0; i < 8; i++ )
+    if (table_length == 0) {
+        printf("Empty HVM info table: %.*s\n", sig_length, sig);
+    }
+
+    /* strncmp(t->signature, signature, sig_length) */
+    for ( i = 0; i < sig_length; i++ )
     {
-        if ( signature[i] != t->signature[i] )
+        if ( table_sig[i] != sig[i] )
         {
-            printf("Bad hvm info signature\n");
+            printf("Bad HVM info signature for: %.*s\n", sig_length, sig);
             return 0;
         }
     }
 
-    for ( i = 0; i < t->length; i++ )
-        sum += ptr[i];
+    for ( i = 0; i < table_length; i++ )
+        sum += table[i];
 
     return (sum == 0);
 }
@@ -575,10 +577,10 @@ static struct hvm_info_table *get_hvm_info_table(void)
         return table;
 
     t = (struct hvm_info_table *)HVM_INFO_PADDR;
-
-    if ( !validate_hvm_info(t) )
+    
+    if ( !validate_hvm_info_table((uint8_t*)t, t->length, t->signature, "HVM INFO", 8) )
     {
-        printf("Bad hvm info table\n");
+        printf("Bad HVM info table\n");
         return NULL;
     }
 
@@ -647,50 +649,53 @@ uint16_t get_cpu_mhz(void)
     return cpu_mhz;
 }
 
-static int validate_hvm_sminfo(struct hvm_sminfo_table *t)
+struct hvm_sminfo_table *get_hvm_sminfo_table(void)
 {
-    char signature[] = "SM INFO";
-    uint8_t *ptr = (uint8_t *)t;
-    uint8_t sum = 0;
-    uint32_t length;
-    int i;
+    static struct hvm_sminfo_table *table = NULL;
+    static int validated = 0;
+    struct hvm_sminfo_table *t;
 
-    if ( (t->total_length == 0) && (t->sm_count == 0) ) {
-        printf("Empty hvm smbios info table\n");
-    }
+    if ( validated )
+        return table;
 
-    /* strncmp(t->signature, "SM INFO", 7) */
-    for ( i = 0; i < 7; i++ )
-    {
-        if ( signature[i] != t->signature[i] )
-        {
-            printf("Bad hvm smbios info signature\n");
-            return 0;
-        }
+    t = (struct hvm_sminfo_table *)HVM_SMINFO_PADDR;
+
+    if ( (t->total_length == 0) && (t->sm_count == 0) ) {
+        printf("Empty HVM SMBIOS info table\n");
+        validated = 1;
+        return table;
     }
 
-    length = sizeof(struct hvm_sminfo_table) + t->total_length;
-    for ( i = 0; i < length; i++ )
-        sum += ptr[i];
+    if ( validate_hvm_info_table((uint8_t*)t, t->total_length + sizeof(struct hvm_sminfo_table), t->signature, "SM INFO", 7) )
+        table = t;
+    else
+        printf("Bad or missing HVM SMBIOS info table\n");
+    validated = 1;
 
-    return (sum == 0);
+    return table;
 }
 
-struct hvm_sminfo_table *get_hvm_sminfo_table(void)
+struct hvm_acinfo_table *get_hvm_acinfo_table(void)
 {
-    static struct hvm_sminfo_table *table = NULL;
+    static struct hvm_acinfo_table *table = NULL;
     static int validated = 0;
-    struct hvm_sminfo_table *t;
+    struct hvm_acinfo_table *t;
 
     if ( validated )
         return table;
 
-    t = (struct hvm_sminfo_table *)HVM_SMINFO_PADDR;
+    t = (struct hvm_acinfo_table *)HVM_ACINFO_PADDR;
 
-    if ( validate_hvm_sminfo(t) )
+    if ( t->slic_length == 0 ) {
+        printf("HVM ACPI info table missing SLIC table?\n");
+        validated = 1;
+        return table;
+    }
+  
+    if ( validate_hvm_info_table((uint8_t*)t, t->slic_length + sizeof(struct hvm_acinfo_table), t->signature, "AC INFO", 7) )        
         table = t;
     else
-        printf("Bad or missing hvm smbios info table\n");
+        printf("Bad or missing HVM SMBIOS info table\n");
     validated = 1;
 
     return table;
index cd8ede9dec7cb3533c92097c4f3409800ddc09e9..4900150e3a66bd66c291683ef827ac2ee2683669 100644 (file)
@@ -107,8 +107,9 @@ int get_vcpu_nr(void);
 int get_acpi_enabled(void);
 int get_apic_mode(void);
 
-/* HVM-build SMBIOS info. */
+/* HVM-build SMBIOS/ACPI info extensions */
 struct hvm_sminfo_table *get_hvm_sminfo_table(void);
+struct hvm_acinfo_table *get_hvm_acinfo_table(void);
 
 /* String and memory functions */
 int strcmp(const char *cs, const char *ct);
index d0ee338ab4700da369947de43e9749e892d76a16..b84bbdf5c312b51193e2c38641dcf2b65627ae4d 100644 (file)
 #define HVM_INFO_PFN         0x09F
 #define HVM_INFO_OFFSET      0x800
 #define HVM_INFO_PADDR       ((HVM_INFO_PFN << 12) + HVM_INFO_OFFSET)
+#define HVM_INFO_MAX         0x400
 #define HVM_SMINFO_OFFSET    0x0
 #define HVM_SMINFO_PADDR     ((HVM_INFO_PFN << 12) + HVM_SMINFO_OFFSET)
 #define HVM_SMINFO_MAX       0x800
+#define HVM_ACINFO_OFFSET    0xC00
+#define HVM_ACINFO_PADDR     ((HVM_INFO_PFN << 12) + HVM_ACINFO_OFFSET)
+#define HVM_ACINFO_MAX       0x400
 
 #define HVM_SMINFO_EXTENSIONS 1
+#define HVM_ACINFO_EXTENSIONS 1
 
 struct hvm_info_table {
     char        signature[8]; /* "HVM INFO" */
@@ -54,4 +59,19 @@ struct hvm_smtable_header {
     uint32_t    sm_length; /* beginning after this stucture, includes fixed table, string list, and terminator */
 };
 
+#define HVM_ACINFO_OEM_ID_SIZE       6
+#define HVM_ACINFO_OEM_TABLE_ID_SIZE 8
+#define HVM_ACINFO_CREATOR_ID_SIZE   4
+
+struct hvm_acinfo_table {
+    char        signature[7]; /* "AC INFO" */
+    uint8_t     checksum;
+    uint32_t    slic_length; /* length of SLIC following this structure */
+    char        oem_id[HVM_ACINFO_OEM_ID_SIZE];
+    char        oem_table_id[HVM_ACINFO_OEM_TABLE_ID_SIZE];
+    uint32_t    oem_revision;
+    char        creator_id[HVM_ACINFO_CREATOR_ID_SIZE];
+    uint32_t    creator_revision;
+};
+
 #endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */