#include "kernel/acpi/manager.hpp" #include "kapi/acpi.hpp" #include "kapi/memory.hpp" #include "kapi/system.hpp" #include #include #include namespace kernel::acpi { manager::manager(kapi::acpi::root_system_description_pointer const & sdp) : m_sdp{&sdp} { if (m_sdp->signature() != "RSD PTR ") { kapi::system::panic("[OS:ACPI] Invalid RSDP signature!"); } if (m_sdp->revision() >= 2) { auto const xsdp = static_cast(m_sdp); if (!xsdp->validate()) { kapi::system::panic("[OS:ACPI] Invalid XSDP signature!"); } auto physical_extended_table_address = xsdp->table_address(); auto linear_extended_table_address = kapi::memory::hhdm_to_linear(physical_extended_table_address); m_rsdt = static_cast(linear_extended_table_address); m_extended = true; } else { if (!m_sdp->validate()) { kapi::system::panic("[OS:ACPI] Invalid RSDP checksum!"); } auto physical_root_table_address = m_sdp->table_address(); auto linear_root_table_address = kapi::memory::hhdm_to_linear(physical_root_table_address); m_rsdt = static_cast(linear_root_table_address); } } auto manager::load_tables() -> bool { if (!kapi::acpi::validate_checksum({reinterpret_cast(m_rsdt), m_rsdt->length().value})) { kapi::system::panic("[OS:ACPI] Invalid RSDT checksum!"); } auto entry_size = m_extended ? sizeof(std::uint64_t) : sizeof(std::uint32_t); auto entry_count = (m_rsdt->length().value - sizeof(kapi::acpi::system_description_table_header)) / entry_size; auto entries_base = reinterpret_cast(m_rsdt) + sizeof(kapi::acpi::system_description_table_header); for (std::size_t i = 0; i < entry_count; ++i) { auto physical_table_address = kapi::memory::physical_address{}; if (m_extended) { auto entry = reinterpret_cast(entries_base + (i * entry_size)); physical_table_address = kapi::memory::physical_address{*entry}; } else { auto entry = reinterpret_cast(entries_base + (i * entry_size)); physical_table_address = kapi::memory::physical_address{*entry}; } auto linear_table_address = kapi::memory::hhdm_to_linear(physical_table_address); auto table = static_cast(linear_table_address); if (!kapi::acpi::validate_checksum({reinterpret_cast(table), table->length().value})) { kstd::println(kstd::print_sink::stderr, "[OS:ACPI] Invalid table checksum!"); } else { kstd::println("[OS:ACPI] Found table: {}@{:#x}/{:#x} OEM: {} Rev: {}", table->signature(), linear_table_address, physical_table_address, table->oem_id(), table->creator_revision()); m_tables.emplace(table->signature(), table); } } return !m_tables.empty(); } } // namespace kernel::acpi