aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-03-18 17:18:37 +0100
committerFelix Morgner <felix.morgner@ost.ch>2026-03-18 17:18:37 +0100
commite7ccb96aecae7b231fb05818d7e45a767aebc31d (patch)
tree68f7a623018d025b3fb6d10ce49d022242cc14f2
parent12c0586ee15cadfa178e6982dc0f76b047cb2df9 (diff)
downloadteachos-e7ccb96aecae7b231fb05818d7e45a767aebc31d.tar.xz
teachos-e7ccb96aecae7b231fb05818d7e45a767aebc31d.zip
kstd: introduce strong type for memory amounts
-rw-r--r--arch/x86_64/include/arch/memory/page_table.hpp3
-rw-r--r--arch/x86_64/kapi/memory.cpp17
-rw-r--r--arch/x86_64/src/memory/kernel_mapper.cpp9
-rw-r--r--kapi/include/kapi/memory/address.hpp11
-rw-r--r--kapi/include/kapi/memory/chunk.hpp8
-rw-r--r--kapi/include/kapi/memory/layout.hpp6
-rw-r--r--kernel/include/kernel/memory/block_list_allocator.hpp13
-rw-r--r--kernel/include/kernel/memory/heap_allocator.hpp5
-rw-r--r--kernel/kapi/memory.cpp10
-rw-r--r--kernel/src/memory.cpp5
-rw-r--r--kernel/src/memory/block_list_allocator.cpp28
-rw-r--r--kernel/src/memory/operators.cpp13
-rw-r--r--libs/kstd/include/kstd/units145
-rw-r--r--libs/multiboot2/CMakeLists.txt1
-rw-r--r--libs/multiboot2/include/multiboot2/information.hpp16
-rw-r--r--libs/multiboot2/include/multiboot2/information/data.hpp31
16 files changed, 266 insertions, 55 deletions
diff --git a/arch/x86_64/include/arch/memory/page_table.hpp b/arch/x86_64/include/arch/memory/page_table.hpp
index 2889d38..3cbb0af 100644
--- a/arch/x86_64/include/arch/memory/page_table.hpp
+++ b/arch/x86_64/include/arch/memory/page_table.hpp
@@ -4,6 +4,7 @@
#include "kapi/memory.hpp"
#include <kstd/ext/bitfield_enum>
+#include <kstd/units>
#include <array>
#include <cstddef>
@@ -116,7 +117,7 @@ namespace arch::memory
};
//! The maximum number of entries in this table.
- constexpr auto static entry_count{kapi::memory::page::size / sizeof(entry)};
+ constexpr auto static entry_count{kapi::memory::page::size / kstd::units::bytes{sizeof(entry)}};
//! Get the entry at the given index.
//!
diff --git a/arch/x86_64/kapi/memory.cpp b/arch/x86_64/kapi/memory.cpp
index 07e7465..5f12e5c 100644
--- a/arch/x86_64/kapi/memory.cpp
+++ b/arch/x86_64/kapi/memory.cpp
@@ -13,6 +13,7 @@
#include "arch/memory/region_allocator.hpp"
#include <kstd/print>
+#include <kstd/units>
#include <multiboot2/constants.hpp>
#include <multiboot2/information.hpp>
@@ -28,6 +29,8 @@
#include <span>
#include <utility>
+using namespace kstd::units_literals;
+
namespace kapi::memory
{
@@ -46,7 +49,7 @@ namespace kapi::memory
}
auto const & mbi = boot::bootstrap_information.mbi;
- auto mbi_span = std::span{std::bit_cast<std::byte *>(mbi), mbi->size_bytes()};
+ auto mbi_span = std::span{std::bit_cast<std::byte *>(mbi), static_cast<std::size_t>(mbi->size())};
auto image_span = std::span{&arch::boot::_start_physical, &arch::boot::_end_physical};
return arch::memory::region_allocator::memory_information{
@@ -107,10 +110,10 @@ namespace kapi::memory
[[maybe_unused]] auto remap_multiboot_information(page_mapper & mapper) -> void
{
auto mbi_base = std::bit_cast<std::uintptr_t>(boot::bootstrap_information.mbi);
- auto mbi_size = boot::bootstrap_information.mbi->size_bytes();
+ auto mbi_size = boot::bootstrap_information.mbi->size();
auto mbi_physical_start = physical_address{mbi_base & ~std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)};
auto mbi_virtual_start = linear_address{mbi_base};
- auto mbi_block_count = (mbi_size + frame::size - 1) / frame::size;
+ auto mbi_block_count = (mbi_size + frame::size - 1_B) / frame::size;
for (auto i = 0uz; i < mbi_block_count; ++i)
{
@@ -126,8 +129,8 @@ namespace kapi::memory
auto module_physical_start = physical_address{module.start_address};
auto module_virtual_start =
linear_address{module.start_address + std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)};
- auto module_size = module.end_address - module.start_address;
- auto module_block_count = (module_size + frame::size - 1) / frame::size;
+ auto module_size = static_cast<kstd::units::bytes>(module.end_address - module.start_address);
+ auto module_block_count = (module_size + frame::size - 1_B) / frame::size;
for (auto i = 0uz; i < module_block_count; ++i)
{
@@ -147,7 +150,7 @@ namespace kapi::memory
}))
{
auto start = frame::containing(physical_address{region.base});
- auto count = region.size_in_B / page::size;
+ auto count = kstd::units::bytes{region.size_in_B} / page::size;
new_allocator.release_many({start, count});
}
@@ -167,7 +170,7 @@ namespace kapi::memory
[&](auto frame) { new_allocator.mark_used(frame); });
auto mbi_base = std::bit_cast<std::uintptr_t>(boot::bootstrap_information.mbi);
- auto mbi_size = boot::bootstrap_information.mbi->size_bytes();
+ auto mbi_size = boot::bootstrap_information.mbi->size();
auto mbi_address = physical_address{mbi_base & ~std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)};
auto mbi_start = frame::containing(mbi_address);
auto mbi_end = frame::containing(mbi_address + mbi_size) + 1;
diff --git a/arch/x86_64/src/memory/kernel_mapper.cpp b/arch/x86_64/src/memory/kernel_mapper.cpp
index e5bb7f8..ced8a14 100644
--- a/arch/x86_64/src/memory/kernel_mapper.cpp
+++ b/arch/x86_64/src/memory/kernel_mapper.cpp
@@ -6,6 +6,7 @@
#include "arch/boot/ld.hpp"
#include <kstd/print>
+#include <kstd/units>
#include <elf/format.hpp>
#include <elf/section_header.hpp>
@@ -19,13 +20,14 @@
#include <string_view>
#include <utility>
+using namespace std::string_view_literals;
+using namespace kstd::units_literals;
+
namespace arch::memory
{
namespace
{
- using namespace std::string_view_literals;
-
constexpr auto static ignored_section_prefixes = std::array{
".boot_"sv,
};
@@ -71,7 +73,8 @@ namespace arch::memory
auto kernel_mapper::map_section(section_header_type const & section, std::string_view name,
kapi::memory::page_mapper & mapper) -> void
{
- auto number_of_pages = (section.size + (kapi::memory::page::size - 1)) / kapi::memory::page::size;
+ auto number_of_pages =
+ (kstd::units::bytes{section.size} + (kapi::memory::page::size - 1_B)) / kapi::memory::page::size;
auto linear_start_address = kapi::memory::linear_address{section.virtual_load_address};
auto physical_start_address = kapi::memory::physical_address{section.virtual_load_address & ~m_kernel_load_base};
diff --git a/kapi/include/kapi/memory/address.hpp b/kapi/include/kapi/memory/address.hpp
index 69fc7b9..587aeac 100644
--- a/kapi/include/kapi/memory/address.hpp
+++ b/kapi/include/kapi/memory/address.hpp
@@ -4,6 +4,7 @@
// IWYU pragma: private, include "kapi/memory.hpp"
#include <kstd/format>
+#include <kstd/units>
#include <bit>
#include <compare>
@@ -183,6 +184,16 @@ namespace kapi::memory
return static_cast<MaskType>(m_value & mask);
}
+ constexpr auto operator+(kstd::units::bytes n) const noexcept -> address
+ {
+ return address{m_value + n.value};
+ }
+
+ constexpr auto operator+=(kstd::units::bytes n) noexcept -> address &
+ {
+ return *this = *this + n;
+ }
+
//! Check if this address is equal to another one.
constexpr auto operator==(address const &) const noexcept -> bool = default;
diff --git a/kapi/include/kapi/memory/chunk.hpp b/kapi/include/kapi/memory/chunk.hpp
index 4529535..a046221 100644
--- a/kapi/include/kapi/memory/chunk.hpp
+++ b/kapi/include/kapi/memory/chunk.hpp
@@ -3,6 +3,8 @@
// IWYU pragma: private, include "kapi/memory.hpp"
+#include <kstd/units>
+
#include <compare>
#include <cstddef>
@@ -15,7 +17,7 @@ namespace kapi::memory
//! @tparam ChunkType The CRTP type of the deriving class
//! @tparam AddressType The type of addresses used to index this chunk
//! @tparam Size The size of this chunk.
- template<typename ChunkType, typename AddressType, std::size_t Size>
+ template<typename ChunkType, typename AddressType, kstd::units::bytes Size>
struct chunk
{
//! The type of addresses used to index this chunk
@@ -30,7 +32,7 @@ namespace kapi::memory
//! @return A handle to a chunk containing the given address.
constexpr auto static containing(address_type address) noexcept -> ChunkType
{
- return ChunkType{address / size};
+ return ChunkType{address / size.value};
}
//! Get the start address of the chunk referenced by this handle.
@@ -38,7 +40,7 @@ namespace kapi::memory
//! @return The address of the first byte contained by the chunk referenced by this handle.
[[nodiscard]] constexpr auto start_address() const noexcept -> address_type
{
- return address_type{m_number * size};
+ return address_type{(m_number * size).value};
}
//! Get the number of the chunk referenced by this handle.
diff --git a/kapi/include/kapi/memory/layout.hpp b/kapi/include/kapi/memory/layout.hpp
index d4153d8..157f41e 100644
--- a/kapi/include/kapi/memory/layout.hpp
+++ b/kapi/include/kapi/memory/layout.hpp
@@ -5,18 +5,20 @@
#include "kapi/memory/address.hpp"
+#include <kstd/units>
+
namespace kapi::memory
{
//! The size of a single page of virtual memory.
//!
//! Platforms that use different sizes of pages are expected to emulate 4 KiB pages towards the kernel.
- constexpr auto page_size = 4096uz;
+ constexpr auto page_size = kstd::units::KiB(4);
//! The size of a single frame of physical memory.
//!
//! Platforms that use different sizes of frames are expected to emulate 4 KiB pages towards the kernel.
- constexpr auto frame_size = 4096uz;
+ constexpr auto frame_size = kstd::units::KiB(4);
//! The linear base address of the higher-half direct map.
//!
diff --git a/kernel/include/kernel/memory/block_list_allocator.hpp b/kernel/include/kernel/memory/block_list_allocator.hpp
index 5e81c44..f319097 100644
--- a/kernel/include/kernel/memory/block_list_allocator.hpp
+++ b/kernel/include/kernel/memory/block_list_allocator.hpp
@@ -6,6 +6,7 @@
#include "kernel/memory/heap_allocator.hpp"
#include <kstd/mutex>
+#include <kstd/units>
#include <cstddef>
#include <new>
@@ -32,7 +33,7 @@ namespace kernel::memory
//! @param size The size of the block to allocate
//! @param alignment The desired alignment of the allocated block
//! @return A pointer to the beginning of the block on success, @p nullptr otherwise.
- [[nodiscard]] auto allocate(std::size_t size, std::align_val_t alignment) noexcept -> void * override;
+ [[nodiscard]] auto allocate(kstd::units::bytes size, kstd::units::bytes alignment) noexcept -> void * override;
//! Deallocate a block of memory previously allocated.
//!
@@ -42,7 +43,7 @@ namespace kernel::memory
private:
struct block_header final
{
- std::size_t usable_size;
+ kstd::units::bytes usable_size;
bool free;
block_header * next;
block_header * prev;
@@ -52,16 +53,16 @@ namespace kernel::memory
//!
//! Each allocated block carries a block header, like any unallocated one, but in addition also has a back-pointer
//! to the block header to support padding due to alignment.
- constexpr auto static allocated_metadata_size = sizeof(block_header) + sizeof(block_header *);
+ constexpr auto static allocated_metadata_size = kstd::units::bytes{sizeof(block_header) + sizeof(block_header *)};
//! The minimum number of bytes for an allocation.
- constexpr auto static minimum_allocation_size = 16uz;
+ constexpr auto static minimum_allocation_size = kstd::units::bytes{16uz};
//! Try to expand the heap to accommodate the given size.
//!
//! @param delta The size to expand the heap by.
//! @return @p true if the heap was expanded, @p false otherwise.
- auto expand(std::size_t delta) noexcept -> bool;
+ auto expand(kstd::units::bytes delta) noexcept -> bool;
//! Split a given free block to accommodate and allocation.
//!
@@ -70,7 +71,7 @@ namespace kernel::memory
//! @param block The block to split.
//! @param size The size of the allocation.
//! @param padding The amount of padding to apply.
- auto split(block_header * block, std::size_t size, std::size_t padding) noexcept -> void;
+ auto split(block_header * block, kstd::units::bytes size, kstd::units::bytes padding) noexcept -> void;
//! Try to coalesce a given block with it's preceding and/or following block.
//!
diff --git a/kernel/include/kernel/memory/heap_allocator.hpp b/kernel/include/kernel/memory/heap_allocator.hpp
index bc771e3..55de7e4 100644
--- a/kernel/include/kernel/memory/heap_allocator.hpp
+++ b/kernel/include/kernel/memory/heap_allocator.hpp
@@ -1,9 +1,8 @@
#ifndef TEACHOS_KERNEL_MEMORY_HEAP_ALLOCATOR_HPP
#define TEACHOS_KERNEL_MEMORY_HEAP_ALLOCATOR_HPP
-#include <kstd/mutex>
+#include <kstd/units>
-#include <cstddef>
#include <new>
namespace kernel::memory
@@ -19,7 +18,7 @@ namespace kernel::memory
//! @param size The size of the block to allocate
//! @param alignment The desired alignment of the allocated block
//! @return A pointer to the beginning of the block on success, @p nullptr otherwise.
- [[nodiscard]] virtual auto allocate(std::size_t size, std::align_val_t alignment) noexcept -> void * = 0;
+ [[nodiscard]] virtual auto allocate(kstd::units::bytes size, kstd::units::bytes alignment) noexcept -> void * = 0;
//! Deallocate a block of memory previously allocated.
//!
diff --git a/kernel/kapi/memory.cpp b/kernel/kapi/memory.cpp
index d8065d4..2803d76 100644
--- a/kernel/kapi/memory.cpp
+++ b/kernel/kapi/memory.cpp
@@ -5,6 +5,7 @@
#include "kernel/memory/bitmap_allocator.hpp"
#include <kstd/print>
+#include <kstd/units>
#include <algorithm>
#include <cstddef>
@@ -112,8 +113,10 @@ namespace kapi::memory
auto init_pmm(std::size_t frame_count, void (&handoff_handler)(frame_allocator &)) -> void
{
- auto const bitmap_bytes = (frame_count + 7uz) / 8uz;
- auto const bitmap_pages = (bitmap_bytes + page::size - 1uz) / page::size;
+ using namespace kstd::units_literals;
+
+ auto const bitmap_bytes = kstd::units::bytes{(frame_count + 7uz) / 8uz};
+ auto const bitmap_pages = (bitmap_bytes + page::size - 1_B) / page::size;
auto const bitmap_frames = allocate_many_frames(bitmap_pages);
if (!bitmap_frames)
@@ -130,7 +133,8 @@ namespace kapi::memory
});
auto bitmap_ptr = static_cast<std::uint64_t *>(pmm_metadata_base);
- auto bitmap = std::span{bitmap_ptr, (bitmap_bytes + sizeof(std::uint64_t) - 1uz) / sizeof(std::uint64_t)};
+ auto bitmap =
+ std::span{bitmap_ptr, (bitmap_bytes + kstd::type_size<std::uint64_t> - 1_B) / kstd::type_size<std::uint64_t>};
allocator.emplace(bitmap, frame_count);
diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp
index 0f614f0..4a8e203 100644
--- a/kernel/src/memory.cpp
+++ b/kernel/src/memory.cpp
@@ -7,10 +7,9 @@
#include "kernel/memory/heap_allocator.hpp"
#include <kstd/print>
+#include <kstd/units>
#include <atomic>
-#include <cstddef>
-#include <new>
#include <optional>
namespace kernel::memory
@@ -22,7 +21,7 @@ namespace kernel::memory
{
null_allocator static instance;
- [[nodiscard]] auto allocate(std::size_t, std::align_val_t) noexcept -> void * override
+ [[nodiscard]] auto allocate(kstd::units::bytes, kstd::units::bytes) noexcept -> void * override
{
kstd::print(kstd::print_sink::stderr, "Tried to allocate memory without an active heap!");
return nullptr;
diff --git a/kernel/src/memory/block_list_allocator.cpp b/kernel/src/memory/block_list_allocator.cpp
index 5d870d8..fbc5945 100644
--- a/kernel/src/memory/block_list_allocator.cpp
+++ b/kernel/src/memory/block_list_allocator.cpp
@@ -6,19 +6,21 @@
#include "kernel/memory/heap_allocator.hpp"
#include <kstd/mutex>
+#include <kstd/units>
#include <bit>
#include <cstddef>
#include <cstdint>
#include <memory>
-#include <new>
+
+using namespace kstd::units_literals;
namespace kernel::memory
{
namespace
{
- [[nodiscard]] constexpr auto align_up(std::byte * pointer, std::align_val_t alignment) noexcept -> std::byte *
+ [[nodiscard]] constexpr auto align_up(std::byte * pointer, kstd::units::bytes alignment) noexcept -> std::byte *
{
auto const remainder = std::bit_cast<std::uintptr_t>(pointer) % static_cast<std::size_t>(alignment);
return remainder == 0 ? pointer : pointer + static_cast<std::size_t>(alignment) - remainder;
@@ -33,7 +35,7 @@ namespace kernel::memory
, m_lock{}
{}
- auto block_list_allocator::allocate(std::size_t size, std::align_val_t alignment) noexcept -> void *
+ auto block_list_allocator::allocate(kstd::units::bytes size, kstd::units::bytes alignment) noexcept -> void *
{
kstd::lock_guard guard{m_lock};
@@ -47,13 +49,13 @@ namespace kernel::memory
auto const raw_block = reinterpret_cast<std::byte *>(current);
auto const unaligned_payload = raw_block + allocated_metadata_size;
auto const aligned_payload = align_up(unaligned_payload, alignment);
- auto const required_padding = static_cast<std::size_t>(aligned_payload - unaligned_payload);
+ auto const required_padding = static_cast<kstd::units::bytes>(aligned_payload - unaligned_payload);
auto const total_required_size = required_padding + allocated_metadata_size + size;
if (current->usable_size >= total_required_size)
{
auto const payload_header = aligned_payload - sizeof(block_header *) - sizeof(block_header);
- auto const front_padding = static_cast<std::size_t>(payload_header - raw_block);
+ auto const front_padding = static_cast<kstd::units::bytes>(payload_header - raw_block);
auto payload_block = current;
@@ -72,9 +74,10 @@ namespace kernel::memory
payload_block->prev = current;
}
- auto const payload_size =
- aligned_payload - reinterpret_cast<std::byte *>(payload_block) - allocated_metadata_size + size;
- split(payload_block, payload_size, 0uz);
+ auto const header_size =
+ static_cast<kstd::units::bytes>(aligned_payload - reinterpret_cast<std::byte *>(payload_block));
+ auto const payload_size = header_size - allocated_metadata_size + size;
+ split(payload_block, payload_size, 0_B);
payload_block->free = false;
@@ -87,7 +90,7 @@ namespace kernel::memory
current = current->next;
}
- auto const search_size = size + static_cast<std::size_t>(alignment);
+ auto const search_size = size + alignment;
if (attempt == 0uz && !expand(search_size))
{
return nullptr;
@@ -114,10 +117,10 @@ namespace kernel::memory
coalesce(block);
}
- auto block_list_allocator::expand(std::size_t size) noexcept -> bool
+ auto block_list_allocator::expand(kstd::units::bytes size) noexcept -> bool
{
auto const total_required_size = size + allocated_metadata_size;
- auto const frames_needed = (total_required_size + kapi::memory::frame::size - 1) / kapi::memory::frame::size;
+ auto const frames_needed = (total_required_size + kapi::memory::frame::size - 1_B) / kapi::memory::frame::size;
auto const flags = kapi::memory::page_mapper::flags::writable | kapi::memory::page_mapper::flags::supervisor_only |
kapi::memory::page_mapper::flags::global;
@@ -187,7 +190,8 @@ namespace kernel::memory
}
}
- auto block_list_allocator::split(block_header * block, std::size_t size, std::size_t padding) noexcept -> void
+ auto block_list_allocator::split(block_header * block, kstd::units::bytes size, kstd::units::bytes padding) noexcept
+ -> void
{
auto const new_block_size = size + padding;
diff --git a/kernel/src/memory/operators.cpp b/kernel/src/memory/operators.cpp
index 57e31e6..c786b53 100644
--- a/kernel/src/memory/operators.cpp
+++ b/kernel/src/memory/operators.cpp
@@ -2,13 +2,16 @@
#include "kernel/memory.hpp"
+#include <kstd/units>
+
#include <cstddef>
#include <new>
[[nodiscard]] auto operator new(std::size_t size, std::align_val_t alignment, std::nothrow_t const &) noexcept -> void *
{
auto & allocator = kernel::memory::get_heap_allocator();
- return allocator.allocate(size, alignment);
+ return allocator.allocate(static_cast<kstd::units::bytes>(size),
+ static_cast<kstd::units::bytes>(static_cast<std::size_t>(alignment)));
}
[[nodiscard]] auto operator new(std::size_t size, std::align_val_t alignment) -> void *
@@ -83,9 +86,9 @@ auto operator delete[](void * pointer) noexcept -> void
::operator delete(pointer);
}
-auto operator delete[](void * pointer, std::size_t) noexcept -> void
+auto operator delete[](void * pointer, std::size_t size) noexcept -> void
{
- ::operator delete(pointer);
+ ::operator delete(pointer, size);
}
auto operator delete[](void * pointer, std::align_val_t) noexcept -> void
@@ -93,7 +96,7 @@ auto operator delete[](void * pointer, std::align_val_t) noexcept -> void
::operator delete(pointer);
}
-auto operator delete[](void * pointer, std::size_t, std::align_val_t) noexcept -> void
+auto operator delete[](void * pointer, std::size_t size, std::align_val_t) noexcept -> void
{
- ::operator delete(pointer);
+ ::operator delete(pointer, size);
}
diff --git a/libs/kstd/include/kstd/units b/libs/kstd/include/kstd/units
new file mode 100644
index 0000000..f6dcdb1
--- /dev/null
+++ b/libs/kstd/include/kstd/units
@@ -0,0 +1,145 @@
+#ifndef KSTD_UNITS_HPP
+#define KSTD_UNITS_HPP
+
+#include <compare>
+#include <concepts>
+#include <cstddef>
+
+namespace kstd
+{
+
+ //! A basic template for strongly typed units.
+ template<typename ValueType, typename Tag>
+ struct basic_unit
+ {
+ using value_type = ValueType;
+
+ explicit constexpr basic_unit(value_type value) noexcept
+ : value{value}
+ {}
+
+ explicit constexpr operator value_type() const noexcept
+ {
+ return value;
+ }
+
+ constexpr auto operator+(basic_unit const & other) const noexcept -> basic_unit
+ {
+ return basic_unit{value + other.value};
+ }
+
+ constexpr auto operator+=(basic_unit const & other) noexcept -> basic_unit &
+ {
+ return *this = *this + other;
+ }
+
+ constexpr auto operator-(basic_unit const & other) const noexcept -> basic_unit
+ {
+ return basic_unit{value - other.value};
+ }
+
+ constexpr auto operator-=(basic_unit const & other) noexcept -> basic_unit &
+ {
+ return *this = *this - other;
+ }
+
+ constexpr auto operator*(std::integral auto factor) noexcept -> basic_unit
+ {
+ return basic_unit{value * factor};
+ }
+
+ constexpr auto operator*=(std::integral auto factor) noexcept -> basic_unit
+ {
+ return *this = *this * factor;
+ }
+
+ constexpr auto operator/(std::integral auto divisor) noexcept -> basic_unit
+ {
+ return basic_unit{value / divisor};
+ }
+
+ constexpr auto operator/=(std::integral auto divisor) noexcept -> basic_unit
+ {
+ return *this = *this / divisor;
+ }
+
+ constexpr auto operator/(basic_unit const & other) const noexcept
+ {
+ return value / other.value;
+ }
+
+ constexpr auto operator<=>(basic_unit const & other) const noexcept -> std::strong_ordering = default;
+
+ value_type value;
+ };
+
+ template<std::integral Factor, typename ValueType, typename Tag>
+ constexpr auto operator*(Factor factor, basic_unit<ValueType, Tag> const & unit) noexcept
+ -> basic_unit<ValueType, Tag>
+ {
+ return basic_unit<ValueType, Tag>{unit.value * factor};
+ }
+
+ namespace units
+ {
+ using bytes = basic_unit<std::size_t, struct bytes_tag>;
+
+ constexpr auto KiB(std::size_t value) noexcept -> bytes
+ {
+ return bytes{value * 1024};
+ }
+
+ constexpr auto MiB(std::size_t value) noexcept -> bytes
+ {
+ return bytes{value * 1024 * 1024};
+ }
+
+ constexpr auto GiB(std::size_t value) noexcept -> bytes
+ {
+ return bytes{value * 1024 * 1024 * 1024};
+ }
+
+ template<typename ValueType>
+ constexpr auto operator+(ValueType * pointer, bytes offset) -> ValueType *
+ {
+ return pointer + offset.value;
+ }
+
+ } // namespace units
+
+ namespace units_literals
+ {
+ constexpr auto operator""_B(unsigned long long value) noexcept -> units::bytes
+ {
+ return units::bytes{value};
+ }
+
+ constexpr auto operator""_KiB(unsigned long long value) noexcept -> units::bytes
+ {
+ return units::KiB(value);
+ }
+
+ constexpr auto operator""_MiB(unsigned long long value) noexcept -> units::bytes
+ {
+ return units::MiB(value);
+ }
+
+ constexpr auto operator""_GiB(unsigned long long value) noexcept -> units::bytes
+ {
+ return units::GiB(value);
+ }
+
+ } // namespace units_literals
+
+ template<typename ValueType>
+ constexpr auto object_size(ValueType const &) -> units::bytes
+ {
+ return units::bytes{sizeof(ValueType)};
+ }
+
+ template<typename T>
+ constexpr auto type_size = units::bytes{sizeof(T)};
+
+} // namespace kstd
+
+#endif \ No newline at end of file
diff --git a/libs/multiboot2/CMakeLists.txt b/libs/multiboot2/CMakeLists.txt
index 350a996..b306b66 100644
--- a/libs/multiboot2/CMakeLists.txt
+++ b/libs/multiboot2/CMakeLists.txt
@@ -20,6 +20,7 @@ target_include_directories("multiboot2" INTERFACE
target_link_libraries("multiboot2" INTERFACE
"libs::elf"
+ "libs::kstd"
)
set_target_properties("multiboot2" PROPERTIES
diff --git a/libs/multiboot2/include/multiboot2/information.hpp b/libs/multiboot2/include/multiboot2/information.hpp
index fbd534c..d2fac2e 100644
--- a/libs/multiboot2/include/multiboot2/information.hpp
+++ b/libs/multiboot2/include/multiboot2/information.hpp
@@ -5,11 +5,12 @@
#include "information/iterator.hpp" // IWYU pragma: export
#include "information/tag.hpp" // IWYU pragma: export
+#include <kstd/units>
+
#include <elf/format.hpp>
#include <elf/section_header.hpp>
#include <algorithm>
-#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <optional>
@@ -119,7 +120,12 @@ namespace multiboot2
*/
[[nodiscard]] auto string() const noexcept -> std::string_view
{
- return {data(), size()};
+ return {data(), vla_tag::size()};
+ }
+
+ [[nodiscard]] constexpr auto size() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{end_address - start_address};
}
};
@@ -130,9 +136,9 @@ namespace multiboot2
using pointer = iterator::pointer;
using reference = iterator::reference;
- [[nodiscard]] auto size_bytes() const noexcept -> std::size_t
+ [[nodiscard]] auto size() const noexcept -> kstd::units::bytes
{
- return m_size;
+ return kstd::units::bytes{m_size};
}
// Range access
@@ -190,7 +196,7 @@ namespace multiboot2
{
return get<multiboot2::elf_symbols<Format>>().and_then(
[](auto x) -> std::optional<multiboot2::elf_symbols<Format>> {
- if (x.entry_size == elf::section_header_size<Format>)
+ if (x.entry_size_in_B == elf::section_header_size<Format>)
{
return std::optional{x};
}
diff --git a/libs/multiboot2/include/multiboot2/information/data.hpp b/libs/multiboot2/include/multiboot2/information/data.hpp
index 9fa6d5b..3b07d20 100644
--- a/libs/multiboot2/include/multiboot2/information/data.hpp
+++ b/libs/multiboot2/include/multiboot2/information/data.hpp
@@ -6,6 +6,8 @@
#include "multiboot2/constants/information_id.hpp"
#include "multiboot2/constants/memory_type.hpp"
+#include <kstd/units>
+
#include <cstdint>
namespace multiboot2
@@ -27,6 +29,16 @@ namespace multiboot2
//! loader.
struct basic_memory : tag_data<information_id::basic_memory_information>
{
+ [[nodiscard]] constexpr auto lower() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{lower_KiB * 1024};
+ }
+
+ [[nodiscard]] constexpr auto upper() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{upper_KiB * 1024};
+ }
+
//! The amount of lower memory available to the system.
//!
//! Any memory below the 1 MiB address boundary is considered to be lower memory. The maximum possible value for
@@ -72,11 +84,16 @@ namespace multiboot2
//! time. The array begins after the last member of this structure.
struct elf_symbols : tag_data<information_id::elf_sections>
{
+ [[nodiscard]] constexpr auto entry_size() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{entry_size_in_B};
+ }
+
//! The number of section header table entries.
std::uint32_t count;
//! The size of each section header table entry.
- std::uint32_t entry_size;
+ std::uint32_t entry_size_in_B;
//! The section number of the string table containing the section names.
std::uint32_t string_table_index;
@@ -102,6 +119,11 @@ namespace multiboot2
return type == memory_type::available;
}
+ [[nodiscard]] constexpr auto size() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{size_in_B};
+ }
+
//! The physical start address of this region
std::uint64_t base;
@@ -117,11 +139,16 @@ namespace multiboot2
std::uint32_t : 0;
};
+ [[nodiscard]] constexpr auto entry_size() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{entry_size_in_B};
+ }
+
//! The size of each entry present in the map.
//!
//! This field is present to allow for future extension of the entry format. Each entry's size is guaranteed to
//! always be an integer multiple of 8.
- std::uint32_t entry_size;
+ std::uint32_t entry_size_in_B;
//! The version of each entry present in the map
std::uint32_t entry_version;