From 54079f9b8dab6a70a0826d4b4f86d46765cf63f9 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 23 Dec 2025 13:09:28 +0100 Subject: libs/multiboot2: clean up file structure --- libs/multiboot2/include/multiboot2/constants.hpp | 7 +- .../multiboot2/constants/architecture_id.hpp | 22 +++ .../multiboot2/constants/information_id.hpp | 42 +++++ .../include/multiboot2/constants/memory_type.hpp | 25 +++ .../include/multiboot2/constants/tag_id.hpp | 31 ++++ libs/multiboot2/include/multiboot2/impl/data.hpp | 135 -------------- libs/multiboot2/include/multiboot2/impl/ids.hpp | 81 -------- .../include/multiboot2/impl/iterator.hpp | 73 -------- libs/multiboot2/include/multiboot2/impl/tag.hpp | 206 --------------------- libs/multiboot2/include/multiboot2/information.hpp | 46 ++--- .../include/multiboot2/information/data.hpp | 138 ++++++++++++++ .../include/multiboot2/information/iterator.hpp | 73 ++++++++ .../include/multiboot2/information/tag.hpp | 206 +++++++++++++++++++++ 13 files changed, 561 insertions(+), 524 deletions(-) create mode 100644 libs/multiboot2/include/multiboot2/constants/architecture_id.hpp create mode 100644 libs/multiboot2/include/multiboot2/constants/information_id.hpp create mode 100644 libs/multiboot2/include/multiboot2/constants/memory_type.hpp create mode 100644 libs/multiboot2/include/multiboot2/constants/tag_id.hpp delete mode 100644 libs/multiboot2/include/multiboot2/impl/data.hpp delete mode 100644 libs/multiboot2/include/multiboot2/impl/ids.hpp delete mode 100644 libs/multiboot2/include/multiboot2/impl/iterator.hpp delete mode 100644 libs/multiboot2/include/multiboot2/impl/tag.hpp create mode 100644 libs/multiboot2/include/multiboot2/information/data.hpp create mode 100644 libs/multiboot2/include/multiboot2/information/iterator.hpp create mode 100644 libs/multiboot2/include/multiboot2/information/tag.hpp diff --git a/libs/multiboot2/include/multiboot2/constants.hpp b/libs/multiboot2/include/multiboot2/constants.hpp index 0f6b82f..2198210 100644 --- a/libs/multiboot2/include/multiboot2/constants.hpp +++ b/libs/multiboot2/include/multiboot2/constants.hpp @@ -1,18 +1,13 @@ #ifndef MULTIBOOT2_CONSTANTS_HPP #define MULTIBOOT2_CONSTANTS_HPP -#include "impl/ids.hpp" // IWYU pragma: export +#include "constants/architecture_id.hpp" // IWYU pragma: export #include namespace multiboot2 { - using impl::architecture_id; - using impl::information_id; - using impl::memory_type; - using impl::tag_id; - constexpr auto inline header_magic = std::uint32_t{0xe852'50d6}; } // namespace multiboot2 diff --git a/libs/multiboot2/include/multiboot2/constants/architecture_id.hpp b/libs/multiboot2/include/multiboot2/constants/architecture_id.hpp new file mode 100644 index 0000000..3d560da --- /dev/null +++ b/libs/multiboot2/include/multiboot2/constants/architecture_id.hpp @@ -0,0 +1,22 @@ +#ifndef MULTIBOOT2_CONSTANTS_ARCHITECTURE_ID_HPP +#define MULTIBOOT2_CONSTANTS_ARCHITECTURE_ID_HPP + +// IWYU pragma: private, include + +#include + +namespace multiboot2 +{ + + //! The IDs of the supported system architectures. + enum struct architecture_id : std::uint32_t + { + //! 32-bit protected mode i386 + i386 = 0, + //! 32-bit MIPS + MIPS32 = 4, + }; + +} // namespace multiboot2 + +#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/constants/information_id.hpp b/libs/multiboot2/include/multiboot2/constants/information_id.hpp new file mode 100644 index 0000000..7b0fd55 --- /dev/null +++ b/libs/multiboot2/include/multiboot2/constants/information_id.hpp @@ -0,0 +1,42 @@ +#ifndef MULTIBOOT2_CONSTANTS_INFORMATION_ID_HPP +#define MULTIBOOT2_CONSTANTS_INFORMATION_ID_HPP + +// IWYU pragma: private, include + +#include + +namespace multiboot2 +{ + + /** + * @brief Information tag IDs. + */ + enum struct information_id : std::uint32_t + { + END, ///< Signals final tag for the multiboot2 information structure. + CMDLINE, ///< Contains the command line string. + BOOT_LOADER_NAME, ///< Contains the name of the boot loader booting the kernel. + MODULE, ///< Indicates the boot module which was loaded along the kernel image. + BASIC_MEMORY_INFO, ///< Contains the amount of lower (0MB start address) and upper memory (1MB start address). + BOOTDEV, ///< Indicates which BIOS disk device the hoot loader has loaded the OS image from. + MEMORY_MAP, ///< Describes the memory layout of the system with individual areas and their flags. + VBE_INFO, ///< Includes information to access and utilize the device GPU. + FRAMEBUFFER, ///< VBE framebuffer information. + ELF_SECTIONS, ///< Includes list of all section headers from the loaded ELF kernel. + APM_INFO, ///< Advanced Power Management information. + EFI32, ///< EFI 32 bit system table pointer. + EFI64, ///< EFI 64 bit system table pointer. + SMBIOS, ///< Contains copy of all System Management BIOS tables. + ACPI_OLD, ///< Contains copy of RSDP as defined per ACPI1.0 specification. + ACPI_NEW, ///< Contains copy of RSDP as defined per ACPI2.0 or later specification. + NETWORK, ///< Contains network information specified specified as DHCP. + EFI_MEMORY_MAP, ///< Contains EFI memory map. + EFI_BS_NOT_TERMINATED, ///< Indicates ExitBootServices wasn't called. + EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer. + EFI64_IMAGE_HANDLE, ///< EFI 64 bit image handle pointer. + LOAD_BASE_ADDRESS ///< Contains image load base physical address. + }; + +} // namespace multiboot2 + +#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/constants/memory_type.hpp b/libs/multiboot2/include/multiboot2/constants/memory_type.hpp new file mode 100644 index 0000000..56fd0b8 --- /dev/null +++ b/libs/multiboot2/include/multiboot2/constants/memory_type.hpp @@ -0,0 +1,25 @@ +#ifndef MULTIBOOT2_CONSTANTS_MEMORY_TYPE_HPP +#define MULTIBOOT2_CONSTANTS_MEMORY_TYPE_HPP + +// IWYU pragma: private, include + +#include + +namespace multiboot2 +{ + + /** + * @brief Memory type IDs. + */ + enum struct memory_type : std::uint32_t + { + AVAILABLE = 1, + RESERVED, + ACPI_RECLAIMABLE, + NON_VOLATILE_STORAGE, + BAD_RAM, + }; + +} // namespace multiboot2 + +#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/constants/tag_id.hpp b/libs/multiboot2/include/multiboot2/constants/tag_id.hpp new file mode 100644 index 0000000..378c2b6 --- /dev/null +++ b/libs/multiboot2/include/multiboot2/constants/tag_id.hpp @@ -0,0 +1,31 @@ +#ifndef MULTIBOOT2_CONSTANTS_TAG_ID_HPP +#define MULTIBOOT2_CONSTANTS_TAG_ID_HPP + +// IWYU pragma: private, include + +#include + +namespace multiboot2 +{ + + /** + * @brief Header tag IDs. + */ + enum struct tag_id : std::uint32_t + { + END, + INFORMATION_REQUEST, + ADDRESSES, + ENTRY_ADDRESS, + CONSOLE_FLAGS, + PREFERRED_FRAMEBUFFER_MODE, + PAGE_ALIGN_MODULES, + EFI_BOOT_SERVICES_SUPPORTED, + EFI32_ENTRY_ADDRESS, + EFI64_ENTRY_ADDRESS, + RELOCATABLE, + }; + +} // namespace multiboot2 + +#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/impl/data.hpp b/libs/multiboot2/include/multiboot2/impl/data.hpp deleted file mode 100644 index 733ce3a..0000000 --- a/libs/multiboot2/include/multiboot2/impl/data.hpp +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef MULTIBOOT2_IMPL_DATA_HPP -#define MULTIBOOT2_IMPL_DATA_HPP - -// IWYU pragma: private - -#include "multiboot2/impl/ids.hpp" - -#include - -namespace multiboot2::impl -{ - template - struct tag_data - { - constexpr auto static inline id = Id; - }; - - /** - * @brief Basic system memory information - */ - struct basic_memory_data : tag_data - { - /** - * @brief Amount of lower memory (below 1MiB) available to the system. - * - * The maximum possible value for this field is 640 KiB. - */ - std::uint32_t lower_KiB; - - /** - * @brief Amount of upper memory (above 1MiB) available to the system. - * - * The maximum possible value for this field is the address of the first upper memory hole minus 1MiB. - */ - std::uint32_t upper_KiB; - }; - - /** - * @brief Device the image got loaded from - */ - struct bios_boot_device_data : tag_data - { - /** - * @brief BIOS device number as understood by INT 13h. - */ - std::uint32_t device_number; - - /** - * @brief Number of the primary partition. - */ - std::uint32_t partition_number; - - /** - * @brief Number the sub-partion on the primary partition. - */ - std::uint32_t sub_partition_number; - }; - - /** - * @brief Supplied image command line - */ - struct command_line_data : tag_data - { - /* This struct intentionally left blank. */ - }; - - /** - * @brief ELF symbols of the image - */ - struct elf_symbols_data : tag_data - { - std::uint32_t count; - std::uint32_t entry_size; - std::uint32_t string_table_index; - }; - - /** - * @brief Name of the boot loader - */ - struct loader_name_data : tag_data - { - /* This struct intentionally left blank. */ - }; - - /** - * @brief Detailed map of the memory regions present in the system - * - */ - struct memory_map_data : tag_data - { - /** - * @brief A region of memory - */ - struct region - { - /** - * @brief Check if the memory described by this region is available for use. - */ - [[nodiscard]] constexpr auto available() const noexcept - { - return type == memory_type::AVAILABLE; - } - - /** - * @brief Start address of this region - */ - std::uint64_t base; - - /** - * @brief Size of this region in bytes. - */ - std::uint64_t size_in_B; - - /** - * @brief Type of this region. - */ - memory_type type; - - std::uint32_t : 0; - }; - - /** - * @brief Size of each entry present in the map - */ - std::uint32_t entry_size; - - /** - * @brief Version of each entry present in the map - */ - std::uint32_t entry_version; - }; - -} // namespace multiboot2::impl - -#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/impl/ids.hpp b/libs/multiboot2/include/multiboot2/impl/ids.hpp deleted file mode 100644 index 98bc1f2..0000000 --- a/libs/multiboot2/include/multiboot2/impl/ids.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef MULTIBOOT2_IMPL_IDS_HPP -#define MULTIBOOT2_IMPL_IDS_HPP - -// IWYU pragma: private - -#include - -namespace multiboot2::impl -{ - - /** - * @brief Information tag IDs. - */ - enum struct information_id : std::uint32_t - { - END, ///< Signals final tag for the multiboot2 information structure. - CMDLINE, ///< Contains the command line string. - BOOT_LOADER_NAME, ///< Contains the name of the boot loader booting the kernel. - MODULE, ///< Indicates the boot module which was loaded along the kernel image. - BASIC_MEMORY_INFO, ///< Contains the amount of lower (0MB start address) and upper memory (1MB start address). - BOOTDEV, ///< Indicates which BIOS disk device the hoot loader has loaded the OS image from. - MEMORY_MAP, ///< Describes the memory layout of the system with individual areas and their flags. - VBE_INFO, ///< Includes information to access and utilize the device GPU. - FRAMEBUFFER, ///< VBE framebuffer information. - ELF_SECTIONS, ///< Includes list of all section headers from the loaded ELF kernel. - APM_INFO, ///< Advanced Power Management information. - EFI32, ///< EFI 32 bit system table pointer. - EFI64, ///< EFI 64 bit system table pointer. - SMBIOS, ///< Contains copy of all System Management BIOS tables. - ACPI_OLD, ///< Contains copy of RSDP as defined per ACPI1.0 specification. - ACPI_NEW, ///< Contains copy of RSDP as defined per ACPI2.0 or later specification. - NETWORK, ///< Contains network information specified specified as DHCP. - EFI_MEMORY_MAP, ///< Contains EFI memory map. - EFI_BS_NOT_TERMINATED, ///< Indicates ExitBootServices wasn't called. - EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer. - EFI64_IMAGE_HANDLE, ///< EFI 64 bit image handle pointer. - LOAD_BASE_ADDRESS ///< Contains image load base physical address. - }; - - /** - * @brief Header tag IDs. - */ - enum struct tag_id : std::uint32_t - { - END, - INFORMATION_REQUEST, - ADDRESSES, - ENTRY_ADDRESS, - CONSOLE_FLAGS, - PREFERRED_FRAMEBUFFER_MODE, - PAGE_ALIGN_MODULES, - EFI_BOOT_SERVICES_SUPPORTED, - EFI32_ENTRY_ADDRESS, - EFI64_ENTRY_ADDRESS, - RELOCATABLE, - }; - - /** - * @brief System architecture IDs. - */ - enum struct architecture_id : std::uint32_t - { - I386 = 0, - MIPS32 = 4, - }; - - /** - * @brief Memory type IDs. - */ - enum struct memory_type : std::uint32_t - { - AVAILABLE = 1, - RESERVED, - ACPI_RECLAIMABLE, - NON_VOLATILE_STORAGE, - BAD_RAM, - }; - -} // namespace multiboot2::impl - -#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/impl/iterator.hpp b/libs/multiboot2/include/multiboot2/impl/iterator.hpp deleted file mode 100644 index 5651f22..0000000 --- a/libs/multiboot2/include/multiboot2/impl/iterator.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef MULTIBOOT2_IMPL_INFORMATION_ITERATOR_HPP -#define MULTIBOOT2_IMPL_INFORMATION_ITERATOR_HPP - -// IWYU pragma: private - -#include "multiboot2/impl/ids.hpp" -#include "multiboot2/impl/tag.hpp" - -#include -#include -#include - -namespace multiboot2::impl -{ - - struct information_iterator - { - using iterator_category = std::forward_iterator_tag; - using value_type = impl::tag_header; - using pointer = value_type const *; - using reference = value_type const &; - using difference_type = std::ptrdiff_t; - - constexpr information_iterator() = default; - - constexpr explicit information_iterator(impl::tag_header const * offset) - : m_current(offset) - {} - - constexpr auto operator==(information_iterator const &) const noexcept -> bool = default; - - constexpr auto operator*() const noexcept -> reference - { - return *(m_current.value()); - } - - constexpr auto operator->() const noexcept -> pointer - { - return m_current.value(); - } - - constexpr auto operator++() noexcept -> information_iterator & - { - if (m_current) - { - if (auto next = m_current.value()->next(); next->information_id() != information_id::END) - { - m_current = next; - } - else - { - m_current.reset(); - } - } - return *this; - } - - constexpr auto operator++(int) noexcept -> information_iterator - { - auto copy = *this; - ++(*this); - return copy; - } - - private: - std::optional m_current{}; - }; - - static_assert(std::input_or_output_iterator); - -} // namespace multiboot2::impl - -#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/impl/tag.hpp b/libs/multiboot2/include/multiboot2/impl/tag.hpp deleted file mode 100644 index 708cda4..0000000 --- a/libs/multiboot2/include/multiboot2/impl/tag.hpp +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef MULTIBOOT2_IMPL_TAG_HPP -#define MULTIBOOT2_IMPL_TAG_HPP - -// IWYU pragma: private - -#include "multiboot2/impl/ids.hpp" - -#include -#include -#include -#include - -namespace multiboot2::impl -{ - - /** - * @brief Header data and functionality shared by all tags. - */ - struct tag_header - { - tag_header() - : m_id{} - , m_size{} - {} - - tag_header(tag_header const * data) - : tag_header{*data} - {} - - [[nodiscard]] auto full_size() const noexcept -> std::size_t - { - return (m_size + 7) & (~7); - } - - [[nodiscard]] auto information_id() const noexcept -> impl::information_id const & - { - return m_id; - } - - [[nodiscard]] auto next() const noexcept -> tag_header const * - { - return std::bit_cast(std::bit_cast(this) + full_size()); - } - - [[nodiscard]] auto unaligned_size() const noexcept -> std::uint32_t - { - return m_size; - } - - private: - impl::information_id m_id; - std::uint32_t m_size; - }; - - /** - * @brief A tag containing no variable length array data. - */ - template - struct tag : tag_header, Data - { - tag() - : tag_header{} - , Data{} - {} - - explicit tag(tag_header const * header) - requires(sizeof(tag) > sizeof(tag_header)) - : tag_header{header} - , Data{*std::bit_cast(header + 1)} - {} - - explicit tag(tag_header const * header) - requires(sizeof(tag) == sizeof(tag_header)) - : tag_header{header} - , Data{} - {} - }; - - /** - * @brief A tag containing variable length array data. - */ - template typename Range> - struct vla_tag : tag - { - using range_type = Range; - - using value_type = range_type::value_type; - using reference = range_type::const_reference; - using const_reference = range_type::const_reference; - using pointer = range_type::const_pointer; - using const_pointer = range_type::const_pointer; - - using iterator = range_type::const_iterator; - using const_iterator = range_type::const_iterator; - using reverse_iterator = range_type::const_reverse_iterator; - using const_reverse_iterator = range_type::const_reverse_iterator; - using size_type = range_type::size_type; - using difference_type = range_type::difference_type; - - vla_tag() - : tag{} - , m_vla{} - {} - - explicit vla_tag(tag_header const * header) - : tag{header} - , m_vla{vla_start(header), vla_size(header)} - {} - - [[nodiscard]] auto begin() const noexcept -> const_iterator - { - return m_vla.begin(); - } - - [[nodiscard]] auto end() const noexcept -> const_iterator - { - return m_vla.end(); - } - - [[nodiscard]] auto cbegin() const noexcept -> const_iterator - { - return begin(); - } - - [[nodiscard]] auto cend() const noexcept -> const_iterator - { - return end(); - } - - [[nodiscard]] auto rbegin() const noexcept -> const_reverse_iterator - { - return m_vla.rbegin(); - } - - [[nodiscard]] auto rend() const noexcept -> const_reverse_iterator - { - return m_vla.rend(); - } - - [[nodiscard]] auto crbegin() const noexcept -> const_reverse_iterator - { - return rbegin(); - } - - [[nodiscard]] auto crend() const noexcept -> const_reverse_iterator - { - return rend(); - } - - [[nodiscard]] auto front() const noexcept -> const_reference - { - return m_vla.front(); - } - - [[nodiscard]] auto back() const noexcept -> const_reference - { - return m_vla.back(); - } - - [[nodiscard]] auto size() const noexcept -> std::size_t - { - return m_vla.size(); - } - - [[nodiscard]] auto empty() const noexcept -> bool - { - return m_vla.empty(); - } - - [[nodiscard]] auto data() const noexcept -> const_pointer - { - return m_vla.data(); - } - - [[nodiscard]] auto at() const -> const_reference - { - return m_vla.at(); - } - - [[nodiscard]] auto operator[](std::size_t index) const noexcept -> const_reference - { - return m_vla[index]; - } - - private: - auto static vla_start(tag_header const * header) noexcept -> VlaData * - { - auto raw = std::bit_cast(header); - auto start = raw + sizeof(tag); - return std::bit_cast(start); - } - - auto static vla_size(tag_header const * header) noexcept -> std::size_t - { - auto size = (header->unaligned_size() - sizeof(tag) - - std::is_same_v> * 1) / - sizeof(VlaData); - return size; - } - - range_type m_vla; - }; - -} // namespace multiboot2::impl - -#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/information.hpp b/libs/multiboot2/include/multiboot2/information.hpp index 2d60a6d..abb0826 100644 --- a/libs/multiboot2/include/multiboot2/information.hpp +++ b/libs/multiboot2/include/multiboot2/information.hpp @@ -1,9 +1,9 @@ -#ifndef JOS_MULTIBOOT2_INFORMATION_HPP -#define JOS_MULTIBOOT2_INFORMATION_HPP +#ifndef MULTIBOOT2_INFORMATION_HPP +#define MULTIBOOT2_INFORMATION_HPP -#include "impl/data.hpp" -#include "impl/iterator.hpp" -#include "impl/tag.hpp" +#include "information/data.hpp" // IWYU pragma: export +#include "information/iterator.hpp" // IWYU pragma: export +#include "information/tag.hpp" // IWYU pragma: export #include #include @@ -20,25 +20,25 @@ namespace multiboot2 { /** - * @copydoc multiboot2::impl::basic_memory_data + * @copydoc multiboot2::basic_memory_data */ - struct basic_memory : impl::tag + struct basic_memory : tag { using tag::tag; }; /** - * @copydoc multiboot2::impl::bios_boot_device_data + * @copydoc multiboot2::bios_boot_device_data */ - struct bios_boot_device : impl::tag + struct bios_boot_device : tag { using tag::tag; }; /** - * @copydoc multiboot2::impl::command_line_data + * @copydoc multiboot2::command_line_data */ - struct command_line : impl::vla_tag + struct command_line : vla_tag { using vla_tag::vla_tag; @@ -52,12 +52,12 @@ namespace multiboot2 }; /** - * @copydoc multiboot2::impl::elf_symbols_data + * @copydoc multiboot2::elf_symbols_data */ template - struct elf_symbols : impl::vla_tag const, std::span> + struct elf_symbols : vla_tag const, std::span> { - using base = impl::vla_tag const, std::span>; + using base = vla_tag const, std::span>; using base::base; [[nodiscard]] auto name(elf::section_header const & section) const noexcept -> std::string_view @@ -75,9 +75,9 @@ namespace multiboot2 }; /** - * @copydoc multiboot2::impl::loader_name_data + * @copydoc multiboot2::loader_name_data */ - struct loader_name : impl::vla_tag + struct loader_name : vla_tag { using vla_tag::vla_tag; @@ -91,9 +91,9 @@ namespace multiboot2 }; /** - * @copydoc multiboot2::impl::memory_map_data + * @copydoc multiboot2::memory_map_data */ - struct memory_map : impl::vla_tag + struct memory_map : vla_tag { using vla_tag::vla_tag; @@ -108,10 +108,10 @@ namespace multiboot2 struct information_view { - using iterator = impl::information_iterator; - using value_type = impl::information_iterator::value_type; - using pointer = impl::information_iterator::pointer; - using reference = impl::information_iterator::reference; + using iterator = iterator; + using value_type = iterator::value_type; + using pointer = iterator::pointer; + using reference = iterator::reference; [[nodiscard]] auto size_bytes() const noexcept -> std::size_t { @@ -224,7 +224,7 @@ namespace multiboot2 uint32_t m_size{}; uint32_t : 32; - impl::tag_header m_tags{}; + tag_header m_tags{}; }; } // namespace multiboot2 diff --git a/libs/multiboot2/include/multiboot2/information/data.hpp b/libs/multiboot2/include/multiboot2/information/data.hpp new file mode 100644 index 0000000..38280f8 --- /dev/null +++ b/libs/multiboot2/include/multiboot2/information/data.hpp @@ -0,0 +1,138 @@ +#ifndef MULTIBOOT2_INFORMATION_DATA_HPP +#define MULTIBOOT2_INFORMATION_DATA_HPP + +// IWYU pragma: private, include + +#include "multiboot2/constants/information_id.hpp" +#include "multiboot2/constants/memory_type.hpp" + +#include + +namespace multiboot2 +{ + //! A simple base mixin providing all data classes with an ID accessor. + template + struct tag_data + { + //! The ID of this data class. + constexpr auto static inline id = Id; + }; + + /** + * @brief Basic system memory information + */ + struct basic_memory_data : tag_data + { + /** + * @brief Amount of lower memory (below 1MiB) available to the system. + * + * The maximum possible value for this field is 640 KiB. + */ + std::uint32_t lower_KiB; + + /** + * @brief Amount of upper memory (above 1MiB) available to the system. + * + * The maximum possible value for this field is the address of the first upper memory hole minus 1MiB. + */ + std::uint32_t upper_KiB; + }; + + /** + * @brief Device the image got loaded from + */ + struct bios_boot_device_data : tag_data + { + /** + * @brief BIOS device number as understood by INT 13h. + */ + std::uint32_t device_number; + + /** + * @brief Number of the primary partition. + */ + std::uint32_t partition_number; + + /** + * @brief Number the sub-partition on the primary partition. + */ + std::uint32_t sub_partition_number; + }; + + /** + * @brief Supplied image command line + */ + struct command_line_data : tag_data + { + /* This struct intentionally left blank. */ + }; + + /** + * @brief ELF symbols of the image + */ + struct elf_symbols_data : tag_data + { + std::uint32_t count; + std::uint32_t entry_size; + std::uint32_t string_table_index; + }; + + /** + * @brief Name of the boot loader + */ + struct loader_name_data : tag_data + { + /* This struct intentionally left blank. */ + }; + + /** + * @brief Detailed map of the memory regions present in the system + * + */ + struct memory_map_data : tag_data + { + /** + * @brief A region of memory + */ + struct region + { + /** + * @brief Check if the memory described by this region is available for use. + */ + [[nodiscard]] constexpr auto available() const noexcept + { + return type == memory_type::AVAILABLE; + } + + /** + * @brief Start address of this region + */ + std::uint64_t base; + + /** + * @brief Size of this region in bytes. + */ + std::uint64_t size_in_B; + + /** + * @brief Type of this region. + */ + memory_type type; + + std::uint32_t : 0; + }; + + /** + * @brief Size of each entry present in the map + */ + std::uint32_t entry_size; + + /** + * @brief Version of each entry present in the map + */ + std::uint32_t entry_version; + }; + +} // namespace multiboot2 + +#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/information/iterator.hpp b/libs/multiboot2/include/multiboot2/information/iterator.hpp new file mode 100644 index 0000000..c771933 --- /dev/null +++ b/libs/multiboot2/include/multiboot2/information/iterator.hpp @@ -0,0 +1,73 @@ +#ifndef MULTIBOOT2_INFORMATION_ITERATOR_HPP +#define MULTIBOOT2_INFORMATION_ITERATOR_HPP + +// IWYU pragma: private, include + +#include "multiboot2/constants/information_id.hpp" +#include "tag.hpp" + +#include +#include +#include + +namespace multiboot2 +{ + + struct iterator + { + using iterator_category = std::forward_iterator_tag; + using value_type = tag_header; + using pointer = value_type const *; + using reference = value_type const &; + using difference_type = std::ptrdiff_t; + + constexpr iterator() = default; + + constexpr explicit iterator(tag_header const * offset) + : m_current(offset) + {} + + constexpr auto operator==(iterator const &) const noexcept -> bool = default; + + constexpr auto operator*() const noexcept -> reference + { + return *(m_current.value()); + } + + constexpr auto operator->() const noexcept -> pointer + { + return m_current.value(); + } + + constexpr auto operator++() noexcept -> iterator & + { + if (m_current) + { + if (auto next = m_current.value()->next(); next->information_id() != information_id::END) + { + m_current = next; + } + else + { + m_current.reset(); + } + } + return *this; + } + + constexpr auto operator++(int) noexcept -> iterator + { + auto copy = *this; + ++(*this); + return copy; + } + + private: + std::optional m_current{}; + }; + + static_assert(std::input_or_output_iterator); + +} // namespace multiboot2 + +#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/information/tag.hpp b/libs/multiboot2/include/multiboot2/information/tag.hpp new file mode 100644 index 0000000..cd1fc0e --- /dev/null +++ b/libs/multiboot2/include/multiboot2/information/tag.hpp @@ -0,0 +1,206 @@ +#ifndef MULTIBOOT2_INFORMATION_TAG_HPP +#define MULTIBOOT2_INFORMATION_TAG_HPP + +// IWYU pragma: private, include + +#include "multiboot2/constants/information_id.hpp" + +#include +#include +#include +#include + +namespace multiboot2 +{ + + /** + * @brief Header data and functionality shared by all tags. + */ + struct tag_header + { + tag_header() + : m_id{} + , m_size{} + {} + + tag_header(tag_header const * data) + : tag_header{*data} + {} + + [[nodiscard]] auto full_size() const noexcept -> std::size_t + { + return (m_size + 7) & (~7); + } + + [[nodiscard]] auto information_id() const noexcept -> information_id const & + { + return m_id; + } + + [[nodiscard]] auto next() const noexcept -> tag_header const * + { + return std::bit_cast(std::bit_cast(this) + full_size()); + } + + [[nodiscard]] auto unaligned_size() const noexcept -> std::uint32_t + { + return m_size; + } + + private: + enum information_id m_id; + std::uint32_t m_size; + }; + + /** + * @brief A tag containing no variable length array data. + */ + template + struct tag : tag_header, Data + { + tag() + : tag_header{} + , Data{} + {} + + explicit tag(tag_header const * header) + requires(sizeof(tag) > sizeof(tag_header)) + : tag_header{header} + , Data{*std::bit_cast(header + 1)} + {} + + explicit tag(tag_header const * header) + requires(sizeof(tag) == sizeof(tag_header)) + : tag_header{header} + , Data{} + {} + }; + + /** + * @brief A tag containing variable length array data. + */ + template typename Range> + struct vla_tag : tag + { + using range_type = Range; + + using value_type = range_type::value_type; + using reference = range_type::const_reference; + using const_reference = range_type::const_reference; + using pointer = range_type::const_pointer; + using const_pointer = range_type::const_pointer; + + using iterator = range_type::const_iterator; + using const_iterator = range_type::const_iterator; + using reverse_iterator = range_type::const_reverse_iterator; + using const_reverse_iterator = range_type::const_reverse_iterator; + using size_type = range_type::size_type; + using difference_type = range_type::difference_type; + + vla_tag() + : tag{} + , m_vla{} + {} + + explicit vla_tag(tag_header const * header) + : tag{header} + , m_vla{vla_start(header), vla_size(header)} + {} + + [[nodiscard]] auto begin() const noexcept -> const_iterator + { + return m_vla.begin(); + } + + [[nodiscard]] auto end() const noexcept -> const_iterator + { + return m_vla.end(); + } + + [[nodiscard]] auto cbegin() const noexcept -> const_iterator + { + return begin(); + } + + [[nodiscard]] auto cend() const noexcept -> const_iterator + { + return end(); + } + + [[nodiscard]] auto rbegin() const noexcept -> const_reverse_iterator + { + return m_vla.rbegin(); + } + + [[nodiscard]] auto rend() const noexcept -> const_reverse_iterator + { + return m_vla.rend(); + } + + [[nodiscard]] auto crbegin() const noexcept -> const_reverse_iterator + { + return rbegin(); + } + + [[nodiscard]] auto crend() const noexcept -> const_reverse_iterator + { + return rend(); + } + + [[nodiscard]] auto front() const noexcept -> const_reference + { + return m_vla.front(); + } + + [[nodiscard]] auto back() const noexcept -> const_reference + { + return m_vla.back(); + } + + [[nodiscard]] auto size() const noexcept -> std::size_t + { + return m_vla.size(); + } + + [[nodiscard]] auto empty() const noexcept -> bool + { + return m_vla.empty(); + } + + [[nodiscard]] auto data() const noexcept -> const_pointer + { + return m_vla.data(); + } + + [[nodiscard]] auto at() const -> const_reference + { + return m_vla.at(); + } + + [[nodiscard]] auto operator[](std::size_t index) const noexcept -> const_reference + { + return m_vla[index]; + } + + private: + auto static vla_start(tag_header const * header) noexcept -> VlaData * + { + auto raw = std::bit_cast(header); + auto start = raw + sizeof(tag); + return std::bit_cast(start); + } + + auto static vla_size(tag_header const * header) noexcept -> std::size_t + { + auto size = (header->unaligned_size() - sizeof(tag) - + std::is_same_v> * 1) / + sizeof(VlaData); + return size; + } + + range_type m_vla; + }; + +} // namespace multiboot2 + +#endif \ No newline at end of file -- cgit v1.2.3