Store ACPI table pointers in list

This commit is contained in:
Josh Holtrop 2023-10-25 19:13:36 -04:00
parent e480bd0ed0
commit 2b87792c67

View File

@ -6,37 +6,45 @@ module hulk.acpi;
import hulk.hurl; import hulk.hurl;
import hulk.klog; import hulk.klog;
import hulk.memory; import hulk.memory;
import hulk.list;
struct Acpi struct Acpi
{ {
private static uint signature(string s) /**
{ * List of ACPI tables.
return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); */
} private static __gshared List!Header tables;
enum uint APIC_SIGNATURE = signature("APIC"); enum uint APIC_SIGNATURE = signature("APIC");
enum uint MCFG_SIGNATURE = signature("MCFG"); enum uint MCFG_SIGNATURE = signature("MCFG");
enum uint XSDT_SIGNATURE = signature("XSDT"); enum uint XSDT_SIGNATURE = signature("XSDT");
static align(4) struct Header /**
* ACPI table header structure.
*/
static struct Header
{ {
uint signature; uint signature;
uint length; uint length;
ubyte revision; ubyte revision;
ubyte checksum; ubyte checksum;
char[6] oemid; char[6] oemid;
ulong oemtableid; char[8] oemtableid;
uint oem_revision; uint oem_revision;
uint creator_id; uint creator_id;
uint creator_revision; uint creator_revision;
} }
/**
* XSDT table.
*/
static struct XSDT static struct XSDT
{ {
Header header; Header header;
/* Table pointers are not ulong-aligned! They begin at offset 36. */ /* Table pointers are not ulong-aligned! They begin at offset 36. */
align(4) ulong[1] tables; align(4) ulong[1] tables;
} }
static assert(XSDT.tables.offsetof == 36);
static struct MADT static struct MADT
{ {
@ -106,7 +114,7 @@ struct Acpi
public static void initialize(ulong acpi_xsdt_phys) public static void initialize(ulong acpi_xsdt_phys)
{ {
Klog.writefln("\a3Initialize ACPI"); Klog.writefln("\a3Initializing ACPI");
/* Map the XSDT header. */ /* Map the XSDT header. */
map_table(acpi_xsdt_phys, PAGE_SIZE); map_table(acpi_xsdt_phys, PAGE_SIZE);
@ -126,19 +134,20 @@ struct Acpi
{ {
ulong address = xsdt.tables[i]; ulong address = xsdt.tables[i];
map_table(address, PAGE_SIZE); map_table(address, PAGE_SIZE);
const(Header) * header = cast(const(Header) *)address; Header * header = cast(Header *)address;
uint length = header.length; uint length = header.length;
if (length > PAGE_SIZE) if (length > PAGE_SIZE)
{ {
map_table(address, length); map_table(address, length);
} }
tables.add(header);
uint signature = header.signature; uint signature = header.signature;
Klog.writefln("Found ACPI table %08x (%c%c%c%c)", Klog.writefln("Found ACPI table '%c%c%c%c' at %p",
signature,
signature & 0xFFu, signature & 0xFFu,
(signature >> 8u) & 0xFFu, (signature >> 8u) & 0xFFu,
(signature >> 16u) & 0xFFu, (signature >> 16u) & 0xFFu,
(signature >> 24u) & 0xFFu); (signature >> 24u) & 0xFFu,
address);
if (signature == APIC_SIGNATURE) if (signature == APIC_SIGNATURE)
{ {
madt = cast(MADT *)address; madt = cast(MADT *)address;
@ -159,8 +168,36 @@ struct Acpi
} }
} }
/**
* Get pointer to ACPI table by name.
*
* @param name
* Table name.
*/
public Header * get_table(string name)
{
uint signature = signature(name);
foreach (table; tables)
{
if (table.signature == signature)
{
return &table;
}
}
Klog.fatal_error("Could not find requested ACPI table");
return null;
}
private static void map_table(ulong address, ulong length) private static void map_table(ulong address, ulong length)
{ {
Hurl.identity_map_range(address, length, PT_WRITABLE | PT_DISABLE_CACHE | PT_NO_EXECUTE); Hurl.identity_map_range(address, length, PT_WRITABLE | PT_DISABLE_CACHE | PT_NO_EXECUTE);
} }
/**
* Convert table signature from string to 32-bit unsigned integer.
*/
private static uint signature(string s)
{
return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
}
} }