aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/memory/multiboot
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/src/memory/multiboot')
-rw-r--r--arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp13
-rw-r--r--arch/x86_64/src/memory/multiboot/memory_map.cpp24
-rw-r--r--arch/x86_64/src/memory/multiboot/reader.cpp117
3 files changed, 154 insertions, 0 deletions
diff --git a/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp
new file mode 100644
index 0000000..78ab952
--- /dev/null
+++ b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp
@@ -0,0 +1,13 @@
+#include "arch/memory/multiboot/elf_sybols_section.hpp"
+
+namespace teachos::arch::memory::multiboot
+{
+ auto elf_section_flags::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; }
+
+ auto elf_section_header::is_null() const -> bool
+ {
+ return name_table_index == 0U && type == elf_section_type::INACTIVE && flags == elf_section_flags(0U) &&
+ virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U &&
+ fixed_table_entry_size == 0U;
+ }
+} // namespace teachos::arch::memory::multiboot
diff --git a/arch/x86_64/src/memory/multiboot/memory_map.cpp b/arch/x86_64/src/memory/multiboot/memory_map.cpp
new file mode 100644
index 0000000..6b1d1d4
--- /dev/null
+++ b/arch/x86_64/src/memory/multiboot/memory_map.cpp
@@ -0,0 +1,24 @@
+#include "arch/memory/multiboot/memory_map.hpp"
+
+namespace teachos::arch::memory::multiboot
+{
+ memory_area_iterator::memory_area_iterator(multiboot::memory_area * p)
+ : ptr(p)
+ {
+ // Nothing to do
+ }
+
+ multiboot::memory_area & memory_area_iterator::operator*() const { return *ptr; }
+
+ auto memory_area_iterator::operator++(int) -> memory_area_iterator
+ {
+ ++(*this);
+ return *this;
+ }
+
+ auto memory_area_iterator::operator++() -> memory_area_iterator &
+ {
+ ++ptr;
+ return *this;
+ }
+} // namespace teachos::arch::memory::multiboot
diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp
new file mode 100644
index 0000000..8741b44
--- /dev/null
+++ b/arch/x86_64/src/memory/multiboot/reader.cpp
@@ -0,0 +1,117 @@
+#include "arch/memory/multiboot/reader.hpp"
+
+#include "arch/boot/pointers.hpp"
+#include "arch/exception_handling/assert.hpp"
+#include "arch/memory/multiboot/info.hpp"
+
+namespace teachos::arch::memory::multiboot
+{
+ namespace
+ {
+ template<typename T>
+ requires std::is_pointer<T>::value
+ auto align_to_8_byte_boundary(T ptr, uint32_t size) -> T
+ {
+ return reinterpret_cast<T>(reinterpret_cast<uint8_t *>(ptr) + ((size + 7) & ~7));
+ }
+
+ auto process_memory_map(memory_map_header * mminfo, memory_area *& memory_areas, uint8_t & area_count) -> void
+ {
+ auto expected_entry_size = mminfo->entry_size;
+ constexpr auto actual_entry_size = sizeof(memory_area);
+ arch::exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected memory_area entry size");
+
+ auto total_size = mminfo->info.size;
+ auto total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size;
+ auto number_of_entries = total_entries_size / actual_entry_size;
+
+ memory_areas = &mminfo->entries;
+ area_count = number_of_entries;
+ }
+
+ auto process_elf_sections(elf_symbols_section_header * symbol, uint64_t & kernel_start,
+ uint64_t & kernel_end) -> void
+ {
+ auto expected_entry_size = symbol->entry_size;
+ constexpr auto actual_entry_size = sizeof(elf_section_header);
+ arch::exception_handling::assert(expected_entry_size == actual_entry_size,
+ "Unexpected elf_section_header entry size");
+
+ auto expected_total_size = symbol->info.size;
+ auto actual_total_entry_size = actual_entry_size * symbol->number_of_sections;
+ constexpr auto actual_total_section_size = sizeof(elf_symbols_section_header) - sizeof(uint32_t);
+ auto actual_total_size = actual_total_entry_size + actual_total_section_size;
+ arch::exception_handling::assert(expected_total_size == actual_total_size,
+ "Unexpected elf_symbols_section_header total size");
+
+ auto begin = reinterpret_cast<elf_section_header *>(&symbol->end);
+ auto end = begin + symbol->number_of_sections;
+ arch::exception_handling::assert(begin->is_null(), "Missing elf_section_header begin");
+
+ std::size_t symbol_table_section_count = 0U;
+ std::size_t dynamic_section_count = 0U;
+
+ for (auto section = begin; section != end; ++section)
+ {
+ switch (section->type)
+ {
+ case elf_section_type::PROGRAMM: {
+ if (section->virtual_address < kernel_start)
+ {
+ kernel_start = section->virtual_address;
+ }
+ auto virtual_address_end = section->virtual_address + section->section_size;
+ if (virtual_address_end > kernel_end)
+ {
+ kernel_end = virtual_address_end;
+ }
+ break;
+ }
+ case elf_section_type::DYNAMIC_SYMBOL_TABLE:
+ case elf_section_type::SYMBOL_TABLE:
+ symbol_table_section_count++;
+ break;
+ case elf_section_type::DYNAMIC:
+ dynamic_section_count++;
+ break;
+ default:
+ // All other cases are not important and can be ignored
+ break;
+ }
+ }
+
+ arch::exception_handling::assert(symbol_table_section_count == 1U, "Unexpected symbol_table_count value");
+ arch::exception_handling::assert(dynamic_section_count <= 1U, "Unexpected dynamic_section_count value");
+ }
+ } // namespace
+
+ auto read_multiboot2() -> memory_information
+ {
+ memory_information mem_info{UINT64_MAX, 0U, boot::multiboot_information_pointer, 0U, nullptr, 0U};
+
+ auto * multiboot_information_pointer = reinterpret_cast<info_header *>(boot::multiboot_information_pointer);
+ auto multiboot_tag = &(multiboot_information_pointer->tags);
+ mem_info.multiboot_end = mem_info.multiboot_start + multiboot_information_pointer->total_size;
+
+ for (auto tag = multiboot_tag; tag->type != tag_type::END; tag = align_to_8_byte_boundary(tag, tag->size))
+ {
+ switch (tag->type)
+ {
+ case tag_type::ELF_SECTIONS: {
+ auto symbol = reinterpret_cast<elf_symbols_section_header *>(tag);
+ process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end);
+ break;
+ }
+ case tag_type::MEMORY_MAP: {
+ auto mminfo = reinterpret_cast<memory_map_header *>(tag);
+ process_memory_map(mminfo, mem_info.memory_areas, mem_info.area_count);
+ break;
+ }
+ default:
+ // All other cases are not important and can be ignored
+ break;
+ }
+ }
+ return mem_info;
+ }
+} // namespace teachos::arch::memory::multiboot