398 lines
16 KiB
Diff
398 lines
16 KiB
Diff
Subject: [PATCH] firmware: FIRMWARE
|
|
|
|
Targets VMAware check: FIRMWARE
|
|
|
|
ACPI table fingerprints: PCI link-device names, PNP0A06 resource stubs, the
|
|
FADT C-state latencies and the AML the checker string-matches on.
|
|
|
|
Applies to QEMU v11.1.1. Apply from the source root with:
|
|
patch -p1 < 01-firmware.patch
|
|
|
|
---
|
|
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
|
|
index 8837b69..4001d9d 100644
|
|
--- a/hw/i386/acpi-build.c
|
|
+++ b/hw/i386/acpi-build.c
|
|
@@ -165,8 +165,8 @@ static void init_common_fadt_data(MachineState *ms, Object *o,
|
|
(1 << ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL) : 0),
|
|
.int_model = 1 /* Multiple APIC */,
|
|
.rtc_century = RTC_CENTURY,
|
|
- .plvl2_lat = 0xfff /* C2 state not supported */,
|
|
- .plvl3_lat = 0xfff /* C3 state not supported */,
|
|
+ .plvl2_lat = 0xffe /* C2 state not supported */,
|
|
+ .plvl3_lat = 0xffe /* C3 state not supported */,
|
|
.smi_cmd = smm_enabled ? ACPI_PORT_SMI_CMD : 0,
|
|
.sci_int = object_property_get_uint(o, ACPI_PM_PROP_SCI_INT, NULL),
|
|
.acpi_enable_cmd =
|
|
@@ -748,9 +748,9 @@ static void build_q35_pci0_int(Aml *table)
|
|
aml_append(table, method);
|
|
|
|
aml_append(pci0_scope,
|
|
- aml_name_decl("PRTP", build_q35_routing_table("LNK")));
|
|
+ aml_name_decl("IRQP", build_q35_routing_table("LNK")));
|
|
aml_append(pci0_scope,
|
|
- aml_name_decl("PRTA", build_q35_routing_table("GSI")));
|
|
+ aml_name_decl("IRQA", build_q35_routing_table("APC")));
|
|
|
|
method = aml_method("_PRT", 0, AML_NOTSERIALIZED);
|
|
{
|
|
@@ -762,10 +762,10 @@ static void build_q35_pci0_int(Aml *table)
|
|
/* Note: we provide the same info as the PCI routing
|
|
table of the Bochs BIOS */
|
|
if_ctx = aml_if(aml_equal(aml_name("PICF"), aml_int(0)));
|
|
- aml_append(if_ctx, aml_return(aml_name("PRTP")));
|
|
+ aml_append(if_ctx, aml_return(aml_name("IRQP")));
|
|
aml_append(method, if_ctx);
|
|
else_ctx = aml_else();
|
|
- aml_append(else_ctx, aml_return(aml_name("PRTA")));
|
|
+ aml_append(else_ctx, aml_return(aml_name("IRQA")));
|
|
aml_append(method, else_ctx);
|
|
}
|
|
aml_append(pci0_scope, method);
|
|
@@ -783,14 +783,14 @@ static void build_q35_pci0_int(Aml *table)
|
|
aml_append(sb_scope, build_link_dev("LNKG", 6, aml_name("PRQG")));
|
|
aml_append(sb_scope, build_link_dev("LNKH", 7, aml_name("PRQH")));
|
|
|
|
- aml_append(sb_scope, build_gsi_link_dev("GSIA", 0x10, 0x10));
|
|
- aml_append(sb_scope, build_gsi_link_dev("GSIB", 0x11, 0x11));
|
|
- aml_append(sb_scope, build_gsi_link_dev("GSIC", 0x12, 0x12));
|
|
- aml_append(sb_scope, build_gsi_link_dev("GSID", 0x13, 0x13));
|
|
- aml_append(sb_scope, build_gsi_link_dev("GSIE", 0x14, 0x14));
|
|
- aml_append(sb_scope, build_gsi_link_dev("GSIF", 0x15, 0x15));
|
|
- aml_append(sb_scope, build_gsi_link_dev("GSIG", 0x16, 0x16));
|
|
- aml_append(sb_scope, build_gsi_link_dev("GSIH", 0x17, 0x17));
|
|
+ aml_append(sb_scope, build_gsi_link_dev("APCA", 0x10, 0x10));
|
|
+ aml_append(sb_scope, build_gsi_link_dev("APCB", 0x11, 0x11));
|
|
+ aml_append(sb_scope, build_gsi_link_dev("APCC", 0x12, 0x12));
|
|
+ aml_append(sb_scope, build_gsi_link_dev("APCD", 0x13, 0x13));
|
|
+ aml_append(sb_scope, build_gsi_link_dev("APCE", 0x14, 0x14));
|
|
+ aml_append(sb_scope, build_gsi_link_dev("APCF", 0x15, 0x15));
|
|
+ aml_append(sb_scope, build_gsi_link_dev("APCG", 0x16, 0x16));
|
|
+ aml_append(sb_scope, build_gsi_link_dev("APCH", 0x17, 0x17));
|
|
|
|
aml_append(table, sb_scope);
|
|
}
|
|
@@ -801,7 +801,7 @@ static Aml *build_q35_dram_controller(const AcpiMcfgInfo *mcfg)
|
|
Aml *resource_template;
|
|
|
|
/* DRAM controller */
|
|
- dev = aml_device("DRAC");
|
|
+ dev = aml_device("MCFG");
|
|
aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C01")));
|
|
|
|
resource_template = aml_resource_template();
|
|
@@ -885,7 +885,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
|
acpi_table_begin(&table, table_data);
|
|
dsdt = init_aml_allocator();
|
|
|
|
- build_dbg_aml(dsdt);
|
|
if (i440fx) {
|
|
sb_scope = aml_scope("_SB");
|
|
dev = aml_device("PCI0");
|
|
@@ -901,6 +900,36 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
|
build_piix4_pci0_int(dsdt);
|
|
} else if (q35) {
|
|
sb_scope = aml_scope("_SB");
|
|
+
|
|
+ /*
|
|
+ * Emulate Windows ACPI OSYS/_OSI logic in DSDT.
|
|
+ * Adds Windows 2001/2006/2009/2012/2013/2015.
|
|
+ */
|
|
+ static const struct {
|
|
+ const char *osi;
|
|
+ uint32_t osys;
|
|
+ } win_osi[] = {
|
|
+ { "Windows 2001", 0x07D1 },
|
|
+ { "Windows 2001 SP1", 0x07D1 },
|
|
+ { "Windows 2001 SP2", 0x07D2 },
|
|
+ { "Windows 2001.1", 0x07D3 },
|
|
+ { "Windows 2006", 0x07D6 },
|
|
+ { "Windows 2009", 0x07D9 },
|
|
+ { "Windows 2012", 0x07DC },
|
|
+ { "Windows 2013", 0x07DD },
|
|
+ { "Windows 2015", 0x07DF },
|
|
+ };
|
|
+
|
|
+ aml_append(sb_scope, aml_name_decl("OSYS", aml_int(0x03E8)));
|
|
+
|
|
+ for (unsigned n = 0; n < ARRAY_SIZE(win_osi); n++) {
|
|
+ Aml *osi = aml_if(aml_equal(
|
|
+ aml_call1("_OSI", aml_string("%s", win_osi[n].osi)), aml_int(1)));
|
|
+ aml_append(osi, aml_store(aml_int(win_osi[n].osys),
|
|
+ aml_name("OSYS")));
|
|
+ aml_append(sb_scope, osi);
|
|
+ }
|
|
+
|
|
dev = aml_device("PCI0");
|
|
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
|
|
aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
|
|
@@ -916,7 +945,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
|
/* reserve SMI block resources, IO ports 0xB2, 0xB3 */
|
|
dev = aml_device("PCI0.SMI0");
|
|
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A06")));
|
|
- aml_append(dev, aml_name_decl("_UID", aml_string("SMI resources")));
|
|
+ aml_append(dev, aml_name_decl("_UID", aml_string("Reserved resources A")));
|
|
crs = aml_resource_template();
|
|
aml_append(crs,
|
|
aml_io(
|
|
@@ -967,22 +996,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
|
}
|
|
aml_append(dsdt, scope);
|
|
|
|
- {
|
|
- CPUHotplugFeatures opts = {
|
|
- .acpi_1_compatible = true,
|
|
- .smi_path = pm->smi_on_cpuhp ? "\\_SB.PCI0.SMI0.SMIC" : NULL,
|
|
- .fw_unplugs_cpu = pm->smi_on_cpu_unplug,
|
|
- };
|
|
- build_cpus_aml(dsdt, machine, opts, pc_madt_cpu_entry,
|
|
- pm->cpu_hp_io_base, "\\_SB.PCI0", "\\_GPE._E02",
|
|
- AML_SYSTEM_IO);
|
|
- }
|
|
-
|
|
- if (pcms->memhp_io_base && nr_mem) {
|
|
- build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0",
|
|
- "\\_GPE._E03", AML_SYSTEM_IO,
|
|
- pcms->memhp_io_base);
|
|
- }
|
|
|
|
crs_range_set_init(&crs_range_set);
|
|
bus = PC_MACHINE(machine)->pcibus;
|
|
@@ -1133,9 +1146,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
|
aml_append(scope, aml_name_decl("_CRS", crs));
|
|
|
|
/* reserve GPE0 block resources */
|
|
- dev = aml_device("GPE0");
|
|
+ dev = aml_device("RSRA");
|
|
aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06")));
|
|
- aml_append(dev, aml_name_decl("_UID", aml_string("GPE0 resources")));
|
|
+ aml_append(dev, aml_name_decl("_UID", aml_int(0)));
|
|
/* device present, functioning, decoding, not shown in UI */
|
|
aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
|
|
crs = aml_resource_template();
|
|
@@ -1188,12 +1201,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
|
aml_append(scope, aml_name_decl("_S5", pkg));
|
|
aml_append(dsdt, scope);
|
|
|
|
- /* create fw_cfg node, unconditionally */
|
|
- {
|
|
- scope = aml_scope("\\_SB.PCI0");
|
|
- fw_cfg_add_acpi_dsdt(scope, x86ms->fw_cfg);
|
|
- aml_append(dsdt, scope);
|
|
- }
|
|
|
|
sb_scope = aml_scope("\\_SB");
|
|
{
|
|
@@ -2168,8 +2175,6 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
|
x86ms->oem_id, x86ms->oem_table_id, &pcms->cxl_devices_state);
|
|
}
|
|
|
|
- acpi_add_table(table_offsets, tables_blob);
|
|
- build_waet(tables_blob, tables->linker, x86ms->oem_id, x86ms->oem_table_id);
|
|
|
|
if (pcms->wdat_enabled == true) {
|
|
g_assert(pm.tco_io_base);
|
|
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
|
|
index 87162ff..4c303cb 100644
|
|
--- a/hw/acpi/pcihp.c
|
|
+++ b/hw/acpi/pcihp.c
|
|
@@ -687,10 +687,10 @@ void build_append_pcihp_resources(Aml *scope /* \\_SB.PCI0 */,
|
|
{
|
|
Aml *dev, *crs;
|
|
|
|
- dev = aml_device("PHPR");
|
|
+ dev = aml_device("RSRB");
|
|
aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06")));
|
|
aml_append(dev,
|
|
- aml_name_decl("_UID", aml_string("PCI Hotplug resources")));
|
|
+ aml_name_decl("_UID", aml_string("Reserved resources B")));
|
|
/* device present, functioning, decoding, not shown in UI */
|
|
aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
|
|
crs = aml_resource_template();
|
|
@@ -699,6 +699,83 @@ void build_append_pcihp_resources(Aml *scope /* \\_SB.PCI0 */,
|
|
aml_append(scope, dev);
|
|
}
|
|
|
|
+/*
|
|
+ * Helper to generate "Real Hardware" looking ACPI names.
|
|
+ * This removes the "S<hex>" signature and ensures unique naming
|
|
+ * for multifunction devices.
|
|
+ */
|
|
+static void get_mimic_pci_name(char *name, int devfn) {
|
|
+ int slot = PCI_SLOT(devfn);
|
|
+ int func = PCI_FUNC(devfn);
|
|
+
|
|
+ switch (slot) {
|
|
+ case 0:
|
|
+ // Host Bridge is almost always Slot 0, Function 0 (and also bus 0 but we cant access bus number in this context)
|
|
+ if (func == 0) sprintf(name, "MCHC");
|
|
+ else sprintf(name, "H%X", func);
|
|
+ break;
|
|
+
|
|
+ case 2:
|
|
+ // Slot 2: Graphics + associated HDMI Audio
|
|
+ if (func == 0) sprintf(name, "GFX0"); // Primary GPU
|
|
+ else if (func == 1) sprintf(name, "HDAU"); // HDMI Audio
|
|
+ else sprintf(name, "GFX%X", func); // Fallback uniqueness
|
|
+ break;
|
|
+
|
|
+ case 3:
|
|
+ // Slot 3: Network
|
|
+ if (func == 0) sprintf(name, "GLAN");
|
|
+ else sprintf(name, "NET%X", func);
|
|
+ break;
|
|
+
|
|
+ case 4:
|
|
+ // Slot 4: Multimedia / Audio
|
|
+ if (func == 0) sprintf(name, "HDEF");
|
|
+ else sprintf(name, "MM%02X", func);
|
|
+ break;
|
|
+
|
|
+ case 5:
|
|
+ // Slot 5: USB XHCI (QEMU default often)
|
|
+ if (func == 0) sprintf(name, "XHC1");
|
|
+ else sprintf(name, "XHC%X", func);
|
|
+ break;
|
|
+
|
|
+ case 6:
|
|
+ // Slot 6: SATA (AHCI)
|
|
+ if (func == 0) sprintf(name, "SAT0");
|
|
+ else sprintf(name, "SAT%X", func);
|
|
+ break;
|
|
+
|
|
+ case 29:
|
|
+ // Slot 29 (0x1D): USB EHCI (Intel Standard)
|
|
+ if (func == 0) sprintf(name, "EHC1");
|
|
+ else sprintf(name, "EHC%X", func);
|
|
+ break;
|
|
+
|
|
+ case 20:
|
|
+ // Slot 20 (0x14): LPC / SMBus / SATA 2
|
|
+ if (func == 0) sprintf(name, "LPCB"); // ISA Bridge
|
|
+ else if (func == 2) sprintf(name, "SAT1"); // 2nd SATA
|
|
+ else if (func == 3) sprintf(name, "SBUS"); // SMBus
|
|
+ else sprintf(name, "S20%X", func); // Fallback
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ /*
|
|
+ * For generic slots, we use "RP" (Root Port) + devfn (Hex).
|
|
+ *
|
|
+ * Why 'devfn' and not 'slot'?
|
|
+ * - Slot 10, Func 0 (devfn 0x50) -> RP50
|
|
+ * - Slot 10, Func 1 (devfn 0x51) -> RP51
|
|
+ *
|
|
+ * This guarantees ACPI uniqueness for multifunction devices
|
|
+ * while completely breaking the "S" + hex signature.
|
|
+ */
|
|
+ sprintf(name, "RP%02X", devfn);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
bool build_append_notification_callback(Aml *parent_scope, const PCIBus *bus)
|
|
{
|
|
Aml *method;
|
|
@@ -912,7 +989,11 @@ void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus)
|
|
}
|
|
|
|
/* start to compose PCI device descriptor */
|
|
- dev = aml_device("S%.02X", devfn);
|
|
+
|
|
+ char mimic_name[5];
|
|
+ get_mimic_pci_name(mimic_name, devfn);
|
|
+ dev = aml_device("%s", mimic_name);
|
|
+
|
|
aml_append(dev, aml_name_decl("_ADR", aml_int(adr)));
|
|
|
|
call_dev_aml_func(DEVICE(bus->devices[devfn]), dev);
|
|
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
|
|
index 990abc6..01c8fc4 100644
|
|
--- a/hw/acpi/aml-build.c
|
|
+++ b/hw/acpi/aml-build.c
|
|
@@ -1751,15 +1751,14 @@ void acpi_table_begin(AcpiTable *desc, GArray *array)
|
|
* reserve space for Length field, which will be patched by
|
|
* acpi_table_end() when the table creation is finished.
|
|
*/
|
|
- build_append_int_noprefix(array, 0, 4); /* Length */
|
|
- build_append_int_noprefix(array, desc->rev, 1); /* Revision */
|
|
- build_append_int_noprefix(array, 0, 1); /* Checksum */
|
|
- build_append_padded_str(array, desc->oem_id, 6, '\0'); /* OEMID */
|
|
- /* OEM Table ID */
|
|
- build_append_padded_str(array, desc->oem_table_id, 8, '\0');
|
|
- build_append_int_noprefix(array, 1, 4); /* OEM Revision */
|
|
- g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
|
|
- build_append_int_noprefix(array, 1, 4); /* Creator Revision */
|
|
+ build_append_int_noprefix(array, 0, 4); /* Length */
|
|
+ build_append_int_noprefix(array, desc->rev, 1); /* Revision */
|
|
+ build_append_int_noprefix(array, 0, 1); /* Checksum */
|
|
+ build_append_padded_str(array, ACPI_BUILD_APPNAME6, 6, '\0'); /* OEMID */
|
|
+ build_append_padded_str(array, ACPI_BUILD_APPNAME8, 8, '\0'); /* OEM Table ID */
|
|
+ build_append_int_noprefix(array, 1, 4); /* OEM Revision */
|
|
+ g_array_append_vals(array, "ACPI", 4); /* Creator ID */
|
|
+ build_append_int_noprefix(array, 1, 4); /* Creator Revision */
|
|
}
|
|
|
|
void acpi_table_end(BIOSLinker *linker, AcpiTable *desc)
|
|
@@ -2488,7 +2487,7 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
|
/* ACPI1.0: INT_MODEL, ACPI2.0+: Reserved */
|
|
build_append_int_noprefix(tbl, f->int_model /* Multiple APIC */, 1);
|
|
/* Preferred_PM_Profile */
|
|
- build_append_int_noprefix(tbl, 0 /* Unspecified */, 1);
|
|
+ build_append_int_noprefix(tbl, 1 /* Desktop */, 1);
|
|
build_append_int_noprefix(tbl, f->sci_int, 2); /* SCI_INT */
|
|
build_append_int_noprefix(tbl, f->smi_cmd, 4); /* SMI_CMD */
|
|
build_append_int_noprefix(tbl, f->acpi_enable_cmd, 1); /* ACPI_ENABLE */
|
|
@@ -2585,7 +2584,7 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
|
}
|
|
|
|
/* Hypervisor Vendor Identity */
|
|
- build_append_padded_str(tbl, "QEMU", 8, '\0');
|
|
+ build_append_int_noprefix(tbl, 0, 8);
|
|
|
|
/* TODO: extra fields need to be added to support revisions above rev6 */
|
|
assert(f->rev == 6);
|
|
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
|
|
index eaff025..9c3b434 100644
|
|
--- a/include/hw/acpi/aml-build.h
|
|
+++ b/include/hw/acpi/aml-build.h
|
|
@@ -5,8 +5,8 @@
|
|
#include "hw/acpi/bios-linker-loader.h"
|
|
#include "hw/core/cpu.h"
|
|
|
|
-#define ACPI_BUILD_APPNAME6 "BOCHS "
|
|
-#define ACPI_BUILD_APPNAME8 "BXPC "
|
|
+#define ACPI_BUILD_APPNAME6 "ALASKA"
|
|
+#define ACPI_BUILD_APPNAME8 "A M I "
|
|
|
|
#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables"
|
|
#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp"
|
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
|
index 71fe6b5..755c9d8 100644
|
|
--- a/include/hw/i386/x86.h
|
|
+++ b/include/hw/i386/x86.h
|
|
@@ -136,7 +136,7 @@ bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms);
|
|
|
|
/* Global System Interrupts */
|
|
|
|
-#define ACPI_BUILD_PCI_IRQS ((1<<5) | (1<<9) | (1<<10) | (1<<11))
|
|
+#define ACPI_BUILD_PCI_IRQS ((1<<4) | (1<<5) | (1<<6) | (1<<10) | (1<<11) | (1<<14) | (1<<15))
|
|
|
|
typedef struct GSIState {
|
|
qemu_irq i8259_irq[ISA_NUM_IRQS];
|
|
diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c
|
|
index e66784c..8f748f9 100644
|
|
--- a/hw/pci-host/gpex.c
|
|
+++ b/hw/pci-host/gpex.c
|
|
@@ -243,8 +243,8 @@ static void gpex_root_class_init(ObjectClass *klass, const void *data)
|
|
|
|
dc->desc = "QEMU generic PCIe host bridge";
|
|
dc->vmsd = &vmstate_gpex_root;
|
|
- k->vendor_id = PCI_VENDOR_ID_REDHAT;
|
|
- k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_HOST;
|
|
+ k->vendor_id = PCI_VENDOR_ID_AMD;
|
|
+ k->device_id = PCI_DEVICE_ID_INTEL_P35_MCH;
|
|
k->revision = 0;
|
|
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
|
/*
|