From bd585306e31889ee4fce60abb79bc3b3a58e2b84 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 13:11:15 +0200 Subject: kapi: add basic ACPI support --- kapi/CMakeLists.txt | 8 ++- kapi/include/kapi/acpi.hpp | 64 ++++++++++++++++++++ kapi/src/acpi.cpp | 68 ++++++++++++++++++++++ .../include/kernel/memory/block_list_allocator.hpp | 10 ++-- libs/kstd/include/kstd/units | 7 ++- .../multiboot2/constants/information_id.hpp | 8 +-- libs/multiboot2/include/multiboot2/information.hpp | 43 +++++++++++++- .../include/multiboot2/information/data.hpp | 12 +++- 8 files changed, 205 insertions(+), 15 deletions(-) create mode 100644 kapi/include/kapi/acpi.hpp create mode 100644 kapi/src/acpi.cpp diff --git a/kapi/CMakeLists.txt b/kapi/CMakeLists.txt index c9aa23f..eeda158 100644 --- a/kapi/CMakeLists.txt +++ b/kapi/CMakeLists.txt @@ -1,4 +1,6 @@ -add_library("kapi" INTERFACE) +add_library("kapi" STATIC + "src/acpi.cpp" +) add_library("os::kapi" ALIAS "kapi") file(GLOB_RECURSE KAPI_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "include/**.hpp") @@ -10,11 +12,11 @@ target_sources("kapi" PUBLIC ${KAPI_HEADERS} ) -target_include_directories("kapi" INTERFACE +target_include_directories("kapi" PUBLIC "include" ) -target_link_libraries("kapi" INTERFACE +target_link_libraries("kapi" PUBLIC "libs::kstd" "gcc" diff --git a/kapi/include/kapi/acpi.hpp b/kapi/include/kapi/acpi.hpp new file mode 100644 index 0000000..20e5e77 --- /dev/null +++ b/kapi/include/kapi/acpi.hpp @@ -0,0 +1,64 @@ +#ifndef TEACHOS_KAPI_ACPI_HPP +#define TEACHOS_KAPI_ACPI_HPP + +#include "kapi/memory.hpp" +#include + +#include +#include +#include +#include + +namespace kapi::acpi +{ + + //! @addtogroup kapi-acpi-api-defined + //! @{ + + struct [[gnu::packed]] root_system_description_pointer + { + [[nodiscard]] auto oem_id() const noexcept -> std::string_view; + [[nodiscard]] auto revision() const noexcept -> std::uint8_t; + [[nodiscard]] auto signature() const noexcept -> std::string_view; + [[nodiscard]] auto table_address() const noexcept -> memory::physical_address; + [[nodiscard]] auto validate() const noexcept -> bool; + + private: + std::array m_signature; + [[maybe_unused]] std::uint8_t m_checksum; + std::array m_oem_id; + std::uint8_t m_revision; + std::array m_rsdt_address; + }; + + struct [[gnu::packed]] extended_system_description_pointer : root_system_description_pointer + { + [[nodiscard]] auto length() const noexcept -> kstd::units::bytes; + [[nodiscard]] auto table_address() const noexcept -> memory::physical_address; + [[nodiscard]] auto validate() const noexcept -> bool; + + private: + std::uint32_t m_length; + std::array m_xsdt_address; + [[maybe_unused]] std::uint8_t m_extended_checksum; + [[maybe_unused]] std::array m_reserved; + }; + + //! @} + + struct [[gnu::packed]] system_description_table_header + { + std::array signature; + std::uint32_t length; + std::uint8_t revision; + std::uint8_t checksum; + std::array oem_id; + std::array oem_table_id; + std::uint32_t oem_revision; + std::uint32_t creator_id; + std::uint32_t create_revision; + }; + +} // namespace kapi::acpi + +#endif diff --git a/kapi/src/acpi.cpp b/kapi/src/acpi.cpp new file mode 100644 index 0000000..aa0066d --- /dev/null +++ b/kapi/src/acpi.cpp @@ -0,0 +1,68 @@ +#include "kapi/acpi.hpp" + +#include "kapi/memory.hpp" + +#include + +#include +#include +#include +#include +#include +#include + +namespace kapi::acpi +{ + + namespace + { + constexpr auto validate_checksum(std::span data) -> bool + { + auto sum = std::ranges::fold_left( + data, std::uint8_t{}, [](std::uint8_t acc, auto byte) { return static_cast(byte) + acc; }); + return sum == 0; + } + } // namespace + + auto root_system_description_pointer::oem_id() const noexcept -> std::string_view + { + return {m_oem_id.data(), m_oem_id.size()}; + } + + auto root_system_description_pointer::revision() const noexcept -> std::uint8_t + { + return m_revision; + } + + auto root_system_description_pointer::signature() const noexcept -> std::string_view + { + return {m_signature.data(), m_signature.size()}; + } + + auto root_system_description_pointer::table_address() const noexcept -> memory::physical_address + { + auto raw = std::bit_cast(m_rsdt_address); + return memory::physical_address{static_cast(raw)}; + } + + auto root_system_description_pointer::validate() const noexcept -> bool + { + return validate_checksum({reinterpret_cast(this), sizeof(root_system_description_pointer)}); + } + + auto extended_system_description_pointer::length() const noexcept -> kstd::units::bytes + { + return kstd::units::bytes{m_length}; + } + + auto extended_system_description_pointer::table_address() const noexcept -> memory::physical_address + { + return memory::physical_address{std::bit_cast(m_xsdt_address)}; + } + + auto extended_system_description_pointer::validate() const noexcept -> bool + { + return validate_checksum({reinterpret_cast(this), m_length}); + } + +}; // namespace kapi::acpi diff --git a/kernel/include/kernel/memory/block_list_allocator.hpp b/kernel/include/kernel/memory/block_list_allocator.hpp index f319097..de89f3b 100644 --- a/kernel/include/kernel/memory/block_list_allocator.hpp +++ b/kernel/include/kernel/memory/block_list_allocator.hpp @@ -43,10 +43,10 @@ namespace kernel::memory private: struct block_header final { - kstd::units::bytes usable_size; - bool free; - block_header * next; - block_header * prev; + kstd::units::bytes usable_size{}; + bool free{}; + block_header * next{}; + block_header * prev{}; }; //! The size of the metadata required for each allocated block. @@ -87,4 +87,4 @@ namespace kernel::memory } // namespace kernel::memory -#endif \ No newline at end of file +#endif diff --git a/libs/kstd/include/kstd/units b/libs/kstd/include/kstd/units index f6dcdb1..bc7e1b9 100644 --- a/libs/kstd/include/kstd/units +++ b/libs/kstd/include/kstd/units @@ -14,6 +14,11 @@ namespace kstd { using value_type = ValueType; + constexpr basic_unit() noexcept + : value{} + { + } + explicit constexpr basic_unit(value_type value) noexcept : value{value} {} @@ -142,4 +147,4 @@ namespace kstd } // namespace kstd -#endif \ No newline at end of file +#endif diff --git a/libs/multiboot2/include/multiboot2/constants/information_id.hpp b/libs/multiboot2/include/multiboot2/constants/information_id.hpp index be492eb..27c5300 100644 --- a/libs/multiboot2/include/multiboot2/constants/information_id.hpp +++ b/libs/multiboot2/include/multiboot2/constants/information_id.hpp @@ -57,10 +57,10 @@ namespace multiboot2 smbios_tables, //! A copy of RSDP as defined per ACPI 1.0 specification. - acpi_old_rsdp, + acpi_rsdp, - //! A copy of RSDP as defined per ACPI 2.0 or later specification. - acpi_new_rsdp, + //! A copy of XSDP as defined per ACPI 2.0 or later specification. + acpi_xsdp, //! The network information specified specified as per DHCP. networking_information, @@ -83,4 +83,4 @@ namespace multiboot2 } // namespace multiboot2 -#endif \ No newline at end of file +#endif diff --git a/libs/multiboot2/include/multiboot2/information.hpp b/libs/multiboot2/include/multiboot2/information.hpp index d2fac2e..a2ded56 100644 --- a/libs/multiboot2/include/multiboot2/information.hpp +++ b/libs/multiboot2/include/multiboot2/information.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -128,6 +129,26 @@ namespace multiboot2 return kstd::units::bytes{end_address - start_address}; } }; + + struct acpi_rsdp : vla_tag + { + using vla_tag::vla_tag; + + [[nodiscard]] auto pointer() const noexcept -> range_type + { + return {data(), size()}; + } + }; + + struct acpi_xsdp : vla_tag + { + using vla_tag::vla_tag; + + [[nodiscard]] auto pointer() const noexcept -> range_type + { + return {data(), size()}; + } + }; struct information_view { @@ -245,6 +266,26 @@ namespace multiboot2 std::views::transform(transform_module); } + [[nodiscard]] auto maybe_acpi_rsdp() const noexcept -> std::optional + { + return get(); + } + + [[nodiscard]] auto acpi_rsdp() const noexcept -> acpi_rsdp + { + return maybe_acpi_rsdp().value(); + } + + [[nodiscard]] auto maybe_acpi_xsdp() const noexcept -> std::optional + { + return get(); + } + + [[nodiscard]] auto acpi_xsdp() const noexcept -> acpi_xsdp + { + return maybe_acpi_xsdp().value(); + } + private: template [[nodiscard]] constexpr auto get() const noexcept -> std::optional @@ -264,4 +305,4 @@ namespace multiboot2 } // namespace multiboot2 -#endif \ No newline at end of file +#endif diff --git a/libs/multiboot2/include/multiboot2/information/data.hpp b/libs/multiboot2/include/multiboot2/information/data.hpp index 3b07d20..315eb39 100644 --- a/libs/multiboot2/include/multiboot2/information/data.hpp +++ b/libs/multiboot2/include/multiboot2/information/data.hpp @@ -167,8 +167,18 @@ namespace multiboot2 std::uint32_t end_address; }; + //! A copy of the ACPI RSDP + struct acpi_rsdp : tag_data + { + }; + + //! A copy of the ACPI XSDP + struct acpi_xsdp : tag_data + { + }; + } // namespace data } // namespace multiboot2 -#endif \ No newline at end of file +#endif -- cgit v1.2.3