diff options
Diffstat (limited to 'kapi')
| -rw-r--r-- | kapi/include/kapi/acpi.hpp | 107 | ||||
| -rw-r--r-- | kapi/include/kapi/acpi/multiple_apic_description_table.hpp | 104 | ||||
| -rw-r--r-- | kapi/include/kapi/acpi/pointers.hpp | 79 | ||||
| -rw-r--r-- | kapi/include/kapi/acpi/system_description_table_header.hpp | 76 | ||||
| -rw-r--r-- | kapi/include/kapi/acpi/table_iterator.hpp | 64 | ||||
| -rw-r--r-- | kapi/include/kapi/acpi/table_type.hpp | 22 |
6 files changed, 363 insertions, 89 deletions
diff --git a/kapi/include/kapi/acpi.hpp b/kapi/include/kapi/acpi.hpp index 75b6c48..5323fee 100644 --- a/kapi/include/kapi/acpi.hpp +++ b/kapi/include/kapi/acpi.hpp @@ -1,14 +1,15 @@ #ifndef TEACHOS_KAPI_ACPI_HPP #define TEACHOS_KAPI_ACPI_HPP -#include "kapi/memory.hpp" +#include "kapi/acpi/multiple_apic_description_table.hpp" // IWYU pragma: export +#include "kapi/acpi/pointers.hpp" // IWYU pragma: export +#include "kapi/acpi/system_description_table_header.hpp" // IWYU pragma: export +#include "kapi/acpi/table_type.hpp" #include <kstd/memory> #include <kstd/units> -#include <array> #include <cstddef> -#include <cstdint> #include <span> #include <string_view> @@ -18,91 +19,6 @@ namespace kapi::acpi //! @addtogroup kapi-acpi-kernel-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<char, 8> m_signature; - [[maybe_unused]] std::uint8_t m_checksum; - std::array<char, 6> m_oem_id; - std::uint8_t m_revision; - std::array<std::byte, 4> 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<std::byte, 8> m_xsdt_address; - [[maybe_unused]] std::uint8_t m_extended_checksum; - [[maybe_unused]] std::array<std::byte, 3> m_reserved; - }; - - struct [[gnu::packed]] system_description_table_header - { - [[nodiscard]] auto checksum() const noexcept -> std::uint8_t; - [[nodiscard]] auto creator_revision() const noexcept -> std::uint32_t; - [[nodiscard]] auto creator_id() const noexcept -> std::uint32_t; - [[nodiscard]] auto length() const noexcept -> kstd::units::bytes; - [[nodiscard]] auto oem_id() const noexcept -> std::string_view; - [[nodiscard]] auto oem_revision() const noexcept -> std::uint32_t; - [[nodiscard]] auto oem_table_id() const noexcept -> std::string_view; - [[nodiscard]] auto revision() const noexcept -> std::uint8_t; - [[nodiscard]] auto signature() const noexcept -> std::string_view; - - private: - std::array<char, 4> m_signature; - std::uint32_t m_length; - std::uint8_t m_revision; - std::uint8_t m_checksum; - std::array<char, 6> m_oem_id; - std::array<char, 8> m_oem_table_id; - std::uint32_t m_oem_revision; - std::uint32_t m_creator_id; - std::uint32_t m_creator_revision; - }; - - struct [[gnu::packed]] madt_header : system_description_table_header - { - [[nodiscard]] auto local_interrupt_controller_address() const noexcept -> memory::physical_address; - [[nodiscard]] auto flags() const noexcept -> std::uint32_t; - - private: - std::uint32_t m_local_interrupt_controller_address; - std::uint32_t m_flags; - }; - - struct [[gnu::packed]] madt_subtable_header - { - [[nodiscard]] auto type() const noexcept -> std::uint8_t; - [[nodiscard]] auto length() const noexcept -> std::size_t; - - private: - std::uint8_t m_type; - std::uint8_t m_length; - }; - - struct [[gnu::packed]] madt_local_apic : madt_subtable_header - { - [[nodiscard]] auto apic_id() const noexcept -> std::uint8_t; - [[nodiscard]] auto flags() const noexcept -> std::uint32_t; - [[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; - }; - //! Initialize the ACPI subsystem and discover the available tables. //! //! @return true iff. a valid system description tabled was found, false otherwise. @@ -114,17 +30,30 @@ namespace kapi::acpi //! @return true iff. the checksum is valid, false otherwise. auto validate_checksum(std::span<std::byte const> data) -> bool; - //! Get an ACPI table by its signature. + //! Get a pointer to an ACPI table by its signature. //! //! @param signature The signature of the table to get. //! @return A pointer to the table if found, nullptr otherwise. auto get_table(std::string_view signature) -> kstd::observer_ptr<system_description_table_header const>; + //! Get a type-cast pointer to an ACPI table by its signature. + //! + //! @tparam Signature The signature of the table to get + //! @return A pointer to the table if found, nullptr otherwise. + template<char const * Signature> + auto get_table() -> kstd::observer_ptr<table_type_t<Signature> const> + { + return kstd::make_observer(static_cast<table_type_t<Signature> const *>(get_table(Signature).get())); + } + //! @} //! @addtogroup kapi-acpi-platform-defined //! @{ + //! Retrieve the RSDP or XSDP for this system. + //! + //! @return a pointer to either the RSDP or XSDP data structure, or @p nullptr if neither is present. auto get_root_pointer() -> kstd::observer_ptr<root_system_description_pointer const>; //! @} diff --git a/kapi/include/kapi/acpi/multiple_apic_description_table.hpp b/kapi/include/kapi/acpi/multiple_apic_description_table.hpp new file mode 100644 index 0000000..33acac9 --- /dev/null +++ b/kapi/include/kapi/acpi/multiple_apic_description_table.hpp @@ -0,0 +1,104 @@ +#ifndef TEACHOS_KAPI_ACPI_MUTIPLE_APIC_DESCRIPTION_TABLE_HEADER_HPP +#define TEACHOS_KAPI_ACPI_MUTIPLE_APIC_DESCRIPTION_TABLE_HEADER_HPP + +// IWYU pragma: private, include "kapi/acpi.hpp" + +#include "kapi/acpi/system_description_table_header.hpp" +#include "kapi/acpi/table_iterator.hpp" +#include "kapi/acpi/table_type.hpp" +#include "kapi/memory.hpp" + +#include <kstd/ext/bitfield_enum> +#include <kstd/units> + +#include <cstddef> +#include <cstdint> +#include <type_traits> + +namespace kapi::acpi +{ + + //! @addtogroup kapi-acpi-kernel-defined + //! @{ + + struct [[gnu::packed]] multiple_apic_description_table_entry + { + enum struct types : std::uint8_t + { + processor_local_apic, + io_apic, + io_apic_interrupt_source_override, + io_apic_nmi_source, + local_apic_nmi_interrupts, + local_apic_address_override, + processor_local_x2_apic, + }; + + [[nodiscard]] auto type() const noexcept -> types; + [[nodiscard]] auto length() const noexcept -> std::size_t; + + private: + std::uint8_t m_type; + std::uint8_t m_length; + }; + + //! The common header for all + struct [[gnu::packed]] multiple_apic_description_table : system_description_table_header + { + using iterator = table_iterator<multiple_apic_description_table_entry const>; + using const_iterator = iterator; + + [[nodiscard]] auto local_interrupt_controller_address() const noexcept -> memory::physical_address; + [[nodiscard]] auto flags() const noexcept -> std::uint32_t; + + [[nodiscard]] auto begin() const noexcept -> iterator; + [[nodiscard]] auto cbegin() const noexcept -> iterator; + [[nodiscard]] auto end() const noexcept -> iterator; + [[nodiscard]] auto cend() const noexcept -> iterator; + + private: + std::uint32_t m_local_interrupt_controller_address; + std::uint32_t m_flags; + }; + + struct [[gnu::packed]] processor_local_apic : multiple_apic_description_table_entry + { + enum struct flags : std::uint32_t + { + processor_enabled = 1, + online_capable = 2, + }; + + [[nodiscard]] auto apic_id() const noexcept -> std::uint8_t; + [[nodiscard]] auto active_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; + }; + + //! @} + + //! @addtogroup kapi-acpi + //! @{ + + constexpr char const madt_table_signature[] = "APIC"; // NOLINT + + template<> + struct table_type<madt_table_signature> + { + using type = multiple_apic_description_table; + }; + + //! @} + +} // namespace kapi::acpi + +template<> +struct kstd::ext::is_bitfield_enum<kapi::acpi::processor_local_apic::flags> : std::true_type +{ +}; + +#endif diff --git a/kapi/include/kapi/acpi/pointers.hpp b/kapi/include/kapi/acpi/pointers.hpp new file mode 100644 index 0000000..2b88720 --- /dev/null +++ b/kapi/include/kapi/acpi/pointers.hpp @@ -0,0 +1,79 @@ +#ifndef TEACHOS_KAPI_ACPI_POINTERS_HPP +#define TEACHOS_KAPI_ACPI_POINTERS_HPP + +// IWYU pragma: private, include "kapi/acpi.hpp" + +#include "kapi/memory.hpp" + +#include <kstd/units> + +#include <array> +#include <cstddef> +#include <cstdint> +#include <string_view> + +namespace kapi::acpi +{ + + //! @addtogroup kapi-acpi-kernel-defined + //! @{ + + //! A pointer to the Root System Description Table. + struct [[gnu::packed]] root_system_description_pointer + { + //! Get the ID of the OEM, usually a vendor name. + [[nodiscard]] auto oem_id() const noexcept -> std::string_view; + + //! Get the revision of the ACPI Root System Description Table. + //! + //! @note Revisions greater or equal to two indicate that the system uses the Extended System Description Table, and + //! as such that table should be use to query information. + [[nodiscard]] auto revision() const noexcept -> std::uint8_t; + + //! Get the signature of this pointer. + //! + //! A valid RSDP must always carry the signature "RSD PTR ". + [[nodiscard]] auto signature() const noexcept -> std::string_view; + + //! Get the physical address of the pointed-to Root System Description Table. + [[nodiscard]] auto table_address() const noexcept -> memory::physical_address; + + //! Validate the checksum of this RSDP. + //! + //! @return @p true iff. the checksum of this RSDP is valid, @p false otherwise. + [[nodiscard]] auto validate() const noexcept -> bool; + + private: + std::array<char, 8> m_signature; + [[maybe_unused]] std::uint8_t m_checksum; + std::array<char, 6> m_oem_id; + std::uint8_t m_revision; + std::array<std::byte, 4> m_rsdt_address; + }; + + //! A pointer to the Extended System Description Table. + struct [[gnu::packed]] extended_system_description_pointer : root_system_description_pointer + { + //! Get the length of the data contained in this pointer. + [[nodiscard]] auto length() const noexcept -> kstd::units::bytes; + + //! Get the address of the pointed-to Extended System Description Table. + [[nodiscard]] auto table_address() const noexcept -> memory::physical_address; + + //! Validate the checksum of this XSDP. + //! + //! @return @p true iff. the checksum of this RSDP is valid, @p false otherwise. + [[nodiscard]] auto validate() const noexcept -> bool; + + private: + std::uint32_t m_length; + std::array<std::byte, 8> m_xsdt_address; + [[maybe_unused]] std::uint8_t m_extended_checksum; + [[maybe_unused]] std::array<std::byte, 3> m_reserved; + }; + + //! @} + +} // namespace kapi::acpi + +#endif diff --git a/kapi/include/kapi/acpi/system_description_table_header.hpp b/kapi/include/kapi/acpi/system_description_table_header.hpp new file mode 100644 index 0000000..b336ea1 --- /dev/null +++ b/kapi/include/kapi/acpi/system_description_table_header.hpp @@ -0,0 +1,76 @@ +#ifndef TEACHOS_KAPI_ACPI_SYSTEM_DESCRIPTION_TABLE_HEADER_HPP +#define TEACHOS_KAPI_ACPI_SYSTEM_DESCRIPTION_TABLE_HEADER_HPP + +// IWYU pragma: private, include "kapi/acpi.hpp" + +#include "kapi/acpi/table_type.hpp" + +#include <kstd/units> + +#include <array> +#include <cstdint> +#include <string_view> + +namespace kapi::acpi +{ + + //! @addtogroup kapi-acpi-kernel-defined + //! @{ + + //! The common header of all System Description Tables. + struct [[gnu::packed]] system_description_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::uint32_t; + + //! 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<char, 4> m_signature; + std::uint32_t m_length; + std::uint8_t m_revision; + [[maybe_unused]] std::uint8_t m_checksum; + std::array<char, 6> m_oem_id; + std::array<char, 8> m_oem_table_id; + std::uint32_t m_oem_revision; + std::uint32_t m_creator_id; + std::uint32_t m_creator_revision; + }; + + //! @} + // + //! @addtogroup kapi-acpi + //! @{ + + constexpr char const rsdt_table_signature[] = "RSDT"; // NOLINT + + template<> + struct table_type<rsdt_table_signature> + { + using type = system_description_table_header; + }; + + //! @} + +} // namespace kapi::acpi + +#endif diff --git a/kapi/include/kapi/acpi/table_iterator.hpp b/kapi/include/kapi/acpi/table_iterator.hpp new file mode 100644 index 0000000..998d6d6 --- /dev/null +++ b/kapi/include/kapi/acpi/table_iterator.hpp @@ -0,0 +1,64 @@ +#ifndef TEACHOS_KAPI_ACPI_TABLE_ITERATOR_HPP +#define TEACHOS_KAPI_ACPI_TABLE_ITERATOR_HPP + +#include <bit> +#include <cstddef> +#include <iterator> + +namespace kapi::acpi +{ + + template<typename EntryType> + struct 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 table_iterator() noexcept = default; + + constexpr table_iterator(pointer entry, pointer limit) noexcept + : m_entry{entry} + , m_limit{limit} + {} + + constexpr auto operator++() noexcept -> 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 -> table_iterator + { + auto copy = *this; + ++*this; + return copy; + } + + constexpr auto operator*() const noexcept -> reference + { + return *m_entry; + } + + constexpr auto operator==(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{}; + }; + +} // namespace kapi::acpi + +#endif diff --git a/kapi/include/kapi/acpi/table_type.hpp b/kapi/include/kapi/acpi/table_type.hpp new file mode 100644 index 0000000..e088a24 --- /dev/null +++ b/kapi/include/kapi/acpi/table_type.hpp @@ -0,0 +1,22 @@ +#ifndef TEACHOS_KAPI_ACPI_TABLE_TYPE_HPP +#define TEACHOS_KAPI_ACPI_TABLE_TYPE_HPP + +// IWYU pragma: private + +namespace kapi::acpi +{ + + //! @addtogroup kapi-acpi-kernel-defined + //! @{ + + template<char const *> + struct table_type; + + template<char const * Signature> + using table_type_t = typename table_type<Signature>::type; + + //! @} + +} // namespace kapi::acpi + +#endif |
