commit 5c294beb2d7a31eb9153e6d342efee3ec5d5747b Mon Sep 17 00:00:00 2001 Author: Michael Tokarev Date: Sat, 5 Apr 2014 19:17:54 +0400 Subject: copy OEM ACPI parameters from SLIC table to RSDT and FACP When building RSDT table, pick OEM ID fields from uer-supplied SLIC table instead of using hard-coded QEMU defaults. This way, say, OEM version of Windows7 can be run inside qemu using the same OEM activation as on bare metal, by pointing at system firmware: -acpitable file=/sys/firmware/acpi/tables/SLIC Windows7 requires that OEM ID in RSDT matches those in SLIC to consider SLIC to be valid. In UEFI mode, win7 checks FACP too. This is somewhat hackish approach, but it works fairy well in practice. Signed-off-by: Michael Tokarev --- hw/acpi/aml-build.c | 6 ++++++ hw/acpi/core.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 0d4b324..1837534 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1135,6 +1135,8 @@ Aml *aml_unicode(const char *str) return var; } +char slic_oem_id[6+8]; /* oem_id[6] oem_table_id[8] */ + void build_header(GArray *linker, GArray *table_data, AcpiTableHeader *h, const char *sig, int len, uint8_t rev) @@ -1148,6 +1150,10 @@ build_header(GArray *linker, GArray *table_data, h->oem_revision = cpu_to_le32(1); memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4); h->asl_compiler_revision = cpu_to_le32(1); + if (slic_oem_id[0] && (!memcmp(sig, "RSDT", 4) || !memcmp(sig, "FACP", 4))) { + /* for win7: OEM info in RSDT and SLIC should be the same */ + memcpy(h->oem_id, slic_oem_id, sizeof(slic_oem_id)); + } h->checksum = 0; /* Checksum to be filled in by Guest linker */ bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE, diff --git a/hw/acpi/core.c b/hw/acpi/core.c index fe6215a..a602d76 100644 --- a/hw/acpi/core.c +++ b/hw/acpi/core.c @@ -54,6 +54,7 @@ static const char unsigned dfl_hdr[ACPI_TABLE_HDR_SIZE - ACPI_TABLE_PFX_SIZE] = char unsigned *acpi_tables; size_t acpi_tables_len; +extern char slic_oem_id[6+8]; static QemuOptsList qemu_acpi_opts = { .name = "acpi", @@ -227,6 +228,10 @@ static void acpi_table_install(const char unsigned *blob, size_t bloblen, /* recalculate checksum */ ext_hdr->checksum = acpi_checksum((const char unsigned *)ext_hdr + ACPI_TABLE_PFX_SIZE, acpi_payload_size); + + if (memcmp(ext_hdr->sig, "SLIC", 4) == 0) { + memcpy(slic_oem_id, ext_hdr->oem_id, sizeof(slic_oem_id)); + } } void acpi_table_add(const QemuOpts *opts, Error **errp) -- 2.1.4