aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-04-06 14:47:37 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-04-06 15:11:47 +0200
commit3dcd14a0570fef3bcc68d7df42fe3ff4cd496f93 (patch)
treef778c1b23cf63296aab769a02781f83fb7f1ac53
parent6e54333bcc08ddd8dbcb6aa9c3404001c309ec74 (diff)
downloadteachos-3dcd14a0570fef3bcc68d7df42fe3ff4cd496f93.tar.xz
teachos-3dcd14a0570fef3bcc68d7df42fe3ff4cd496f93.zip
kapi: hook ACPI initialization up to boot process
-rw-r--r--.vscode/settings.json6
-rw-r--r--arch/x86_64/kapi/devices.cpp32
-rw-r--r--kapi/include/kapi/acpi.hpp44
-rw-r--r--kapi/include/kapi/memory/layout.hpp12
-rw-r--r--kernel/CMakeLists.txt1
-rw-r--r--kernel/include/kernel/acpi/manager.hpp26
-rw-r--r--kernel/kapi/acpi.cpp32
-rw-r--r--kernel/src/acpi/manager.cpp54
8 files changed, 186 insertions, 21 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 4271526..6ea3c79 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -32,6 +32,7 @@
"crtp",
"efer",
"functors",
+ "hhdm",
"idtr",
"initializable",
"interprocedural",
@@ -43,6 +44,7 @@
"malloc",
"memcmp",
"memset",
+ "mmio",
"multiboot",
"nodiscard",
"nolintnextline",
@@ -51,12 +53,14 @@
"raii",
"rdmsr",
"RSDP",
+ "rsdt",
"rvalues",
"stringview",
"sysret",
"teachos",
"undelegated",
- "wrmsr"
+ "wrmsr",
+ "xsdp"
],
"testMate.cpp.debug.configTemplate": {
"type": "cppdbg",
diff --git a/arch/x86_64/kapi/devices.cpp b/arch/x86_64/kapi/devices.cpp
index b15503d..e1773e7 100644
--- a/arch/x86_64/kapi/devices.cpp
+++ b/arch/x86_64/kapi/devices.cpp
@@ -1,5 +1,9 @@
#include "kapi/devices.hpp"
+#include "kapi/acpi.hpp"
+#include "kapi/boot.hpp"
+
+#include "arch/boot/boot.hpp"
#include "arch/bus/isa.hpp"
#include "arch/devices/legacy_pit.hpp"
@@ -19,7 +23,33 @@ namespace kapi::devices
auto init_platform_devices() -> void
{
- kstd::println("[x86_64:devices] Initializing ISA bus...");
+ auto const & mbi = boot::bootstrap_information.mbi;
+ auto system_description_pointer = static_cast<acpi::root_system_description_pointer const *>(nullptr);
+
+ if (auto const & xsdp = mbi->maybe_acpi_xsdp())
+ {
+ auto data = xsdp->pointer().data();
+ system_description_pointer = reinterpret_cast<kapi::acpi::root_system_description_pointer const *>(data);
+ }
+ else if (auto const & rsdp = mbi->maybe_acpi_rsdp())
+ {
+ auto data = rsdp->pointer().data();
+ system_description_pointer = reinterpret_cast<kapi::acpi::root_system_description_pointer const *>(data);
+ }
+
+ if (system_description_pointer)
+ {
+ if (!kapi::acpi::init(*system_description_pointer))
+ {
+ kstd::println(kstd::print_sink::stderr, "[x86_64:DEV] ACPI initialization failed. No tables loaded.");
+ }
+ }
+ else
+ {
+ kstd::println(kstd::print_sink::stderr, "[x86_64:DEV] No ACPI RSDP found. Most devices will not be available.");
+ }
+
+ kstd::println("[x86_64:DEV] Initializing ISA bus...");
auto isa_major_number = kapi::devices::allocate_major_number();
auto isa_bus = kstd::make_unique<arch::bus::isa>(isa_major_number);
diff --git a/kapi/include/kapi/acpi.hpp b/kapi/include/kapi/acpi.hpp
index 1068921..d5e3c87 100644
--- a/kapi/include/kapi/acpi.hpp
+++ b/kapi/include/kapi/acpi.hpp
@@ -2,16 +2,36 @@
#define TEACHOS_KAPI_ACPI_HPP
#include "kapi/memory.hpp"
+
#include <kstd/units>
#include <array>
#include <cstddef>
#include <cstdint>
+#include <span>
#include <string_view>
namespace kapi::acpi
{
+ //! @addtogroup kapi-acpi
+ //! @{
+
+ struct [[gnu::packed]] system_description_table_header
+ {
+ std::array<char, 4> signature;
+ std::uint32_t length;
+ std::uint8_t revision;
+ std::uint8_t checksum;
+ std::array<char, 6> oem_id;
+ std::array<char, 8> oem_table_id;
+ std::uint32_t oem_revision;
+ std::uint32_t creator_id;
+ std::uint32_t create_revision;
+ };
+
+ //! @}
+
//! @addtogroup kapi-acpi-kernel-defined
//! @{
@@ -44,20 +64,18 @@ namespace kapi::acpi
[[maybe_unused]] std::array<std::byte, 3> m_reserved;
};
- //! @}
+ //! Initialize the ACPI subsystem and discover the available tables.
+ //!
+ //! @return true iff. a valid system description tabled was found, false otherwise.
+ auto init(root_system_description_pointer const & sdp) -> bool;
- struct [[gnu::packed]] system_description_table_header
- {
- std::array<char, 4> signature;
- std::uint32_t length;
- std::uint8_t revision;
- std::uint8_t checksum;
- std::array<char, 6> oem_id;
- std::array<char, 8> oem_table_id;
- std::uint32_t oem_revision;
- std::uint32_t creator_id;
- std::uint32_t create_revision;
- };
+ //! Validate and ACPI entity checksum.
+ //!
+ //! @param data The data to validate the checksum of.
+ //! @return true iff. the checksum is valid, false otherwise.
+ auto validate_checksum(std::span<std::byte const> data) -> bool;
+
+ //! @}
} // namespace kapi::acpi
diff --git a/kapi/include/kapi/memory/layout.hpp b/kapi/include/kapi/memory/layout.hpp
index 157f41e..26b48d8 100644
--- a/kapi/include/kapi/memory/layout.hpp
+++ b/kapi/include/kapi/memory/layout.hpp
@@ -37,6 +37,18 @@ namespace kapi::memory
//! The linear base address of the loaded kernel image.
constexpr auto kernel_base = linear_address{0xffff'ffff'8000'0000uz};
+ //! Convert a physical address to a linear address using the higher-half direct map.
+ constexpr auto hhdm_to_linear(physical_address address) -> linear_address
+ {
+ return linear_address{address.raw() + higher_half_direct_map_base.raw()};
+ }
+
+ //! Convert a linear address in the higher-half direct map to a physical address.
+ constexpr auto hhdm_to_physical(linear_address address) -> physical_address
+ {
+ return physical_address{address.raw() - higher_half_direct_map_base.raw()};
+ }
+
} // namespace kapi::memory
#endif \ No newline at end of file
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt
index ab77467..fc01723 100644
--- a/kernel/CMakeLists.txt
+++ b/kernel/CMakeLists.txt
@@ -14,6 +14,7 @@ add_library("kernel_objs" OBJECT
"kstd/print.cpp"
# Kernel Implementation
+ "src/acpi/manager.cpp"
"src/memory/bitmap_allocator.cpp"
"src/memory/block_list_allocator.cpp"
"src/memory.cpp"
diff --git a/kernel/include/kernel/acpi/manager.hpp b/kernel/include/kernel/acpi/manager.hpp
new file mode 100644
index 0000000..fc76685
--- /dev/null
+++ b/kernel/include/kernel/acpi/manager.hpp
@@ -0,0 +1,26 @@
+#ifndef TEACHOS_KERNEL_ACPI_MANAGER_HPP
+#define TEACHOS_KERNEL_ACPI_MANAGER_HPP
+
+#include "kapi/acpi.hpp"
+
+#include <kstd/vector>
+
+namespace kernel::acpi
+{
+
+ struct manager
+ {
+ explicit manager(kapi::acpi::root_system_description_pointer const & sdp);
+
+ auto load_tables() -> bool;
+
+ private:
+ kapi::acpi::root_system_description_pointer const * m_sdp{};
+ kapi::acpi::system_description_table_header const * m_rsdt{};
+ kstd::vector<kapi::acpi::system_description_table_header> m_tables{};
+ bool m_extended{};
+ };
+
+} // namespace kernel::acpi
+
+#endif
diff --git a/kernel/kapi/acpi.cpp b/kernel/kapi/acpi.cpp
index aa0066d..787bcff 100644
--- a/kernel/kapi/acpi.cpp
+++ b/kernel/kapi/acpi.cpp
@@ -1,13 +1,18 @@
#include "kapi/acpi.hpp"
#include "kapi/memory.hpp"
+#include "kapi/system.hpp"
+
+#include "kernel/acpi/manager.hpp"
#include <kstd/units>
#include <algorithm>
+#include <atomic>
#include <bit>
#include <cstddef>
#include <cstdint>
+#include <optional>
#include <span>
#include <string_view>
@@ -16,12 +21,7 @@ namespace kapi::acpi
namespace
{
- constexpr auto validate_checksum(std::span<std::byte const> data) -> bool
- {
- auto sum = std::ranges::fold_left(
- data, std::uint8_t{}, [](std::uint8_t acc, auto byte) { return static_cast<std::uint8_t>(byte) + acc; });
- return sum == 0;
- }
+ auto constinit manager = std::optional<kernel::acpi::manager>{};
} // namespace
auto root_system_description_pointer::oem_id() const noexcept -> std::string_view
@@ -65,4 +65,24 @@ namespace kapi::acpi
return validate_checksum({reinterpret_cast<std::byte const *>(this), m_length});
}
+ auto init(root_system_description_pointer const & sdp) -> bool
+ {
+ auto static constinit initialized = std::atomic_flag{};
+ if (initialized.test_and_set())
+ {
+ system::panic("[OS::ACPI] The ACPI manager has already been initialized!");
+ }
+
+ manager.emplace(sdp);
+ return manager->load_tables();
+ }
+
+ auto validate_checksum(std::span<std::byte const> data) -> bool
+ {
+ auto sum = std::ranges::fold_left(data, std::uint8_t{}, [](auto acc, auto byte) {
+ return static_cast<std::uint8_t>(acc + static_cast<std::uint8_t>(byte));
+ });
+ return sum == 0;
+ }
+
}; // namespace kapi::acpi
diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp
new file mode 100644
index 0000000..6a17920
--- /dev/null
+++ b/kernel/src/acpi/manager.cpp
@@ -0,0 +1,54 @@
+#include "kernel/acpi/manager.hpp"
+
+#include "kapi/acpi.hpp"
+#include "kapi/memory.hpp"
+#include "kapi/system.hpp"
+
+#include <cstddef>
+
+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}))
+ {
+ kapi::system::panic("[OS:ACPI] Invalid RSDT checksum!");
+ }
+
+ return false;
+ }
+
+} // namespace kernel::acpi