From dbfb07095aa0dd55073da5e49dcc292e35f50f36 Mon Sep 17 00:00:00 2001 From: Ross Philipson Date: Tue, 20 Jan 2009 16:36:05 -0500 Subject: [PATCH] ACPI activation pass-through changes for HVM loader. 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 | 71 ++++++++++++++++++--- tools/firmware/hvmloader/util.c | 83 +++++++++++++------------ tools/firmware/hvmloader/util.h | 3 +- xen/include/public/hvm/hvm_info_table.h | 20 ++++++ 4 files changed, 128 insertions(+), 49 deletions(-) diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c index a77e992..8173ee6 100644 --- a/tools/firmware/hvmloader/acpi/build.c +++ b/tools/firmware/hvmloader/acpi/build.c @@ -21,6 +21,7 @@ #include "ssdt_pm.h" #include "../config.h" #include "../util.h" +#include #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)); diff --git a/tools/firmware/hvmloader/util.c b/tools/firmware/hvmloader/util.c index 6a29d6b..10fcb12 100644 --- a/tools/firmware/hvmloader/util.c +++ b/tools/firmware/hvmloader/util.c @@ -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; diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h index cd8ede9..4900150 100644 --- a/tools/firmware/hvmloader/util.h +++ b/tools/firmware/hvmloader/util.h @@ -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); diff --git a/xen/include/public/hvm/hvm_info_table.h b/xen/include/public/hvm/hvm_info_table.h index d0ee338..b84bbdf 100644 --- a/xen/include/public/hvm/hvm_info_table.h +++ b/xen/include/public/hvm/hvm_info_table.h @@ -28,11 +28,16 @@ #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__ */ -- 2.39.5