aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/acpi/CMakeLists.txt3
-rw-r--r--libs/acpi/acpi/common/table_header.cpp130
-rw-r--r--libs/acpi/acpi/common/table_header.hpp57
-rw-r--r--libs/acpi/acpi/common/table_header.test.cpp58
-rw-r--r--libs/acpi/test_data/table_header.asl9
-rw-r--r--libs/acpi/test_data/tables.S1
-rw-r--r--libs/acpi/test_data/tables.hpp1
7 files changed, 259 insertions, 0 deletions
diff --git a/libs/acpi/CMakeLists.txt b/libs/acpi/CMakeLists.txt
index 30e1aca..b9c607d 100644
--- a/libs/acpi/CMakeLists.txt
+++ b/libs/acpi/CMakeLists.txt
@@ -20,6 +20,7 @@ file(GLOB_RECURSE ACPI_HEADERS
target_sources("acpi" PRIVATE
"acpi/checksum.cpp"
+ "acpi/common/table_header.cpp"
"acpi/madt.cpp"
"acpi/pointers.cpp"
"acpi/sdt.cpp"
@@ -43,6 +44,7 @@ if(NOT CMAKE_CROSSCOMPILING)
"basic_madt"
"basic_rsdt"
"basic_rsdp"
+ "table_header"
)
foreach(TABLE IN LISTS TEST_TABLES)
@@ -58,6 +60,7 @@ if(NOT CMAKE_CROSSCOMPILING)
set_source_files_properties("test_data/tables.S" PROPERTIES OBJECT_DEPENDS "${GENERATED_TABLE_BLOBS}")
add_executable("acpi_tests"
+ "acpi/common/table_header.test.cpp"
"acpi/madt.test.cpp"
"acpi/pointers.test.cpp"
diff --git a/libs/acpi/acpi/common/table_header.cpp b/libs/acpi/acpi/common/table_header.cpp
new file mode 100644
index 0000000..17a8219
--- /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 common_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 common_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 common_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 common_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 common_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 common_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 common_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 common_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..8ecfd0a
--- /dev/null
+++ b/libs/acpi/acpi/common/table_header.hpp
@@ -0,0 +1,57 @@
+#ifndef ACPI_COMMON_TABLE_HEADER_HPP
+#define ACPI_COMMON_TABLE_HEADER_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 common_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;
+
+ //! Validate this table's checksum
+ [[nodiscard]] auto validate() const noexcept -> bool;
+
+ 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..e43e403
--- /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::common_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::common_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/test_data/table_header.asl b/libs/acpi/test_data/table_header.asl
new file mode 100644
index 0000000..8cddc03
--- /dev/null
+++ b/libs/acpi/test_data/table_header.asl
@@ -0,0 +1,9 @@
+[0004] Signature : "TEST"
+[0004] Table Length : 00000000
+[0001] Revision : 01
+[0001] Checksum : 00
+[0006] Oem ID : "FEMO "
+[0008] Oem Table ID : "HDRTEST "
+[0004] Oem Revision : 00000001
+[0004] Asl Compiler ID : "INTL"
+[0004] Asl Compiler Revision : 00000000
diff --git a/libs/acpi/test_data/tables.S b/libs/acpi/test_data/tables.S
index f40f070..da9a12f 100644
--- a/libs/acpi/test_data/tables.S
+++ b/libs/acpi/test_data/tables.S
@@ -11,5 +11,6 @@
TABLE(basic_madt, "basic_madt.aml")
TABLE(basic_rsdt, "basic_rsdt.aml")
TABLE(basic_rsdp, "basic_rsdp.aml")
+TABLE(table_header, "table_header.aml")
#undef TABLE
diff --git a/libs/acpi/test_data/tables.hpp b/libs/acpi/test_data/tables.hpp
index 510cbda..dc39b37 100644
--- a/libs/acpi/test_data/tables.hpp
+++ b/libs/acpi/test_data/tables.hpp
@@ -18,6 +18,7 @@ namespace acpi::test_data::tables
TABLE(basic_madt);
TABLE(basic_rsdt);
TABLE(basic_rsdp);
+ TABLE(table_header);
} // namespace acpi::test_data::tables