ref: move acpi files

This commit is contained in:
Katharina 2026-07-02 20:07:04 +02:00
parent 5b0cc28bc8
commit da848544c0
4 changed files with 14 additions and 3 deletions

116
kernel/include/acpi/acpi.h Normal file
View file

@ -0,0 +1,116 @@
#pragma once
#include "memory/pointer.h"
#include "util/number.h"
namespace acpi {
constexpr uint32_t fold_signature(const char (&text)[5]) {
return static_cast<uint32_t>(static_cast<uint8_t>(text[0])) |
static_cast<uint32_t>(static_cast<uint8_t>(text[1])) << 8 |
static_cast<uint32_t>(static_cast<uint8_t>(text[2])) << 16 |
static_cast<uint32_t>(static_cast<uint8_t>(text[3])) << 24;
}
enum class signature : uint32_t {
fadt = fold_signature("FACP"),
madt = fold_signature("APIC"),
hpet = fold_signature("HPET"),
mcfg = fold_signature("MCFG"),
srat = fold_signature("SRAT"),
ssdt = fold_signature("SSDT"),
};
struct signature_text_t {
char text[5];
};
inline signature_text_t unfold_signature(uint32_t folded) {
signature_text_t result{};
memcpy(result.text, &folded, 4);
result.text[4] = '\0';
return result;
}
struct sdt_header_t {
uint32_t signature;
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oem_id[6];
char oem_table_id[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
} __attribute__((packed));
static_assert(sizeof(sdt_header_t) == 36);
struct rsdp_t {
char signature[8];
uint8_t checksum;
char oem_id[6];
uint8_t revision;
uint32_t rsdt_address;
uint32_t length;
uint64_t xsdt_address;
uint8_t extended_checksum;
uint8_t reserved[3];
} __attribute__((packed));
static_assert(sizeof(rsdp_t) == 36);
struct madt_t;
struct Rsdp {
explicit Rsdp(paddr_t rsdp_physical) : physical(rsdp_physical) {}
template<typename Fn>
void for_each_table(Fn&& callback) {
auto root = root_table().access<sdt_header_t>();
auto entry_size = uses_xsdt() ? 8 : 4;
auto count = (root->length - sizeof(sdt_header_t)) / entry_size;
auto entries = reinterpret_cast<const uint8_t*>(root) + sizeof(sdt_header_t);
for (auto index = 0u; index < count; index++) {
uint64_t table_physical = 0;
memcpy(&table_physical, entries + index * entry_size, entry_size);
dispatch(paddr_t{table_physical}.access<sdt_header_t>(), callback);
}
}
private:
template<typename Fn>
static void dispatch(const sdt_header_t* header, Fn&& fn) {
#define ACPI_DISPATCH(signature_enum, TableType) \
case signature::signature_enum: \
if constexpr (requires { fn(static_cast<const TableType*>(nullptr)); }) { \
fn(reinterpret_cast<const TableType*>(header)); \
return; \
} \
break;
switch (static_cast<signature>(header->signature)) {
ACPI_DISPATCH(madt, madt_t)
default:
break;
}
#undef ACPI_DISPATCH
if constexpr (requires { fn(static_cast<const sdt_header_t*>(nullptr)); }) {
fn(header);
}
}
bool uses_xsdt() {
return physical.access<rsdp_t>()->revision >= 2;
}
paddr_t root_table() {
auto rsdp = physical.access<rsdp_t>();
return uses_xsdt() ? paddr_t{rsdp->xsdt_address} : paddr_t{rsdp->rsdt_address};
}
paddr_t physical;
};
} // namespace acpi

192
kernel/include/acpi/madt.h Normal file
View file

@ -0,0 +1,192 @@
#pragma once
#include "acpi/acpi.h"
#include "memory/pointer.h"
#include "util/number.h"
namespace acpi {
enum class madt_entry_type : uint8_t {
local_apic = 0,
io_apic = 1,
interrupt_source_override = 2,
nmi_source = 3,
local_apic_nmi = 4,
local_apic_address_override = 5,
};
inline constexpr const char* get_madt_entry_type_name(madt_entry_type type) {
switch (type) {
case madt_entry_type::local_apic:
return "local_apic";
case madt_entry_type::io_apic:
return "io_apic";
case madt_entry_type::interrupt_source_override:
return "interrupt_source_override";
case madt_entry_type::nmi_source:
return "nmi_source";
case madt_entry_type::local_apic_nmi:
return "local_apic_nmi";
case madt_entry_type::local_apic_address_override:
return "local_apic_address_override";
}
return "unknown";
}
struct madt_flags_t {
uint32_t dual_8259_present : 1;
uint32_t reserved : 31;
};
static_assert(sizeof(madt_flags_t) == 4);
struct local_apic_flags_t {
uint32_t enabled : 1;
uint32_t online_capable : 1;
uint32_t reserved : 30;
};
static_assert(sizeof(local_apic_flags_t) == 4);
enum class inti_polarity : uint16_t {
bus_default = 0,
active_high = 1,
active_low = 3,
};
enum class inti_trigger_mode : uint16_t {
bus_default = 0,
edge = 1,
level = 3,
};
struct inti_flags_t {
inti_polarity polarity : 2;
inti_trigger_mode trigger_mode : 2;
uint16_t reserved : 12;
};
static_assert(sizeof(inti_flags_t) == 2);
struct madt_t {
sdt_header_t header;
uint32_t local_apic_address;
madt_flags_t flags;
uint8_t entries[0];
} __attribute__((packed));
static_assert(sizeof(madt_t) == 44);
struct madt_entry_t {
madt_entry_type type;
uint8_t length;
} __attribute__((packed));
static_assert(sizeof(madt_entry_t) == 2);
struct madt_local_apic_t {
madt_entry_type type;
uint8_t length;
uint8_t acpi_processor_uid;
uint8_t apic_id;
local_apic_flags_t flags;
} __attribute__((packed));
static_assert(sizeof(madt_local_apic_t) == 8);
struct madt_io_apic_t {
madt_entry_type type;
uint8_t length;
uint8_t io_apic_id;
uint8_t reserved;
uint32_t io_apic_address;
uint32_t global_system_interrupt_base;
} __attribute__((packed));
static_assert(sizeof(madt_io_apic_t) == 12);
struct madt_interrupt_source_override_t {
madt_entry_type type;
uint8_t length;
uint8_t bus; // always 0 (ISA)
uint8_t source; // ISA IRQ number
uint32_t global_system_interrupt;
inti_flags_t flags;
} __attribute__((packed));
static_assert(sizeof(madt_interrupt_source_override_t) == 10);
struct madt_nmi_source_t {
madt_entry_type type;
uint8_t length;
inti_flags_t flags;
uint32_t global_system_interrupt;
} __attribute__((packed));
static_assert(sizeof(madt_nmi_source_t) == 8);
struct madt_local_apic_nmi_t {
madt_entry_type type;
uint8_t length;
uint8_t acpi_processor_uid; // 0xFF: applies to all processors
inti_flags_t flags;
uint8_t lint; // local APIC LINT# the NMI is wired to
} __attribute__((packed));
static_assert(sizeof(madt_local_apic_nmi_t) == 6);
struct madt_local_apic_address_override_t {
madt_entry_type type;
uint8_t length;
uint16_t reserved;
uint64_t local_apic_address;
} __attribute__((packed));
static_assert(sizeof(madt_local_apic_address_override_t) == 12);
struct Madt {
explicit Madt(paddr_t madt_physical) : table(madt_physical.access<madt_t>()) {}
explicit Madt(const madt_t* madt_table) : table(madt_table) {}
paddr_t local_apic_address() {
uint64_t address = table->local_apic_address;
for_each_entry([&](const madt_local_apic_address_override_t* override_entry) {
address = override_entry->local_apic_address;
});
return paddr_t{address};
}
bool has_legacy_pic() {
return table->flags.dual_8259_present != 0;
}
template<typename Fn>
void for_each_entry(Fn&& callback) {
auto ptr = table->entries;
const auto end = reinterpret_cast<const uint8_t*>(table) + table->header.length;
while (ptr < end) {
auto entry = reinterpret_cast<const madt_entry_t*>(ptr);
if (entry->length < sizeof(madt_entry_t)) {
break;
}
dispatch(entry, callback);
ptr += entry->length;
}
}
private:
template<typename Fn>
static void dispatch(const madt_entry_t* entry, Fn&& fn) {
#define MADT_DISPATCH(entry_enum, EntryType) \
case madt_entry_type::entry_enum: \
if constexpr (requires { fn(static_cast<const EntryType*>(nullptr)); }) \
fn(reinterpret_cast<const EntryType*>(entry)); \
break;
switch (entry->type) {
MADT_DISPATCH(local_apic, madt_local_apic_t)
MADT_DISPATCH(io_apic, madt_io_apic_t)
MADT_DISPATCH(interrupt_source_override, madt_interrupt_source_override_t)
MADT_DISPATCH(nmi_source, madt_nmi_source_t)
MADT_DISPATCH(local_apic_nmi, madt_local_apic_nmi_t)
MADT_DISPATCH(local_apic_address_override, madt_local_apic_address_override_t)
default:
break;
}
#undef MADT_DISPATCH
}
const madt_t* table;
};
} // namespace acpi