Compare commits
2 Commits
6514af8e94
...
10d7e7f0c6
Author | SHA1 | Date | |
---|---|---|---|
10d7e7f0c6 | |||
e088f942d1 |
134
src/hulk/acpi.d
134
src/hulk/acpi.d
@ -18,7 +18,7 @@ struct Acpi
|
||||
enum uint MCFG_SIGNATURE = signature("MCFG");
|
||||
enum uint XSDT_SIGNATURE = signature("XSDT");
|
||||
|
||||
static align(4) struct XsdtHeader
|
||||
static align(4) struct Header
|
||||
{
|
||||
uint signature;
|
||||
uint length;
|
||||
@ -31,35 +31,47 @@ struct Acpi
|
||||
uint creator_revision;
|
||||
}
|
||||
|
||||
static struct Xsdt
|
||||
static struct XSDT
|
||||
{
|
||||
XsdtHeader header;
|
||||
Header header;
|
||||
/* Table pointers are not ulong-aligned! They begin at offset 36. */
|
||||
align(4) ulong[1] tables;
|
||||
}
|
||||
|
||||
static struct MadtHeader
|
||||
static struct MADT
|
||||
{
|
||||
uint signature;
|
||||
uint length;
|
||||
ubyte revision;
|
||||
ubyte checksum;
|
||||
char[6] oemid;
|
||||
ulong oemtableid;
|
||||
uint oem_revision;
|
||||
uint creator_id;
|
||||
uint creator_revision;
|
||||
uint local_apic_address;
|
||||
uint flags;
|
||||
}
|
||||
static struct Entry
|
||||
{
|
||||
enum LOCAL_APIC_ADDRESS_OVERRIDE = 5;
|
||||
|
||||
static struct MadtEntry
|
||||
{
|
||||
ubyte type;
|
||||
ubyte length;
|
||||
}
|
||||
|
||||
static struct MCFGTable
|
||||
Header header;
|
||||
uint local_apic_address;
|
||||
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
|
||||
{
|
||||
/* PCI Segment Group Memory Area Descriptor. */
|
||||
static struct SGMADesc
|
||||
@ -78,17 +90,25 @@ struct Acpi
|
||||
static assert(SGMADesc.sizeof == 16);
|
||||
static assert(SGMADesc.alignof == 4);
|
||||
|
||||
uint signature;
|
||||
uint length;
|
||||
ubyte revision;
|
||||
ubyte checksum;
|
||||
char[6] oemid;
|
||||
ulong oemtableid;
|
||||
uint oem_revision;
|
||||
uint creator_id;
|
||||
uint creator_revision;
|
||||
Header header;
|
||||
uint[2] _reserved;
|
||||
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;
|
||||
@ -96,21 +116,30 @@ struct Acpi
|
||||
public static void initialize(ulong acpi_xsdt_phys)
|
||||
{
|
||||
/* Map the XSDT header. */
|
||||
Hurl.identity_map_range(acpi_xsdt_phys, Xsdt.sizeof, 0u);
|
||||
const(Xsdt) * xsdt = cast(const(Xsdt) *)acpi_xsdt_phys;
|
||||
Hurl.identity_map_range(acpi_xsdt_phys, PAGE_SIZE, 0u);
|
||||
const(XSDT) * xsdt = cast(const(XSDT) *)acpi_xsdt_phys;
|
||||
if (xsdt.header.signature != XSDT_SIGNATURE)
|
||||
{
|
||||
Klog.writef("XSDT signature invalid\n");
|
||||
return;
|
||||
}
|
||||
/* Map the entire XSDT. */
|
||||
if (xsdt.header.length > PAGE_SIZE)
|
||||
{
|
||||
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;
|
||||
for (size_t i = 0u; i < n_entries; i++)
|
||||
{
|
||||
ulong address = xsdt.tables[i];
|
||||
Hurl.identity_map_range(address, 4u, 0u);
|
||||
uint signature = *cast(const(uint) *)address;
|
||||
Hurl.identity_map_range(address, PAGE_SIZE, 0u);
|
||||
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)",
|
||||
signature,
|
||||
signature & 0xFFu,
|
||||
@ -119,49 +148,12 @@ struct Acpi
|
||||
(signature >> 24u) & 0xFFu);
|
||||
if (signature == APIC_SIGNATURE)
|
||||
{
|
||||
parse_apic_table(address);
|
||||
(cast(MADT *)address).initialize();
|
||||
}
|
||||
else if (signature == MCFG_SIGNATURE)
|
||||
{
|
||||
parse_mcfg_table(address);
|
||||
(cast(MCFG *)address).initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static parse_apic_table(ulong address)
|
||||
{
|
||||
const(MadtHeader) * madt_header = cast(const(MadtHeader) *)address;
|
||||
Hurl.identity_map_range(address, madt_header.length, 0u);
|
||||
apic_address = madt_header.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(MadtEntry) * madt_entry = cast(const(MadtEntry) *)(address + 0x2Cu);
|
||||
while (madt_entry < madt_end)
|
||||
{
|
||||
madt_entry = cast(const(MadtEntry) *)(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(MCFGTable) * mcfg_table = cast(const(MCFGTable) *)address;
|
||||
Hurl.identity_map_range(address, mcfg_table.length, 0u);
|
||||
Klog.writefln("MCFG length = %u", mcfg_table.length);
|
||||
size_t n_sgma_descs = (mcfg_table.length - MCFGTable.sgma_descs.offsetof) / MCFGTable.SGMADesc.sizeof;
|
||||
Klog.writefln("# SGMA descriptors = %u", (mcfg_table.length - MCFGTable.sgma_descs.offsetof) / MCFGTable.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_table.sgma_descs[i].pci_segment_group_number,
|
||||
mcfg_table.sgma_descs[i].start_pci_bus_number,
|
||||
mcfg_table.sgma_descs[i].end_pci_bus_number,
|
||||
mcfg_table.sgma_descs[i].base_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user