#include #include #include #include #include #include #include #include #include #include #include namespace kernel::acpi { manager::manager(::acpi::rsdp const & sdp) : m_sdp{&sdp} { if (!m_sdp->validate()) { kapi::system::panic("[OS:ACPI] Invalid RSDP signature!"); } m_extended = m_sdp->revision() >= 2; if (m_extended) { if (!static_cast<::acpi::xsdp const *>(m_sdp)->validate()) { kapi::system::panic("[OS:ACPI] Invalid XSDP signature!"); } } else { if (!m_sdp->validate()) { kapi::system::panic("[OS:ACPI] Invalid RSDP checksum!"); } } auto physical_address = kapi::memory::physical_address{m_sdp->table_address()}; auto linear_address = kapi::memory::hhdm_to_linear(physical_address); m_rsdt = static_cast<::acpi::table_header const *>(linear_address); } auto manager::load_tables() -> bool { if (!::acpi::validate_checksum({reinterpret_cast(m_rsdt), m_rsdt->length().value})) { kapi::system::panic("[OS:ACPI] Invalid RSDT checksum!"); } auto check_and_register_table = [&](auto table_address) -> void { auto physical_table_address = kapi::memory::physical_address{reinterpret_cast(table_address)}; auto mapped_table = kapi::memory::hhdm_to_linear(physical_table_address); auto table = static_cast<::acpi::table_header const *>(mapped_table); if (!::acpi::validate_checksum({static_cast(mapped_table), table->length().value})) { kstd::println(kstd::print_sink::stderr, "[OS:ACPI] Invalid table checksum!"); } else { kstd::println("[OS:ACPI] Found '{}' ACPI table", table->signature()); m_tables.emplace(table->signature(), table); } }; if (m_extended) { auto xsdt = static_cast<::acpi::xsdt const *>(m_rsdt); std::ranges::for_each(*xsdt | std::views::transform([](auto const & entry) { return entry.address(); }), check_and_register_table); } else { auto rsdt = static_cast<::acpi::rsdt const *>(m_rsdt); std::ranges::for_each(*rsdt | std::views::transform([](auto const & entry) { return entry.address(); }), check_and_register_table); } return !m_tables.empty(); } auto manager::get_table(std::string_view signature) -> kstd::observer_ptr<::acpi::table_header const> { if (m_tables.contains(signature)) { return kstd::make_observer(m_tables.at(signature)); } return nullptr; } } // namespace kernel::acpi