aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/memory
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/src/memory')
-rw-r--r--arch/x86_64/src/memory/frame_allocator.cpp44
-rw-r--r--arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp (renamed from arch/x86_64/src/memory/multiboot.cpp)6
-rw-r--r--arch/x86_64/src/memory/multiboot/memory_map.cpp24
-rw-r--r--arch/x86_64/src/memory/multiboot/reader.cpp117
4 files changed, 155 insertions, 36 deletions
diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp
index 70276ae..7776082 100644
--- a/arch/x86_64/src/memory/frame_allocator.cpp
+++ b/arch/x86_64/src/memory/frame_allocator.cpp
@@ -17,37 +17,15 @@ namespace teachos::arch::memory
auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_FRAME_SIZE; }
- memory_area_iterator::memory_area_iterator(memory_area * p)
- : ptr(p)
- {
- // Nothing to do
- }
-
- 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;
- }
-
- area_frame_allocator::area_frame_allocator(std::size_t kernel_start, std::size_t kernel_end,
- std::size_t multiboot_start, std::size_t multiboot_end,
- memory_area * memory_areas, uint8_t area_count)
+ area_frame_allocator::area_frame_allocator(multiboot::memory_information mem_info)
: next_free_frame(0)
, current_area(std::nullopt)
- , area_begin(memory_areas)
- , area_end(memory_areas + area_count)
- , kernel_start(physical_frame::containing_address(kernel_start))
- , kernel_end(physical_frame::containing_address(kernel_end))
- , multiboot_start(physical_frame::containing_address(multiboot_start))
- , multiboot_end(physical_frame::containing_address(multiboot_end))
+ , area_begin(mem_info.memory_areas)
+ , area_end(mem_info.memory_areas + mem_info.area_count)
+ , kernel_start(physical_frame::containing_address(mem_info.kernel_start))
+ , kernel_end(physical_frame::containing_address(mem_info.kernel_end))
+ , multiboot_start(physical_frame::containing_address(mem_info.multiboot_start))
+ , multiboot_end(physical_frame::containing_address(mem_info.multiboot_end))
{
choose_next_area();
}
@@ -56,9 +34,9 @@ namespace teachos::arch::memory
{
current_area = std::nullopt;
- for (memory_area_iterator it = begin(); it != end(); ++it)
+ for (multiboot::memory_area_iterator it = begin(); it != end(); ++it)
{
- memory_area & area = *it;
+ multiboot::memory_area & area = *it;
std::size_t address = area.base_address + area.area_length - 1;
if (physical_frame::containing_address(address) >= next_free_frame)
@@ -126,7 +104,7 @@ namespace teachos::arch::memory
"[deallocate_frame] Not implemented Exception");
}
- auto area_frame_allocator::begin() -> memory_area_iterator { return area_begin; }
+ auto area_frame_allocator::begin() -> multiboot::memory_area_iterator { return area_begin; }
- auto area_frame_allocator::end() -> memory_area_iterator { return area_end; }
+ auto area_frame_allocator::end() -> multiboot::memory_area_iterator { return area_end; }
} // namespace teachos::arch::memory
diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp
index 8c6793e..78ab952 100644
--- a/arch/x86_64/src/memory/multiboot.cpp
+++ b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp
@@ -1,6 +1,6 @@
-#include "arch/memory/multiboot.hpp"
+#include "arch/memory/multiboot/elf_sybols_section.hpp"
-namespace teachos::arch::memory
+namespace teachos::arch::memory::multiboot
{
auto elf_section_flags::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; }
@@ -10,4 +10,4 @@ namespace teachos::arch::memory
virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U &&
fixed_table_entry_size == 0U;
}
-} // namespace teachos::arch::memory
+} // 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