diff options
author | Gleb Natapov <gleb@redhat.com> | 2009-03-02 12:15:59 +0200 |
---|---|---|
committer | Eduardo Habkost <ehabkost@redhat.com> | 2009-03-02 15:14:33 -0300 |
commit | 8c62ae0b4ff06bb1f8988c3060144860361e5744 (patch) | |
tree | 0581f6ff8e4fbb0a29299f92ffa0a16bda121a74 /bios | |
parent | c6325fd4b856e3bc939eb754470cee4aadc9f279 (diff) |
Allow additions of ACPI tables from command line
qemu commit: 8a92ea2f2c7b3e185ef6f4d8d3c376b752275ec7
This is needed to dynamically add SLIC tables with Windows
activation keys.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Bugzilla: 488041
Acked-by: Eduardo Habkost <ehabkost@redhat.com>
Acked-by: Marcelo Tosatti <mtosatti@redhat.com
Diffstat (limited to 'bios')
-rwxr-xr-x | bios/rombios32.c | 73 |
1 files changed, 57 insertions, 16 deletions
diff --git a/bios/rombios32.c b/bios/rombios32.c index f73eb1b1..45c86167 100755 --- a/bios/rombios32.c +++ b/bios/rombios32.c @@ -475,6 +475,8 @@ void wrmsr_smp(uint32_t index, uint64_t val) #define QEMU_CFG_SIGNATURE 0x00 #define QEMU_CFG_ID 0x01 #define QEMU_CFG_UUID 0x02 +#define QEMU_CFG_ARCH_LOCAL 0x8000 +#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0) int qemu_cfg_port; @@ -502,6 +504,27 @@ void qemu_cfg_read(uint8_t *buf, int len) while (len--) *(buf++) = inb(QEMU_CFG_DATA_PORT); } + +static uint16_t acpi_additional_tables(void) +{ + uint16_t cnt; + + qemu_cfg_select(QEMU_CFG_ACPI_TABLES); + qemu_cfg_read((uint8_t*)&cnt, sizeof(cnt)); + + return cnt; +} + +static int acpi_load_table(int i, uint32_t addr, uint16_t *len) +{ + qemu_cfg_read((uint8_t*)len, sizeof(*len)); + + if (!*len) + return -1; + + qemu_cfg_read((uint8_t*)addr, *len); + return 0; +} #endif void uuid_probe(void) @@ -1466,8 +1489,8 @@ void acpi_bios_init(void) struct multiple_apic_table *madt; uint8_t *dsdt; uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr; - uint32_t acpi_tables_size, madt_addr, madt_size; - int i; + uint32_t acpi_tables_size, madt_addr, madt_size, rsdt_size; + int i, external_tables; /* reserve memory space for tables */ #ifdef BX_USE_EBDA_TABLES @@ -1480,10 +1503,17 @@ void acpi_bios_init(void) bios_table_cur_addr += sizeof(*rsdp); #endif +#ifdef BX_QEMU + external_tables = acpi_additional_tables(); +#else + external_tables = 0; +#endif + addr = base_addr = ram_size - ACPI_DATA_SIZE; rsdt_addr = addr; rsdt = (void *)(addr); - addr += sizeof(*rsdt); + rsdt_size = sizeof(*rsdt) + external_tables * 4; + addr += rsdt_size; fadt_addr = addr; fadt = (void *)(addr); @@ -1507,12 +1537,6 @@ void acpi_bios_init(void) madt = (void *)(addr); addr += madt_size; - acpi_tables_size = addr - base_addr; - - BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n", - (unsigned long)rsdp, - (unsigned long)rsdt, acpi_tables_size); - /* RSDP */ memset(rsdp, 0, sizeof(*rsdp)); memcpy(rsdp->signature, "RSD PTR ", 8); @@ -1524,13 +1548,6 @@ void acpi_bios_init(void) rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr); rsdp->checksum = acpi_checksum((void *)rsdp, 20); - /* RSDT */ - memset(rsdt, 0, sizeof(*rsdt)); - rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr); - rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr); - acpi_build_table_header((struct acpi_table_header *)rsdt, - "RSDT", sizeof(*rsdt), 1); - /* FADT */ memset(fadt, 0, sizeof(*fadt)); fadt->firmware_ctrl = cpu_to_le32(facs_addr); @@ -1612,6 +1629,30 @@ void acpi_bios_init(void) acpi_build_table_header((struct acpi_table_header *)madt, "APIC", madt_size, 1); } + + memset(rsdt, 0, rsdt_size); + acpi_additional_tables(); /* resets cfg to required entry */ + for(i = 0; i < external_tables; i++) { + uint16_t len; + if(acpi_load_table(i, addr, &len) < 0) + BX_PANIC("Failed to load ACPI table from QEMU\n"); + rsdt->table_offset_entry[i+2] = cpu_to_le32(addr); + addr += len; + if(addr >= ram_size) + BX_PANIC("ACPI table overflow\n"); + } + + /* RSDT */ + rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr); + rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr); + acpi_build_table_header((struct acpi_table_header *)rsdt, + "RSDT", rsdt_size, 1); + + acpi_tables_size = addr - base_addr; + + BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n", + (unsigned long)rsdp, + (unsigned long)rsdt, acpi_tables_size); } /* SMBIOS entry point -- must be written to a 16-bit aligned address |