aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/CMakeLists.txt4
-rw-r--r--arch/x86_64/include/arch/memory/frame_allocator.hpp84
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp (renamed from arch/x86_64/include/arch/memory/multiboot.hpp)121
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/info.hpp62
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/memory_map.hpp93
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/reader.hpp50
-rw-r--r--arch/x86_64/include/arch/memory/paging.hpp5
-rw-r--r--arch/x86_64/src/kernel/main.cpp151
-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
12 files changed, 396 insertions, 365 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index 3f67d71..7ddf303 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -41,7 +41,9 @@ target_sources("_video" PRIVATE
#]============================================================================]
target_sources("_memory" PRIVATE
- "src/memory/multiboot.cpp"
+ "src/memory/multiboot/elf_symbols_section.cpp"
+ "src/memory/multiboot/memory_map.cpp"
+ "src/memory/multiboot/reader.cpp"
"src/memory/frame_allocator.cpp"
"src/memory/paging.cpp"
)
diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp
index 89f2570..f1096d1 100644
--- a/arch/x86_64/include/arch/memory/frame_allocator.hpp
+++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp
@@ -1,7 +1,8 @@
#ifndef TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP
#define TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP
-#include "multiboot.hpp"
+#include "multiboot/reader.hpp"
+
#include <cstddef>
#include <optional>
#include <type_traits>
@@ -17,7 +18,7 @@ namespace teachos::arch::memory
struct physical_frame
{
/**
- * @brief Constructor
+ * @brief Constructor.
*
* @param frame_number Index number that should be assigned to this physical_frame.
*/
@@ -32,9 +33,9 @@ namespace teachos::arch::memory
static auto containing_address(std::size_t address) -> physical_frame;
/**
- * @brief Evaluates the start address of the physical frame
+ * @brief Evaluates the start address of the physical frame.
*
- * @return start address of the physical frame
+ * @return start address of the physical frame.
*/
auto start_address() const -> uint64_t;
@@ -59,51 +60,6 @@ namespace teachos::arch::memory
};
/**
- * @brief Iterator for memory areas.
- */
- struct memory_area_iterator
- {
- /**
- * @brief Constructor.
- *
- * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer.
- */
- explicit memory_area_iterator(memory_area * p);
-
- /**
- * @brief Dereferences the initally given pointer to its value.
- *
- * @return Reference to the value.
- */
- memory_area & operator*() const;
-
- /**
- * @brief Post increment operator. Returns a copy of the value
- *
- * @return Copy of the incremented underlying address.
- */
- memory_area_iterator operator++(int);
-
- /**
- * @brief Pre increment operator. Returns a reference to the changed value.
- *
- * @return Reference to the incremented underlying address.
- */
- memory_area_iterator & operator++();
-
- /**
- * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators.
- *
- * @param other Other iterator to compare to.
- * @return Whether poith iterators point to the same underlying address in memory.
- */
- bool operator==(memory_area_iterator const & other) const = default;
-
- private:
- memory_area * ptr; ///< Underlying address the iterator is currently pointing too.
- };
-
- /**
* @brief Allocates memory using memory areas read from the multiboot2 information pointer.
*/
struct area_frame_allocator
@@ -111,15 +67,9 @@ namespace teachos::arch::memory
/**
* @brief Constructor
*
- * @param kernel_start Start address of the kernel code in memory.
- * @param kernel_end End address of the kernel code in memory.
- * @param multiboot_start Start address of the multiboot code in memory.
- * @param multiboot_end End address of the multiboot code in memory.
- * @param memory_areas Pointer to the first element of all memory areas.
- * @param area_count Amount of total entries in the memory_areas array.
+ * @param mem_info Structure containg all relevant information to map and allocate memory
*/
- 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(multiboot::memory_information mem_info);
/**
* @brief Allocate memory by finding and returning a free physical_frame.
@@ -146,7 +96,7 @@ namespace teachos::arch::memory
*
* @return Iterator pointing to first element of the memory area.
*/
- auto begin() -> memory_area_iterator;
+ auto begin() -> multiboot::memory_area_iterator;
/**
* @brief Returns the iterator pointing to one past the last element of the memory area.
@@ -154,7 +104,7 @@ namespace teachos::arch::memory
*
* @return Iterator pointing to one past the last element of the memory area.
*/
- auto end() -> memory_area_iterator;
+ auto end() -> multiboot::memory_area_iterator;
private:
/**
@@ -162,14 +112,14 @@ namespace teachos::arch::memory
*/
auto choose_next_area() -> void;
- physical_frame next_free_frame; ///< The physical_frame after the last allocated one.
- std::optional<memory_area> current_area; ///< The current memory area.
- memory_area_iterator area_begin; ///< Pointer to the first element of all memory areas.
- memory_area_iterator area_end; ///< Pointer to one pas the last element of all memory areas.
- physical_frame const kernel_start; ///< The start address of the kernel code in memory.
- physical_frame const kernel_end; ///< The end address of the kernel code in memory.
- physical_frame const multiboot_start; ///< The start address of the multiboot code in memory.
- physical_frame const multiboot_end; ///< The end address of the multiboot code in memory.
+ physical_frame next_free_frame; ///< The physical_frame after the last allocated one.
+ std::optional<multiboot::memory_area> current_area; ///< The current memory area.
+ multiboot::memory_area_iterator area_begin; ///< Pointer to the first element of all memory areas.
+ multiboot::memory_area_iterator area_end; ///< Pointer to one pas the last element of all memory areas.
+ physical_frame const kernel_start; ///< The start address of the kernel code in memory.
+ physical_frame const kernel_end; ///< The end address of the kernel code in memory.
+ physical_frame const multiboot_start; ///< The start address of the multiboot code in memory.
+ physical_frame const multiboot_end; ///< The end address of the multiboot code in memory.
};
} // namespace teachos::arch::memory
diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp
index 8ecb1b5..88d211e 100644
--- a/arch/x86_64/include/arch/memory/multiboot.hpp
+++ b/arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp
@@ -1,118 +1,13 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP
+#include "info.hpp"
#include <bitset>
#include <cstdint>
-namespace teachos::arch::memory
+namespace teachos::arch::memory::multiboot
{
/**
- * @brief Defines all possible types a multiboot2 tag structure can have.
- * See
- * https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Boot-information-format for more information.
- */
- enum class multi_boot_tag_type : 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 Sytem 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, ///< Indicated ExitBootServies wasn't called
- EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer
- EFI64_IMAGE_HANDLE, ///< EFI 64 bit imae handle pointer
- LOAD_BASE_ADDRESS ///< Contains image load base physical address
- };
-
- /**
- * @brief Basic structure that every entry in the multi_boot_tag array of the multi_boot_info struct has to begin
- * with.
- */
- struct multi_boot_tag
- {
- multi_boot_tag_type type; ///< Specific type of this multi_boot_tag entry, used to differentiate handling
- uint32_t size; ///< Total size of this multi_boot_tag entry with all fields of the actual type
- };
-
- /**
- * @brief Basic structure the multiboot_information_pointer points too and which contains all information of
- * multiboot2 in the tags array of different types. The start as well as the content has to be 8 byte aligned.
- */
- struct multi_boot_info
- {
- uint32_t total_size; ///< Total size of all multi_boot_tags and their data
- alignas(8) struct multi_boot_tag tags; ///< Specific tags
- };
-
- /**
- * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type
- * multi_boot_tag_type::BASIC_MEMORY_INFO.
- */
- struct memory_info
- {
- multi_boot_tag tag; ///< Basic multi_boot_tag information
- uint32_t mem_lower; ///< Amount of lower memory (0MB start address)
- uint32_t mem_upper; ///< Amount of upper memory (1MB start address)
- };
-
- /**
- * @brief Defines all memory area types possible that the memory region can be in.
- */
- enum class memory_area_type : uint32_t
- {
- AVAILABLE = 1, ///< Region is available for use by the OS
- RESERVED, ///< Region is reserved by firmware or bootloader and should not be used by OS
- ACPI_AVAILABLE, ///< Region is reclaimable by OS after ACPI event
- RESERVED_HIBERNATION, ///< Region is used for Non-volatile Storage (NVS)
- DEFECTIVE ///< Region is defective or unusable
- };
-
- /**
- * @brief Defines an entry in the entries array of the memory_map struct. Has to have all padding stripped between the
- * individual values, because the size of the entry needs to be exactly 24 bytes and not one byte more. See
- * https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Packed-Structures.html for more information on the
- * used attribute.
- */
- struct __attribute__((packed)) memory_area
- {
- uint32_t size; ///< TODO: Not clear what exactly the size signifies
- uint64_t base_address; ///< Base address the memory region starts at
- uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address
- memory_area_type type; ///< Specific type of memory the region can contain
- };
- /*struct memory_area
- {
- uint64_t base_address; ///< Base address the memory region starts at
- uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address
- memory_area_type type; ///< Specific type of memory the region can contain
- };*/
-
- /**
- * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type
- * multi_boot_tag_type::MEMORY_MAP.
- */
- struct memory_map
- {
- multi_boot_tag tag; ///< Basic multi_boot_tag information
- uint32_t entry_size; ///< Size of each entry in the memory_area array. Guaranteed multiple of 8
- uint32_t entry_version; ///< Version of the entries, currently 0
- struct memory_area entries; ///< Specific memory regions
- };
-
- /**
* @brief Defines all elf section types an elf section header can have. See
* https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information.
*/
@@ -248,15 +143,15 @@ namespace teachos::arch::memory
* The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC section and
* only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE.
*/
- struct elf_symbols_section
+ struct elf_symbols_section_header
{
- multi_boot_tag tag; ///< Basic multi_boot_tag information
+ tag info; ///< Basic multi_boot_tag information
uint32_t number_of_sections; ///< Number of sections in the sections array
uint32_t entry_size; ///< Size of each entry in the sections array
uint32_t section_index; ///< Index to the string table used for symbol names
std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data
///< contained in the section, to ensure byte alignment is actually 4 byte
};
-} // namespace teachos::arch::memory
+} // namespace teachos::arch::memory::multiboot
-#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP
+#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP
diff --git a/arch/x86_64/include/arch/memory/multiboot/info.hpp b/arch/x86_64/include/arch/memory/multiboot/info.hpp
new file mode 100644
index 0000000..ca87834
--- /dev/null
+++ b/arch/x86_64/include/arch/memory/multiboot/info.hpp
@@ -0,0 +1,62 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP
+
+#include <cstdint>
+
+namespace teachos::arch::memory::multiboot
+{
+ /**
+ * @brief Defines all possible types a multiboot2 tag structure can have.
+ * See
+ * https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot2.h for more information on the structure of the
+ * tag headers and see https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot.h for more information on the
+ * actual header contents and their following data.
+ */
+ enum class tag_type : 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 Sytem 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, ///< Indicated ExitBootServies wasn't called
+ EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer
+ EFI64_IMAGE_HANDLE, ///< EFI 64 bit imae handle pointer
+ LOAD_BASE_ADDRESS ///< Contains image load base physical address
+ };
+
+ /**
+ * @brief Basic structure that every entry in the multi_boot_tag array of the multi_boot_info struct has to begin
+ * with.
+ */
+ struct tag
+ {
+ tag_type type; ///< Specific type of this multi_boot_tag entry, used to differentiate handling
+ uint32_t size; ///< Total size of this multi_boot_tag entry with all fields of the actual type
+ };
+
+ /**
+ * @brief Basic structure the multiboot_information_pointer points too and which contains all information of
+ * multiboot2 in the tags array of different types. The start as well as the content has to be 8 byte aligned.
+ */
+ struct info_header
+ {
+ uint32_t total_size; ///< Total size of all multiboot::tags and their data
+ alignas(8) struct tag tags; ///< Specific tags
+ };
+} // namespace teachos::arch::memory::multiboot
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP
diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp
new file mode 100644
index 0000000..4dc11cf
--- /dev/null
+++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp
@@ -0,0 +1,93 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP
+
+#include "info.hpp"
+#include <cstdint>
+
+namespace teachos::arch::memory::multiboot
+{
+ /**
+ * @brief Defines all memory area types possible that the memory region can be in.
+ */
+ enum class memory_area_type : uint32_t
+ {
+ AVAILABLE = 1, ///< Region is available for use by the OS
+ RESERVED, ///< Region is reserved by firmware or bootloader and should not be used by OS
+ ACPI_AVAILABLE, ///< Region is reclaimable by OS after ACPI event
+ RESERVED_HIBERNATION, ///< Region is used for Non-volatile Storage (NVS)
+ DEFECTIVE ///< Region is defective or unusable
+ };
+
+ /**
+ * @brief Defines an entry in the entries array of the memory_map struct. Has to have all padding stripped between the
+ * individual values, because the size of the entry needs to be exactly 24 bytes and not one byte more. See
+ * https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Packed-Structures.html for more information on the
+ * used attribute.
+ */
+ struct __attribute__((packed)) memory_area
+ {
+ uint32_t size; ///< Size of this structure in bytes
+ uint64_t base_address; ///< Base address the memory region starts at
+ uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address
+ memory_area_type type; ///< Specific type of memory the region can contain
+ };
+
+ /**
+ * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type
+ * multi_boot_tag_type::MEMORY_MAP.
+ */
+ struct memory_map_header
+ {
+ tag info; ///< Basic multi_boot_tag information
+ uint32_t entry_size; ///< Size of each entry in the memory_area array. Guaranteed multiple of 8
+ uint32_t entry_version; ///< Version of the entries, currently 0
+ struct memory_area entries; ///< Specific memory regions
+ };
+
+ /**
+ * @brief Iterator for memory areas.
+ */
+ struct memory_area_iterator
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer.
+ */
+ explicit memory_area_iterator(memory_area * p);
+
+ /**
+ * @brief Dereferences the initally given pointer to its value.
+ *
+ * @return Reference to the value.
+ */
+ memory_area & operator*() const;
+
+ /**
+ * @brief Post increment operator. Returns a copy of the value
+ *
+ * @return Copy of the incremented underlying address.
+ */
+ memory_area_iterator operator++(int);
+
+ /**
+ * @brief Pre increment operator. Returns a reference to the changed value.
+ *
+ * @return Reference to the incremented underlying address.
+ */
+ memory_area_iterator & operator++();
+
+ /**
+ * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators.
+ *
+ * @param other Other iterator to compare to.
+ * @return Whether poith iterators point to the same underlying address in memory.
+ */
+ bool operator==(memory_area_iterator const & other) const = default;
+
+ private:
+ memory_area * ptr; ///< Underlying address the iterator is currently pointing too.
+ };
+} // namespace teachos::arch::memory::multiboot
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP
diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp
new file mode 100644
index 0000000..14086a7
--- /dev/null
+++ b/arch/x86_64/include/arch/memory/multiboot/reader.hpp
@@ -0,0 +1,50 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP
+
+#include "elf_sybols_section.hpp"
+#include "memory_map.hpp"
+#include <cstdint>
+
+namespace teachos::arch::memory::multiboot
+{
+ /**
+ * @brief Contains all relevant information to map and allocate memory that is read from the multiboot2 information
+ * structure.
+ */
+ struct memory_information
+ {
+ std::size_t kernel_start; ///< Start address of the kernel code in memory.
+ std::size_t kernel_end; ///< End address of the kernel code in memory.
+ std::size_t multiboot_start; ///< Start address of the multiboot code in memory.
+ std::size_t multiboot_end; ///< End address of the multiboot code in memory.
+ memory_area * memory_areas; ///< Non-owning pointer to the first element of all memory areas.
+ uint8_t area_count; ///< Amount of total entries in the memory_areas array.
+ };
+
+ /**
+ * @brief Reads the relevant multiboot2 information data from memory. This is done using the
+ * multiboot_information_pointer, which marks the start of the multiboot2 data. The indivdual headers we have to read
+ * are 8 byte aligned, whereas the data contained in those headers does not have to be. All sections that are read
+ * additionaly receive some sanity to ensure the read address is actually pointing to the expected structure, if they
+ * are not this method will assert.
+ *
+ * The memory_information variables are calcualted like this:
+ * - kernel_start: Calculated by getting the lowest address specified in the elf symbols headers.
+ * - kernel_end: Calculated by getting the highest address specified in the elf symbols headers and adding the length
+ * of that section.
+ * - multiboot_start: Calcualted by simply getting the value of the multiboot information pointer, because it already
+ * contains the address pointint to the start of the multiboot2 data.
+ * - multiboot_end: Calcualted by getting the value of the multiboot information pointer and adding the total size of
+ * the complete multiboot2 data
+ * - memory_areas: Calculated by simply accessing the address of the entries variable in the memory map header
+ * structure.
+ * - area_count: Calculated by subtracing the memory map header size from the total tag size, which results in the
+ * remaining size (size of the entries array), this size is then divided by the size of one entry in that array, which
+ * should be 24 bytes.
+ *
+ * @return Relevant data read from multiboot2.
+ */
+ auto read_multiboot2() -> memory_information;
+} // namespace teachos::arch::memory::multiboot
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP
diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp
index 4bbb0e0..04c2065 100644
--- a/arch/x86_64/include/arch/memory/paging.hpp
+++ b/arch/x86_64/include/arch/memory/paging.hpp
@@ -4,6 +4,7 @@
#include "arch/exception_handling/assert.hpp"
#include "frame_allocator.hpp"
+#include <bitset>
namespace teachos::arch::memory
{
@@ -113,6 +114,10 @@ namespace teachos::arch::memory
template<level page_table_level>
struct page_table
{
+ /**
+ * @brief Level of the page table, level 1 should not be able to call next_table anymore, because it would result in
+ * attempting to access memory that it should not.
+ */
enum level : uint8_t
{
LEVEL1,
diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp
index babe251..c0d4aed 100644
--- a/arch/x86_64/src/kernel/main.cpp
+++ b/arch/x86_64/src/kernel/main.cpp
@@ -1,120 +1,14 @@
#include "arch/kernel/main.hpp"
-#include "arch/boot/pointers.hpp"
#include "arch/exception_handling/assert.hpp"
#include "arch/memory/frame_allocator.hpp"
-#include "arch/memory/multiboot.hpp"
+#include "arch/memory/multiboot/reader.hpp"
#include "arch/video/vga/text.hpp"
#include <algorithm>
namespace teachos::arch::kernel
{
- auto process_memory_map(arch::memory::memory_map * mminfo, arch::memory::memory_area *& memory_areas,
- uint8_t & area_count) -> void
- {
- auto expected_entry_size = mminfo->entry_size;
- constexpr auto actual_entry_size = sizeof(arch::memory::memory_area);
- arch::exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected memoryarea entry size");
-
- auto total_size = mminfo->tag.size;
- auto total_entries_size = total_size - sizeof(arch::memory::memory_map) + 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(arch::memory::elf_symbols_section * symbol, uint64_t & kernel_start,
- uint64_t & kernel_end) -> void
- {
- auto expected_entry_size = symbol->entry_size;
- constexpr auto actual_entry_size = sizeof(arch::memory::elf_section_header);
- arch::exception_handling::assert(expected_entry_size == actual_entry_size,
- "Unexpected elf_section_header entry size");
-
- auto expected_total_size = symbol->tag.size;
- auto actual_total_entry_size = actual_entry_size * symbol->number_of_sections;
- constexpr auto actual_total_section_size = sizeof(arch::memory::elf_symbols_section) - 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 total size");
-
- auto begin = reinterpret_cast<arch::memory::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)
- {
- bool const writable = section->flags.contains_flags(arch::memory::elf_section_flags::WRITABLE);
- bool const occupies_memory = section->flags.contains_flags(arch::memory::elf_section_flags::OCCUPIES_MEMORY);
- bool const is_executable = section->flags.contains_flags(arch::memory::elf_section_flags::EXECUTABLE_CODE);
- bool const contains_duplicate_data =
- section->flags.contains_flags(arch::memory::elf_section_flags::DUPLICATE_DATA);
- bool const contains_strings = section->flags.contains_flags(arch::memory::elf_section_flags::CONTAINS_STRING);
- bool const section_header_info_is_section_header_table_index = section->flags.contains_flags(
- arch::memory::elf_section_flags::SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX);
- bool const preserve_ordering_after_combination =
- section->flags.contains_flags(arch::memory::elf_section_flags::PRESERVE_ORDERING_AFTER_COMBINATION);
- bool const requires_special_os_processing =
- section->flags.contains_flags(arch::memory::elf_section_flags::REQUIRES_SPECIAL_OS_PROCESSING);
- bool const is_section_group_member =
- section->flags.contains_flags(arch::memory::elf_section_flags::SECTION_GROUP_MEMBER);
- bool const holds_thread_local_data =
- section->flags.contains_flags(arch::memory::elf_section_flags::HOLDS_THREAD_LOCAL_DATA);
- bool const is_compressed = section->flags.contains_flags(arch::memory::elf_section_flags::COMPRESSED);
- bool const has_special_ordering_requirements =
- section->flags.contains_flags(arch::memory::elf_section_flags::SPECIAL_ORDERING_REQUIREMENTS);
- bool const is_excluded_unless_referenced_or_allocated =
- section->flags.contains_flags(arch::memory::elf_section_flags::EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED);
-
- if (writable && occupies_memory && is_executable && contains_duplicate_data && contains_strings &&
- section_header_info_is_section_header_table_index && preserve_ordering_after_combination &&
- requires_special_os_processing && is_section_group_member && holds_thread_local_data && is_compressed &&
- has_special_ordering_requirements && is_excluded_unless_referenced_or_allocated)
- {
- }
-
- switch (section->type)
- {
- case arch::memory::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 arch::memory::elf_section_type::DYNAMIC_SYMBOL_TABLE:
- case arch::memory::elf_section_type::SYMBOL_TABLE:
- symbol_table_section_count++;
- break;
- case arch::memory::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");
- }
-
- 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 main() -> void
{
using namespace video::vga;
@@ -123,47 +17,8 @@ namespace teachos::arch::kernel
text::cursor(false);
text::write("TeachOS is starting up...", text::common_attributes::green_on_black);
- auto * multiboot_information_pointer =
- reinterpret_cast<arch::memory::multi_boot_info *>(arch::boot::multiboot_information_pointer);
- auto multiboot_tag = &(multiboot_information_pointer->tags);
-
- uint64_t kernel_start = UINT64_MAX;
- uint64_t kernel_end = 0;
- uint64_t multiboot_start = arch::boot::multiboot_information_pointer;
- uint64_t multiboot_end = multiboot_start + multiboot_information_pointer->total_size;
- arch::memory::memory_area * memory_areas = nullptr;
- uint8_t area_count = 0;
-
- /*
- * Loop over the multiboot2 tags to access the information needed.
- * Tags are defined in the header file and are padded so that each
- * Tag starts at an 8-bytes aligned adress.
- *
- * The increment part aligns the size to an 8-byte address.
- */
- for (auto tag = multiboot_tag; tag->type != arch::memory::multi_boot_tag_type::END;
- tag = align_to_8_byte_boundary(tag, tag->size))
- {
- switch (tag->type)
- {
- case arch::memory::multi_boot_tag_type::ELF_SECTIONS: {
- auto symbol = reinterpret_cast<teachos::arch::memory::elf_symbols_section *>(tag);
- process_elf_sections(symbol, kernel_start, kernel_end);
- break;
- }
- case arch::memory::multi_boot_tag_type::MEMORY_MAP: {
- auto mminfo = reinterpret_cast<teachos::arch::memory::memory_map *>(tag);
- process_memory_map(mminfo, memory_areas, area_count);
- break;
- }
- default:
- // All other cases are not important and can be ignored
- break;
- }
- }
-
- auto allocator = arch::memory::area_frame_allocator(kernel_start, kernel_end, multiboot_start, multiboot_end,
- memory_areas, area_count);
+ auto memory_information = memory::multiboot::read_multiboot2();
+ auto allocator = memory::area_frame_allocator(memory_information);
auto last_allocated = allocator.allocate_frame();
auto allocated = last_allocated;
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::c