|
|
1.1 ! root 1: Read additional ACPI tables from a VM (Gleb Natapov) ! 2: ! 3: Signed-off-by: Gleb Natapov <[email protected]> ! 4: Signed-off-by: Anthony Liguori <[email protected]> ! 5: ! 6: diff --git a/bios/rombios32.c b/bios/rombios32.c ! 7: index 3269be5..191707d 100644 ! 8: --- a/bios/rombios32.c ! 9: +++ b/bios/rombios32.c ! 10: @@ -457,6 +457,8 @@ void wrmsr_smp(uint32_t index, uint64_t val) ! 11: #define QEMU_CFG_SIGNATURE 0x00 ! 12: #define QEMU_CFG_ID 0x01 ! 13: #define QEMU_CFG_UUID 0x02 ! 14: +#define QEMU_CFG_ARCH_LOCAL 0x8000 ! 15: +#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0) ! 16: ! 17: int qemu_cfg_port; ! 18: ! 19: @@ -484,6 +486,27 @@ void qemu_cfg_read(uint8_t *buf, int len) ! 20: while (len--) ! 21: *(buf++) = inb(QEMU_CFG_DATA_PORT); ! 22: } ! 23: + ! 24: +static uint16_t acpi_additional_tables(void) ! 25: +{ ! 26: + uint16_t cnt; ! 27: + ! 28: + qemu_cfg_select(QEMU_CFG_ACPI_TABLES); ! 29: + qemu_cfg_read((uint8_t*)&cnt, sizeof(cnt)); ! 30: + ! 31: + return cnt; ! 32: +} ! 33: + ! 34: +static int acpi_load_table(int i, uint32_t addr, uint16_t *len) ! 35: +{ ! 36: + qemu_cfg_read((uint8_t*)len, sizeof(*len)); ! 37: + ! 38: + if (!*len) ! 39: + return -1; ! 40: + ! 41: + qemu_cfg_read((uint8_t*)addr, *len); ! 42: + return 0; ! 43: +} ! 44: #endif ! 45: ! 46: void uuid_probe(void) ! 47: @@ -1534,8 +1557,8 @@ void acpi_bios_init(void) ! 48: uint32_t hpet_addr; ! 49: #endif ! 50: uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr, ssdt_addr; ! 51: - uint32_t acpi_tables_size, madt_addr, madt_size; ! 52: - int i; ! 53: + uint32_t acpi_tables_size, madt_addr, madt_size, rsdt_size; ! 54: + uint16_t i, external_tables; ! 55: ! 56: /* reserve memory space for tables */ ! 57: #ifdef BX_USE_EBDA_TABLES ! 58: @@ -1548,10 +1571,17 @@ void acpi_bios_init(void) ! 59: bios_table_cur_addr += sizeof(*rsdp); ! 60: #endif ! 61: ! 62: +#ifdef BX_QEMU ! 63: + external_tables = acpi_additional_tables(); ! 64: +#else ! 65: + external_tables = 0; ! 66: +#endif ! 67: + ! 68: addr = base_addr = ram_size - ACPI_DATA_SIZE; ! 69: rsdt_addr = addr; ! 70: rsdt = (void *)(addr); ! 71: - addr += sizeof(*rsdt); ! 72: + rsdt_size = sizeof(*rsdt) + external_tables * 4; ! 73: + addr += rsdt_size; ! 74: ! 75: fadt_addr = addr; ! 76: fadt = (void *)(addr); ! 77: @@ -1590,12 +1620,6 @@ void acpi_bios_init(void) ! 78: addr += sizeof(*hpet); ! 79: #endif ! 80: ! 81: - acpi_tables_size = addr - base_addr; ! 82: - ! 83: - BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n", ! 84: - (unsigned long)rsdp, ! 85: - (unsigned long)rsdt, acpi_tables_size); ! 86: - ! 87: /* RSDP */ ! 88: memset(rsdp, 0, sizeof(*rsdp)); ! 89: memcpy(rsdp->signature, "RSD PTR ", 8); ! 90: @@ -1607,17 +1631,6 @@ void acpi_bios_init(void) ! 91: rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr); ! 92: rsdp->checksum = acpi_checksum((void *)rsdp, 20); ! 93: ! 94: - /* RSDT */ ! 95: - memset(rsdt, 0, sizeof(*rsdt)); ! 96: - rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr); ! 97: - rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr); ! 98: - rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr); ! 99: -#ifdef BX_QEMU ! 100: - rsdt->table_offset_entry[3] = cpu_to_le32(hpet_addr); ! 101: -#endif ! 102: - acpi_build_table_header((struct acpi_table_header *)rsdt, ! 103: - "RSDT", sizeof(*rsdt), 1); ! 104: - ! 105: /* FADT */ ! 106: memset(fadt, 0, sizeof(*fadt)); ! 107: fadt->firmware_ctrl = cpu_to_le32(facs_addr); ! 108: @@ -1692,6 +1705,7 @@ void acpi_bios_init(void) ! 109: "APIC", madt_size, 1); ! 110: } ! 111: ! 112: + memset(rsdt, 0, rsdt_size); ! 113: #ifdef BX_QEMU ! 114: /* HPET */ ! 115: memset(hpet, 0, sizeof(*hpet)); ! 116: @@ -1702,7 +1716,34 @@ void acpi_bios_init(void) ! 117: hpet->addr.address = cpu_to_le32(ACPI_HPET_ADDRESS); ! 118: acpi_build_table_header((struct acpi_table_header *)hpet, ! 119: "HPET", sizeof(*hpet), 1); ! 120: + ! 121: + acpi_additional_tables(); /* resets cfg to required entry */ ! 122: + for(i = 0; i < external_tables; i++) { ! 123: + uint16_t len; ! 124: + if(acpi_load_table(i, addr, &len) < 0) ! 125: + BX_PANIC("Failed to load ACPI table from QEMU\n"); ! 126: + rsdt->table_offset_entry[i+4] = cpu_to_le32(addr); ! 127: + addr += len; ! 128: + if(addr >= ram_size) ! 129: + BX_PANIC("ACPI table overflow\n"); ! 130: + } ! 131: +#endif ! 132: + ! 133: + /* RSDT */ ! 134: + rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr); ! 135: + rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr); ! 136: + rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr); ! 137: +#ifdef BX_QEMU ! 138: + rsdt->table_offset_entry[3] = cpu_to_le32(hpet_addr); ! 139: #endif ! 140: + acpi_build_table_header((struct acpi_table_header *)rsdt, ! 141: + "RSDT", rsdt_size, 1); ! 142: + ! 143: + acpi_tables_size = addr - base_addr; ! 144: + ! 145: + BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n", ! 146: + (unsigned long)rsdp, ! 147: + (unsigned long)rsdt, acpi_tables_size); ! 148: ! 149: } ! 150: ! 151: -- ! 152: Gleb. ! 153: ! 154: ! 155:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.