diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-04-06 19:04:40 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-04-06 19:04:40 +0200 |
| commit | fe26083101537df306153e7bea7c291a041897f7 (patch) | |
| tree | 0f26687fb172fc1852e9c4d58c351a76e9ceb50c /kernel/src/acpi/manager.cpp | |
| parent | 2a3575a267dede6a364386c0bd6edcff92421f0d (diff) | |
| parent | d5c2e101d62f6b4b69c45c127e7a729d246da566 (diff) | |
| download | teachos-fe26083101537df306153e7bea7c291a041897f7.tar.xz teachos-fe26083101537df306153e7bea7c291a041897f7.zip | |
Merge branch 'fmorgner/develop-BA-FS26/apci' into develop-BA-FS26
This patchset introduces basic support for ACPI. Currently, the only
user of that support is the CPU discovery subsystem. It uses the
processed ACPI information to initialize CPU core devices and their
associated local APICs.
Diffstat (limited to 'kernel/src/acpi/manager.cpp')
| -rw-r--r-- | kernel/src/acpi/manager.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp new file mode 100644 index 0000000..300b85e --- /dev/null +++ b/kernel/src/acpi/manager.cpp @@ -0,0 +1,103 @@ +#include "kernel/acpi/manager.hpp" + +#include "kapi/acpi.hpp" +#include "kapi/memory.hpp" +#include "kapi/system.hpp" + +#include <kstd/memory> +#include <kstd/print> + +#include <cstddef> +#include <cstdint> +#include <string_view> + +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<kapi::acpi::extended_system_description_pointer const *>(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<kapi::acpi::system_description_table_header const *>(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<kapi::acpi::system_description_table_header const *>(linear_root_table_address); + } + } + + auto manager::load_tables() -> bool + { + if (!kapi::acpi::validate_checksum({reinterpret_cast<std::byte const *>(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<std::byte const *>(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<std::uint64_t const *>(entries_base + (i * entry_size)); + physical_table_address = kapi::memory::physical_address{*entry}; + } + else + { + auto entry = reinterpret_cast<std::uint32_t const *>(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<kapi::acpi::system_description_table_header const *>(linear_table_address); + + if (!kapi::acpi::validate_checksum({reinterpret_cast<std::byte const *>(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); + } + } + + return !m_tables.empty(); + } + + auto manager::get_table(std::string_view signature) + -> kstd::observer_ptr<kapi::acpi::system_description_table_header const> + { + if (m_tables.contains(signature)) + { + return kstd::make_observer(m_tables.at(signature)); + } + return nullptr; + } + +} // namespace kernel::acpi |
