aboutsummaryrefslogtreecommitdiff
path: root/libs/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'libs/acpi')
-rw-r--r--libs/acpi/CMakeLists.txt15
-rw-r--r--libs/acpi/acpi/acpi.hpp12
-rw-r--r--libs/acpi/acpi/common/basic_table.hpp35
-rw-r--r--libs/acpi/acpi/common/checksum.cpp (renamed from libs/acpi/acpi/checksum.cpp)2
-rw-r--r--libs/acpi/acpi/common/checksum.hpp (renamed from libs/acpi/acpi/checksum.hpp)0
-rw-r--r--libs/acpi/acpi/common/table_header.cpp130
-rw-r--r--libs/acpi/acpi/common/table_header.hpp56
-rw-r--r--libs/acpi/acpi/common/table_header.test.cpp58
-rw-r--r--libs/acpi/acpi/common/table_signature.hpp17
-rw-r--r--libs/acpi/acpi/common/table_type.hpp (renamed from libs/acpi/acpi/table_type.hpp)4
-rw-r--r--libs/acpi/acpi/common/vla_table.hpp115
-rw-r--r--libs/acpi/acpi/data/madt.cpp112
-rw-r--r--libs/acpi/acpi/data/madt.hpp (renamed from libs/acpi/acpi/madt.hpp)57
-rw-r--r--libs/acpi/acpi/data/madt.test.cpp (renamed from libs/acpi/acpi/madt.test.cpp)6
-rw-r--r--libs/acpi/acpi/data/rsdt.cpp38
-rw-r--r--libs/acpi/acpi/data/rsdt.hpp42
-rw-r--r--libs/acpi/acpi/data/rsdt.test.cpp46
-rw-r--r--libs/acpi/acpi/data/xsdt.cpp38
-rw-r--r--libs/acpi/acpi/data/xsdt.hpp42
-rw-r--r--libs/acpi/acpi/data/xsdt.test.cpp46
-rw-r--r--libs/acpi/acpi/madt.cpp74
-rw-r--r--libs/acpi/acpi/pointers.cpp2
-rw-r--r--libs/acpi/acpi/sdt.cpp58
-rw-r--r--libs/acpi/acpi/sdt.hpp127
-rw-r--r--libs/acpi/test_data/basic_xsdt.asl26
-rw-r--r--libs/acpi/test_data/table_header.asl9
-rw-r--r--libs/acpi/test_data/tables.S2
-rw-r--r--libs/acpi/test_data/tables.hpp2
28 files changed, 864 insertions, 307 deletions
diff --git a/libs/acpi/CMakeLists.txt b/libs/acpi/CMakeLists.txt
index 30e1aca..55d5b54 100644
--- a/libs/acpi/CMakeLists.txt
+++ b/libs/acpi/CMakeLists.txt
@@ -19,10 +19,12 @@ file(GLOB_RECURSE ACPI_HEADERS
)
target_sources("acpi" PRIVATE
- "acpi/checksum.cpp"
- "acpi/madt.cpp"
+ "acpi/common/checksum.cpp"
+ "acpi/common/table_header.cpp"
+ "acpi/data/madt.cpp"
+ "acpi/data/rsdt.cpp"
+ "acpi/data/xsdt.cpp"
"acpi/pointers.cpp"
- "acpi/sdt.cpp"
)
target_sources("acpi" PUBLIC
@@ -43,6 +45,8 @@ if(NOT CMAKE_CROSSCOMPILING)
"basic_madt"
"basic_rsdt"
"basic_rsdp"
+ "basic_xsdt"
+ "table_header"
)
foreach(TABLE IN LISTS TEST_TABLES)
@@ -58,7 +62,10 @@ if(NOT CMAKE_CROSSCOMPILING)
set_source_files_properties("test_data/tables.S" PROPERTIES OBJECT_DEPENDS "${GENERATED_TABLE_BLOBS}")
add_executable("acpi_tests"
- "acpi/madt.test.cpp"
+ "acpi/common/table_header.test.cpp"
+ "acpi/data/madt.test.cpp"
+ "acpi/data/rsdt.test.cpp"
+ "acpi/data/xsdt.test.cpp"
"acpi/pointers.test.cpp"
"test_data/tables.S"
diff --git a/libs/acpi/acpi/acpi.hpp b/libs/acpi/acpi/acpi.hpp
index fb358cc..0da44a8 100644
--- a/libs/acpi/acpi/acpi.hpp
+++ b/libs/acpi/acpi/acpi.hpp
@@ -1,10 +1,12 @@
#ifndef ACPI_ACPI_HPP
#define ACPI_ACPI_HPP
-#include <acpi/checksum.hpp> // IWYU pragma: export
-#include <acpi/madt.hpp> // IWYU pragma: export
-#include <acpi/pointers.hpp> // IWYU pragma: export
-#include <acpi/sdt.hpp> // IWYU pragma: export
-#include <acpi/table_type.hpp> // IWYU pragma: export
+#include <acpi/common/checksum.hpp> // IWYU pragma: export
+#include <acpi/common/table_signature.hpp> // IWYU pragma: export
+#include <acpi/common/table_type.hpp> // IWYU pragma: export
+#include <acpi/data/madt.hpp> // IWYU pragma: export
+#include <acpi/data/rsdt.hpp> // IWYU pragma: export
+#include <acpi/data/xsdt.hpp> // IWYU pragma: export
+#include <acpi/pointers.hpp> // IWYU pragma: export
#endif
diff --git a/libs/acpi/acpi/common/basic_table.hpp b/libs/acpi/acpi/common/basic_table.hpp
new file mode 100644
index 0000000..33f23d5
--- /dev/null
+++ b/libs/acpi/acpi/common/basic_table.hpp
@@ -0,0 +1,35 @@
+#ifndef ACPI_COMMON_BASIC_TABLE_HPP
+#define ACPI_COMMON_BASIC_TABLE_HPP
+
+#include <acpi/common/checksum.hpp>
+#include <acpi/common/table_header.hpp>
+#include <acpi/common/table_signature.hpp>
+
+#include <cstddef>
+#include <span>
+
+namespace acpi
+{
+
+ template<typename TableType>
+ struct basic_table : table_header
+ {
+ [[nodiscard]] auto validate_checksum() const noexcept -> bool
+ {
+ return acpi::validate_checksum(as_span());
+ }
+
+ [[nodiscard]] auto as_span() const noexcept -> std::span<std::byte const>
+ {
+ return {reinterpret_cast<std::byte const *>(this), length().value};
+ }
+
+ [[nodiscard]] auto validate() const noexcept -> bool
+ {
+ return signature() == table_signature_v<TableType> && validate_checksum();
+ }
+ };
+
+} // namespace acpi
+
+#endif \ No newline at end of file
diff --git a/libs/acpi/acpi/checksum.cpp b/libs/acpi/acpi/common/checksum.cpp
index 56275c8..09425dd 100644
--- a/libs/acpi/acpi/checksum.cpp
+++ b/libs/acpi/acpi/common/checksum.cpp
@@ -1,4 +1,4 @@
-#include <acpi/checksum.hpp>
+#include <acpi/common/checksum.hpp>
#include <algorithm>
#include <cstddef>
diff --git a/libs/acpi/acpi/checksum.hpp b/libs/acpi/acpi/common/checksum.hpp
index a92c242..a92c242 100644
--- a/libs/acpi/acpi/checksum.hpp
+++ b/libs/acpi/acpi/common/checksum.hpp
diff --git a/libs/acpi/acpi/common/table_header.cpp b/libs/acpi/acpi/common/table_header.cpp
new file mode 100644
index 0000000..c69ff5d
--- /dev/null
+++ b/libs/acpi/acpi/common/table_header.cpp
@@ -0,0 +1,130 @@
+#include <kstd/cstring>
+#include <kstd/units>
+
+#include <acpi/common/table_header.hpp>
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <span>
+#include <string_view>
+
+namespace acpi
+{
+
+ struct common_table_header_data
+ {
+ 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::array<char, 4> creator_id;
+ std::uint32_t creator_revision;
+ };
+
+ static_assert(sizeof(common_table_header_data) == common_table_header_size);
+
+ auto table_header::creator_revision() const noexcept -> decltype(common_table_header_data::creator_revision)
+ {
+ using type = decltype(common_table_header_data::creator_revision);
+
+ constexpr auto size = sizeof(type);
+ constexpr auto offset = offsetof(common_table_header_data, creator_revision);
+
+ auto const data = std::span<std::byte const, size>{m_data.data() + offset, size};
+ auto value = type{};
+
+ kstd::libc::memcpy(&value, data.data(), size);
+
+ return value;
+ }
+
+ auto table_header::creator_id() const noexcept -> std::string_view
+ {
+ constexpr auto size = sizeof(common_table_header_data::creator_id);
+ constexpr auto offset = offsetof(common_table_header_data, creator_id);
+
+ auto const base = reinterpret_cast<char const *>(m_data.data());
+
+ return std::string_view{base + offset, size};
+ }
+
+ auto table_header::length() const noexcept -> kstd::units::bytes
+ {
+ using type = decltype(common_table_header_data::length);
+
+ constexpr auto size = sizeof(type);
+ constexpr auto offset = offsetof(common_table_header_data, length);
+
+ auto const data = std::span<std::byte const, size>{m_data.data() + offset, size};
+ auto raw_value = type{};
+
+ kstd::libc::memcpy(&raw_value, data.data(), size);
+
+ return kstd::units::bytes{raw_value};
+ }
+
+ auto table_header::oem_id() const noexcept -> std::string_view
+ {
+ constexpr auto size = sizeof(common_table_header_data::oem_id);
+ constexpr auto offset = offsetof(common_table_header_data, oem_id);
+
+ auto const base = reinterpret_cast<char const *>(m_data.data());
+
+ return std::string_view{base + offset, size};
+ }
+
+ auto table_header::oem_table_id() const noexcept -> std::string_view
+ {
+ constexpr auto size = sizeof(common_table_header_data::oem_table_id);
+ constexpr auto offset = offsetof(common_table_header_data, oem_table_id);
+
+ auto const base = reinterpret_cast<char const *>(m_data.data());
+
+ return std::string_view{base + offset, size};
+ }
+
+ auto table_header::oem_revision() const noexcept -> decltype(common_table_header_data::oem_revision)
+ {
+ using type = decltype(common_table_header_data::oem_revision);
+
+ constexpr auto size = sizeof(type);
+ constexpr auto offset = offsetof(common_table_header_data, oem_revision);
+
+ auto const data = std::span<std::byte const, size>{m_data.data() + offset, size};
+ auto value = type{};
+
+ kstd::libc::memcpy(&value, data.data(), size);
+
+ return value;
+ }
+
+ auto table_header::revision() const noexcept -> decltype(common_table_header_data::revision)
+ {
+ using type = decltype(common_table_header_data::revision);
+
+ constexpr auto size = sizeof(type);
+ constexpr auto offset = offsetof(common_table_header_data, revision);
+
+ auto const data = std::span<std::byte const, size>{m_data.data() + offset, size};
+ auto value = type{};
+
+ kstd::libc::memcpy(&value, data.data(), size);
+
+ return value;
+ }
+
+ auto table_header::signature() const noexcept -> std::string_view
+ {
+ constexpr auto size = sizeof(common_table_header_data::signature);
+ constexpr auto offset = offsetof(common_table_header_data, signature);
+
+ auto const base = reinterpret_cast<char const *>(m_data.data());
+
+ return std::string_view{base + offset, size};
+ }
+
+} // namespace acpi \ No newline at end of file
diff --git a/libs/acpi/acpi/common/table_header.hpp b/libs/acpi/acpi/common/table_header.hpp
new file mode 100644
index 0000000..471fed8
--- /dev/null
+++ b/libs/acpi/acpi/common/table_header.hpp
@@ -0,0 +1,56 @@
+#ifndef ACPI_COMMON_TABLE_HEADER_HPP
+#define ACPI_COMMON_TABLE_HEADER_HPP
+
+// IWYU pragma: private, include <acpi/acpi.hpp>
+
+#include <kstd/units>
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <string_view>
+
+namespace acpi
+{
+
+ //! The size of the common table header as defined in the ACPI specification.
+ constexpr auto common_table_header_size = 36;
+
+ //! The common header for all ACPI tables, except the FACS.
+ //!
+ //! Multibyte fields in the header are not guaranteed to be naturally aligned by the firmware. Therefore, no direct
+ //! access to multibyte fields is provided. Instead, the provided member functions handle alignment of the multibyte
+ //! values and thus provide a safe interface to the header fields.
+ struct table_header
+ {
+ //! Get the revision of the utility used to create this table.
+ [[nodiscard]] auto creator_revision() const noexcept -> std::uint32_t;
+
+ //! Get the vendor ID of the utility used to create this table.
+ [[nodiscard]] auto creator_id() const noexcept -> std::string_view;
+
+ //! Get the length of the entire table, including this header.
+ [[nodiscard]] auto length() const noexcept -> kstd::units::bytes;
+
+ //! Get the ID of the OEM.
+ [[nodiscard]] auto oem_id() const noexcept -> std::string_view;
+
+ //! Get the OEMs revision number of this table.
+ [[nodiscard]] auto oem_revision() const noexcept -> std::uint32_t;
+
+ //! Get the OEMs ID of this table.
+ [[nodiscard]] auto oem_table_id() const noexcept -> std::string_view;
+
+ //! Get the revision number of the structure of this table.
+ [[nodiscard]] auto revision() const noexcept -> std::uint8_t;
+
+ //! Get the signature of this table.
+ [[nodiscard]] auto signature() const noexcept -> std::string_view;
+
+ private:
+ std::array<std::byte, common_table_header_size> m_data;
+ };
+
+} // namespace acpi
+
+#endif \ No newline at end of file
diff --git a/libs/acpi/acpi/common/table_header.test.cpp b/libs/acpi/acpi/common/table_header.test.cpp
new file mode 100644
index 0000000..d6976b3
--- /dev/null
+++ b/libs/acpi/acpi/common/table_header.test.cpp
@@ -0,0 +1,58 @@
+#include <kstd/units>
+
+#include <acpi/common/table_header.hpp>
+#include <catch2/catch_test_macros.hpp>
+#include <test_data/tables.hpp>
+
+SCENARIO("Common table header parsing", "[common_table_header]")
+{
+ GIVEN("A valid compiled table header")
+ {
+ auto data = acpi::test_data::tables::table_header();
+
+ WHEN("parsing the header")
+ {
+ auto header = reinterpret_cast<acpi::table_header const *>(data.data());
+
+ THEN("the signature is correct")
+ {
+ REQUIRE(header->signature() == "TEST");
+ }
+
+ THEN("the revision is correct")
+ {
+ REQUIRE(header->revision() == 1);
+ }
+
+ THEN("the length is correct")
+ {
+ REQUIRE(header->length() == kstd::type_size<acpi::table_header>);
+ }
+
+ THEN("the oem id is correct")
+ {
+ REQUIRE(header->oem_id() == "FEMO ");
+ }
+
+ THEN("the oem table id is correct")
+ {
+ REQUIRE(header->oem_table_id() == "HDRTEST ");
+ }
+
+ THEN("the oem revision is correct")
+ {
+ REQUIRE(header->oem_revision() == 1);
+ }
+
+ THEN("the creator id is correct")
+ {
+ REQUIRE(header->creator_id() == "INTL");
+ }
+
+ THEN("the creator revision is non-zero")
+ {
+ REQUIRE(header->creator_revision() != 0);
+ }
+ }
+ }
+}
diff --git a/libs/acpi/acpi/common/table_signature.hpp b/libs/acpi/acpi/common/table_signature.hpp
new file mode 100644
index 0000000..f0c2d7a
--- /dev/null
+++ b/libs/acpi/acpi/common/table_signature.hpp
@@ -0,0 +1,17 @@
+#ifndef ACPI_COMMON_TABLE_SIGNATURE_HPP
+#define ACPI_COMMON_TABLE_SIGNATURE_HPP
+
+// IWYU pragma: private, include <acpi/acpi.hpp>
+
+namespace acpi
+{
+
+ template<typename TableType>
+ struct table_signature;
+
+ template<typename TableType>
+ constexpr auto table_signature_v = table_signature<TableType>::value;
+
+} // namespace acpi
+
+#endif
diff --git a/libs/acpi/acpi/table_type.hpp b/libs/acpi/acpi/common/table_type.hpp
index 7fdd7e3..bc427c7 100644
--- a/libs/acpi/acpi/table_type.hpp
+++ b/libs/acpi/acpi/common/table_type.hpp
@@ -1,5 +1,5 @@
-#ifndef ACPI_TABLE_TYPE_HPP
-#define ACPI_TABLE_TYPE_HPP
+#ifndef ACPI_COMMON_TABLE_TYPE_HPP
+#define ACPI_COMMON_TABLE_TYPE_HPP
// IWYU pragma: private, include <acpi/acpi.hpp>
diff --git a/libs/acpi/acpi/common/vla_table.hpp b/libs/acpi/acpi/common/vla_table.hpp
new file mode 100644
index 0000000..a65a28e
--- /dev/null
+++ b/libs/acpi/acpi/common/vla_table.hpp
@@ -0,0 +1,115 @@
+#ifndef ACPI_COMMON_VLA_TABLE_HPP
+#define ACPI_COMMON_VLA_TABLE_HPP
+
+#include <acpi/common/basic_table.hpp>
+
+#include <cstddef>
+#include <iterator>
+
+namespace acpi
+{
+
+ template<typename EntryType>
+ struct vla_table_iterator
+ {
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = EntryType;
+ using pointer = value_type *;
+ using reference = value_type &;
+ using difference_type = std::ptrdiff_t;
+
+ constexpr vla_table_iterator() noexcept = default;
+
+ constexpr vla_table_iterator(pointer entry, pointer limit) noexcept
+ : m_entry{entry}
+ , m_limit{limit}
+ {}
+
+ constexpr auto operator++() noexcept -> vla_table_iterator &
+ {
+ auto decayed = std::bit_cast<std::byte *>(m_entry);
+ decayed += m_entry->length();
+ m_entry = std::bit_cast<pointer>(decayed);
+ return *this;
+ }
+
+ constexpr auto operator++(int) noexcept -> vla_table_iterator
+ {
+ auto copy = *this;
+ ++*this;
+ return copy;
+ }
+
+ constexpr auto operator*() const noexcept -> reference
+ {
+ return *m_entry;
+ }
+
+ constexpr auto operator->() const noexcept -> pointer
+ {
+ return m_entry;
+ }
+
+ constexpr auto operator==(vla_table_iterator const & other) const noexcept -> bool
+ {
+ return m_entry == other.m_entry || (is_end() && other.is_end());
+ }
+
+ private:
+ [[nodiscard]] constexpr auto is_end() const noexcept -> bool
+ {
+ return m_entry == m_limit;
+ }
+
+ pointer m_entry{};
+ pointer m_limit{};
+ };
+
+ template<typename EntryType, typename TableType>
+ struct vla_table : basic_table<TableType>
+ {
+ using entry_type = EntryType;
+ using iterator = vla_table_iterator<EntryType>;
+ using const_iterator = vla_table_iterator<EntryType const>;
+
+ [[nodiscard]] auto begin() noexcept -> iterator
+ {
+ auto base = std::bit_cast<std::byte *>(this);
+ base += sizeof(TableType);
+ auto limit = std::bit_cast<std::byte *>(this);
+ limit += this->length().value;
+ return iterator{std::bit_cast<entry_type *>(base), std::bit_cast<entry_type *>(limit)};
+ }
+
+ [[nodiscard]] auto end() noexcept -> iterator
+ {
+ return iterator{};
+ }
+
+ [[nodiscard]] auto begin() const noexcept -> const_iterator
+ {
+ auto base = std::bit_cast<std::byte *>(this);
+ base += sizeof(TableType);
+ auto limit = std::bit_cast<std::byte *>(this);
+ limit += this->length().value;
+ return const_iterator{std::bit_cast<entry_type const *>(base), std::bit_cast<entry_type const *>(limit)};
+ }
+
+ [[nodiscard]] auto end() const noexcept -> const_iterator
+ {
+ return const_iterator{};
+ }
+
+ [[nodiscard]] auto cbegin() const noexcept -> const_iterator
+ {
+ return begin();
+ }
+
+ [[nodiscard]] auto cend() const noexcept -> const_iterator
+ {
+ return end();
+ }
+ };
+} // namespace acpi
+
+#endif \ No newline at end of file
diff --git a/libs/acpi/acpi/data/madt.cpp b/libs/acpi/acpi/data/madt.cpp
new file mode 100644
index 0000000..a8d4741
--- /dev/null
+++ b/libs/acpi/acpi/data/madt.cpp
@@ -0,0 +1,112 @@
+#include <kstd/cstring>
+
+#include <acpi/data/madt.hpp>
+
+#include <bit>
+#include <cstddef>
+#include <cstdint>
+#include <span>
+
+namespace acpi
+{
+
+ struct madt_data
+ {
+ std::uint32_t local_interrupt_controller_address;
+ std::uint32_t flags;
+ };
+
+ static_assert(sizeof(madt_data) == 8);
+
+ auto madt::local_interrupt_controller_address() const noexcept -> std::uintptr_t
+ {
+ using type = decltype(madt_data::local_interrupt_controller_address);
+
+ constexpr auto size = sizeof(type);
+ constexpr auto offset = offsetof(madt_data, local_interrupt_controller_address);
+
+ auto const data = std::span<std::byte const, size>{m_data.data() + offset, size};
+ auto value = type{};
+
+ kstd::libc::memcpy(&value, data.data(), size);
+
+ return value;
+ }
+
+ auto madt::flags() const noexcept -> std::uint32_t
+ {
+ using type = decltype(madt_data::flags);
+
+ constexpr auto size = sizeof(type);
+ constexpr auto offset = offsetof(madt_data, flags);
+
+ auto const data = std::span<std::byte const, size>{m_data.data() + offset, size};
+ auto value = type{};
+
+ kstd::libc::memcpy(&value, data.data(), size);
+
+ return value;
+ }
+
+ struct madt_entry_data
+ {
+ std::uint8_t type;
+ std::uint8_t length;
+ };
+
+ static_assert(sizeof(madt_entry_data) == 2);
+
+ auto madt_entry::type() const noexcept -> enum type
+ {
+ constexpr auto field_offset = offsetof(madt_entry_data, type);
+
+ return std::bit_cast<enum type>(*(m_data.data() + field_offset));
+ }
+
+ auto madt_entry::length() const noexcept -> std::size_t
+ {
+ constexpr auto field_offset = offsetof(madt_entry_data, length);
+
+ return static_cast<std::size_t>(*(m_data.data() + field_offset));
+ }
+
+ struct [[gnu::packed]] processor_local_apic_entry_data
+ {
+ std::uint8_t apic_id;
+ std::uint8_t processor_id;
+ std::uint32_t flags;
+ };
+
+ static_assert(sizeof(processor_local_apic_entry_data) == 6);
+
+ auto processor_local_apic_entry::id() const noexcept -> std::uint8_t
+ {
+ constexpr auto field_offset = offsetof(processor_local_apic_entry_data, apic_id);
+
+ return static_cast<std::uint8_t>(*(m_data.data() + field_offset));
+ }
+
+ auto processor_local_apic_entry::flags() const noexcept -> enum flags
+ {
+ using type = decltype(processor_local_apic_entry_data::flags);
+ static_assert(sizeof(type) == sizeof(enum flags));
+
+ constexpr auto size = sizeof(type);
+ constexpr auto offset = offsetof(processor_local_apic_entry_data, flags);
+
+ auto const data = std::span<std::byte const, size>{m_data.data() + offset, size};
+ auto value = type{};
+
+ kstd::libc::memcpy(&value, data.data(), size);
+
+ return static_cast<enum flags>(value);
+ }
+
+ auto processor_local_apic_entry::processor_id() const noexcept -> std::uint32_t
+ {
+ constexpr auto field_offset = offsetof(processor_local_apic_entry_data, processor_id);
+
+ return static_cast<std::uint32_t>(*(m_data.data() + field_offset));
+ }
+
+} // namespace acpi
diff --git a/libs/acpi/acpi/madt.hpp b/libs/acpi/acpi/data/madt.hpp
index 8b75f58..8307826 100644
--- a/libs/acpi/acpi/madt.hpp
+++ b/libs/acpi/acpi/data/madt.hpp
@@ -7,9 +7,11 @@
#include <kstd/os/error.hpp>
#include <kstd/units>
-#include <acpi/sdt.hpp>
-#include <acpi/table_type.hpp>
+#include <acpi/common/table_signature.hpp>
+#include <acpi/common/table_type.hpp>
+#include <acpi/common/vla_table.hpp>
+#include <array>
#include <cstddef>
#include <cstdint>
#include <ranges>
@@ -18,7 +20,19 @@
namespace acpi
{
- struct [[gnu::packed]] madt_entry
+ template<>
+ struct table_signature<struct madt>
+ {
+ constexpr char static const value[] = "APIC"; // NOLINT
+ };
+
+ template<>
+ struct table_type<table_signature_v<struct madt>>
+ {
+ using type = struct madt;
+ };
+
+ struct madt_entry
{
//! The type of an MADT entry.
enum struct type : std::uint8_t
@@ -53,26 +67,16 @@ namespace acpi
}
private:
- std::uint8_t m_type;
- std::uint8_t m_length;
+ std::array<std::byte, 2> m_data{};
};
//! The Multiple APIC Description Table (MADT)
- struct [[gnu::packed]] madt : sdt
+ struct madt : vla_table<madt_entry, madt>
{
- using iterator = sdt_iterator<madt_entry const>;
- using const_iterator = iterator;
-
//! Get the physical address of the local interrupt controllers described by this entry.
[[nodiscard]] auto local_interrupt_controller_address() const noexcept -> std::uintptr_t;
[[nodiscard]] auto flags() const noexcept -> std::uint32_t;
- [[nodiscard]] auto validate() const noexcept -> bool;
-
- [[nodiscard]] auto begin() const noexcept -> iterator;
- [[nodiscard]] auto cbegin() const noexcept -> iterator;
- [[nodiscard]] auto end() const noexcept -> iterator;
- [[nodiscard]] auto cend() const noexcept -> iterator;
template<typename EntryType>
[[nodiscard]] auto only() const noexcept
@@ -82,11 +86,10 @@ namespace acpi
}
private:
- std::uint32_t m_local_interrupt_controller_address;
- std::uint32_t m_flags;
+ std::array<std::byte, 8> m_data{};
};
- struct [[gnu::packed]] processor_local_apic : madt_entry
+ struct processor_local_apic_entry : madt_entry
{
constexpr auto static this_type = type::processor_local_apic;
@@ -96,28 +99,18 @@ namespace acpi
online_capable = 2,
};
- [[nodiscard]] auto apic_id() const noexcept -> std::uint8_t;
- [[nodiscard]] auto active_flags() const noexcept -> flags;
+ [[nodiscard]] auto id() const noexcept -> std::uint8_t;
+ [[nodiscard]] auto flags() const noexcept -> flags;
[[nodiscard]] auto processor_id() const noexcept -> std::uint32_t;
private:
- std::uint8_t m_processor_id;
- std::uint8_t m_apic_id;
- std::uint32_t m_flags;
- };
-
- constexpr char const madt_table_signature[] = "APIC"; // NOLINT
-
- template<>
- struct table_type<madt_table_signature>
- {
- using type = madt;
+ std::array<std::byte, 6> m_data{};
};
} // namespace acpi
template<>
-struct kstd::ext::is_bitfield_enum<acpi::processor_local_apic::flags> : std::true_type
+struct kstd::ext::is_bitfield_enum<enum acpi::processor_local_apic_entry::flags> : std::true_type
{
};
diff --git a/libs/acpi/acpi/madt.test.cpp b/libs/acpi/acpi/data/madt.test.cpp
index 8926192..6795499 100644
--- a/libs/acpi/acpi/madt.test.cpp
+++ b/libs/acpi/acpi/data/madt.test.cpp
@@ -1,6 +1,6 @@
#include <kstd/units>
-#include <acpi/madt.hpp>
+#include <acpi/data/madt.hpp>
#include <catch2/catch_test_macros.hpp>
#include <test_data/tables.hpp>
@@ -38,7 +38,7 @@ SCENARIO("MADT parsing", "[madt]")
THEN("the length is sizeof(madt) + sizeof(processor_local_apic)")
{
- REQUIRE(madt->length() == kstd::type_size<acpi::madt> + kstd::type_size<acpi::processor_local_apic>);
+ REQUIRE(madt->length().value == sizeof(acpi::madt) + sizeof(acpi::processor_local_apic_entry));
}
THEN("the first entry has type processor_local_apic")
@@ -48,7 +48,7 @@ SCENARIO("MADT parsing", "[madt]")
THEN("`only` can be used to get a view of all processor_local_apic entries")
{
- REQUIRE(std::ranges::distance(madt->only<acpi::processor_local_apic>()) == 1);
+ REQUIRE(std::ranges::distance(madt->only<acpi::processor_local_apic_entry>()) == 1);
}
}
}
diff --git a/libs/acpi/acpi/data/rsdt.cpp b/libs/acpi/acpi/data/rsdt.cpp
new file mode 100644
index 0000000..fe108c7
--- /dev/null
+++ b/libs/acpi/acpi/data/rsdt.cpp
@@ -0,0 +1,38 @@
+#include <kstd/cstring>
+
+#include <acpi/common/table_header.hpp>
+#include <acpi/data/rsdt.hpp>
+
+#include <cstddef>
+#include <cstdint>
+#include <span>
+
+namespace acpi
+{
+
+ struct rsdt_entry_data
+ {
+ std::uint32_t address;
+ };
+
+ [[nodiscard]] auto rsdt_entry::address() const noexcept -> table_header *
+ {
+ using type = decltype(rsdt_entry_data::address);
+
+ constexpr auto size = sizeof(type);
+ constexpr auto offset = offsetof(rsdt_entry_data, address);
+
+ auto const data = std::span<std::byte const, size>{m_data.data() + offset, size};
+ auto value = type{};
+
+ kstd::libc::memcpy(&value, data.data(), size);
+
+ return reinterpret_cast<table_header *>(static_cast<uintptr_t>(value));
+ }
+
+ [[nodiscard]] auto rsdt_entry::length() const noexcept -> std::size_t
+ {
+ return sizeof(m_data);
+ }
+
+} // namespace acpi \ No newline at end of file
diff --git a/libs/acpi/acpi/data/rsdt.hpp b/libs/acpi/acpi/data/rsdt.hpp
new file mode 100644
index 0000000..a661187
--- /dev/null
+++ b/