#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))
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;
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;
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;
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;
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;
}
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;
}
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]) &&
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;
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.
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));
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);
}
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;
}
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;
#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" */
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__ */