Move parsing of ACPI tables into table structures

Move mapping ACPI table memory into common location
This commit is contained in:
Josh Holtrop 2023-09-17 09:08:01 -04:00
parent e088f942d1
commit 10d7e7f0c6

View File

@ -42,6 +42,8 @@ struct Acpi
{ {
static struct Entry static struct Entry
{ {
enum LOCAL_APIC_ADDRESS_OVERRIDE = 5;
ubyte type; ubyte type;
ubyte length; ubyte length;
} }
@ -49,6 +51,24 @@ struct Acpi
Header header; Header header;
uint local_apic_address; uint local_apic_address;
uint flags; uint flags;
void initialize()
{
apic_address = local_apic_address;
Klog.writefln("Found 32-bit APIC address: 0x%x", apic_address);
const(void) * end = cast(const(void) *)(&this) + header.length;
const(Entry) * entry = cast(const(Entry) *)(cast(ulong)&this + MADT.sizeof);
while (entry < end)
{
entry = cast(const(Entry) *)(cast(size_t)entry + entry.length);
if (entry.type == Entry.LOCAL_APIC_ADDRESS_OVERRIDE)
{
/* Found a 64-bit Local APIC Address Override entry. */
Klog.writefln("Found 64-bit APIC address: 0x%x", apic_address);
memcpy(cast(void *)&apic_address, cast(const(void) *)entry + 4u, apic_address.sizeof);
}
}
}
} }
static struct MCFG static struct MCFG
@ -73,6 +93,22 @@ struct Acpi
Header header; Header header;
uint[2] _reserved; uint[2] _reserved;
SGMADesc[0] sgma_descs; SGMADesc[0] sgma_descs;
void initialize()
{
Klog.writefln("MCFG length = %u", header.length);
size_t n_sgma_descs = (header.length - MCFG.sgma_descs.offsetof) / MCFG.SGMADesc.sizeof;
Klog.writefln("# SGMA descriptors = %u", (header.length - MCFG.sgma_descs.offsetof) / MCFG.SGMADesc.sizeof);
for (size_t i = 0; i < n_sgma_descs; i++)
{
Klog.writefln("SGMA %u: SG %u; Bus %u-%u; addr %p",
i,
sgma_descs[i].pci_segment_group_number,
sgma_descs[i].start_pci_bus_number,
sgma_descs[i].end_pci_bus_number,
sgma_descs[i].base_address);
}
}
} }
public static __gshared ulong apic_address; public static __gshared ulong apic_address;
@ -80,7 +116,7 @@ struct Acpi
public static void initialize(ulong acpi_xsdt_phys) public static void initialize(ulong acpi_xsdt_phys)
{ {
/* Map the XSDT header. */ /* Map the XSDT header. */
Hurl.identity_map_range(acpi_xsdt_phys, XSDT.sizeof, 0u); Hurl.identity_map_range(acpi_xsdt_phys, PAGE_SIZE, 0u);
const(XSDT) * xsdt = cast(const(XSDT) *)acpi_xsdt_phys; const(XSDT) * xsdt = cast(const(XSDT) *)acpi_xsdt_phys;
if (xsdt.header.signature != XSDT_SIGNATURE) if (xsdt.header.signature != XSDT_SIGNATURE)
{ {
@ -88,13 +124,22 @@ struct Acpi
return; return;
} }
/* Map the entire XSDT. */ /* Map the entire XSDT. */
if (xsdt.header.length > PAGE_SIZE)
{
Hurl.identity_map_range(acpi_xsdt_phys, xsdt.header.length, 0u); Hurl.identity_map_range(acpi_xsdt_phys, xsdt.header.length, 0u);
}
size_t n_entries = (xsdt.header.length - xsdt.header.sizeof) / xsdt.tables[0].sizeof; size_t n_entries = (xsdt.header.length - xsdt.header.sizeof) / xsdt.tables[0].sizeof;
for (size_t i = 0u; i < n_entries; i++) for (size_t i = 0u; i < n_entries; i++)
{ {
ulong address = xsdt.tables[i]; ulong address = xsdt.tables[i];
Hurl.identity_map_range(address, 4u, 0u); Hurl.identity_map_range(address, PAGE_SIZE, 0u);
uint signature = *cast(const(uint) *)address; const(Header) * header = cast(const(Header) *)address;
uint length = header.length;
if (length > PAGE_SIZE)
{
Hurl.identity_map_range(address, length, 0u);
}
uint signature = header.signature;
Klog.writefln("Found ACPI table %08x (%c%c%c%c)", Klog.writefln("Found ACPI table %08x (%c%c%c%c)",
signature, signature,
signature & 0xFFu, signature & 0xFFu,
@ -103,50 +148,12 @@ struct Acpi
(signature >> 24u) & 0xFFu); (signature >> 24u) & 0xFFu);
if (signature == APIC_SIGNATURE) if (signature == APIC_SIGNATURE)
{ {
parse_apic_table(address); (cast(MADT *)address).initialize();
} }
else if (signature == MCFG_SIGNATURE) else if (signature == MCFG_SIGNATURE)
{ {
parse_mcfg_table(address); (cast(MCFG *)address).initialize();
} }
} }
} }
private static parse_apic_table(ulong address)
{
const(MADT) * madt = cast(const(MADT) *)address;
Hurl.identity_map_range(address, madt.header.length, 0u);
apic_address = madt.local_apic_address;
Klog.writefln("Found 32-bit APIC address: 0x%x", apic_address);
const(void) * madt_end = cast(const(void) *)(address + madt.header.length);
const(MADT.Entry) * madt_entry = cast(const(MADT.Entry) *)(address + MADT.sizeof);
while (madt_entry < madt_end)
{
madt_entry = cast(const(MADT.Entry) *)(cast(size_t)madt_entry + madt_entry.length);
if (madt_entry.type == 5u)
{
/* Found a 64-bit Local APIC Address Override entry. */
Klog.writefln("Found 64-bit APIC address: 0x%x", apic_address);
memcpy(cast(void *)&apic_address, cast(const(void) *)madt_entry + 4u, 8u);
}
}
}
private static parse_mcfg_table(ulong address)
{
const(MCFG) * mcfg = cast(const(MCFG) *)address;
Hurl.identity_map_range(address, mcfg.header.length, 0u);
Klog.writefln("MCFG length = %u", mcfg.header.length);
size_t n_sgma_descs = (mcfg.header.length - MCFG.sgma_descs.offsetof) / MCFG.SGMADesc.sizeof;
Klog.writefln("# SGMA descriptors = %u", (mcfg.header.length - MCFG.sgma_descs.offsetof) / MCFG.SGMADesc.sizeof);
for (size_t i = 0; i < n_sgma_descs; i++)
{
Klog.writefln("SGMA %u: SG %u; Bus %u-%u; addr %p",
i,
mcfg.sgma_descs[i].pci_segment_group_number,
mcfg.sgma_descs[i].start_pci_bus_number,
mcfg.sgma_descs[i].end_pci_bus_number,
mcfg.sgma_descs[i].base_address);
}
}
} }