From e9232199bdd97233dabd59f07c63607c93c0c59c Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Sun, 21 Mar 2021 16:53:07 +0200 Subject: Check multiboot2 header length, and if needed map the next page as well --- libk/result.h | 5 +++-- linker.ld | 3 ++- makefile | 6 +++--- src/boot.S | 48 ++++++++++++++++++++++++++++-------------------- src/kernel.cc | 23 ++++++++++++++++------- src/kernel/multiboot.cc | 4 +++- src/vmm.cc | 7 +++++++ src/vmm.h | 8 +------- toolchain.makefile | 5 +++-- 9 files changed, 66 insertions(+), 43 deletions(-) diff --git a/libk/result.h b/libk/result.h index 8077baf..e940bd9 100644 --- a/libk/result.h +++ b/libk/result.h @@ -7,6 +7,7 @@ template class Result { public: + constexpr Result() = default; explicit constexpr Result(T t) : is_ok(true), data{.t = t} {}; explicit constexpr Result(E e) : is_ok(false), data{.e = e} {}; @@ -15,9 +16,9 @@ public: constexpr T value() const { return is_ok ? data.t : T{}; } private: - const bool is_ok; + const bool is_ok = false; union { T t; - E e; + E e = E::NoError; } data; }; diff --git a/linker.ld b/linker.ld index d1dedd2..f7010e7 100644 --- a/linker.ld +++ b/linker.ld @@ -11,7 +11,8 @@ SECTIONS */ . = 0; .multiboot : { - *(.multiboot.header) + . = ALIGN(8); + KEEP(*(.multiboot.header)) } /* Begin putting sections at 4 MiB */ diff --git a/makefile b/makefile index fc3338e..7eecced 100644 --- a/makefile +++ b/makefile @@ -14,7 +14,7 @@ CXX_OBJ := $(addprefix $(OBJ_DIR)/, $(CXX_OBJ)) CXX_DEP = $(CXX_OBJ:%.o=%.d) CXX_TEST_OBJ := $(addprefix $(OBJ_DIR)/, $(CXX_TEST_OBJ)) CXX_INCLUDE := $(addprefix -I, $(CXX_INCLUDE)) -CXX_SYSTEM_INCLUDE := $(addprefix -isystem, $(CXX_SYSTEM_INCLUDE)) +SYSTEM_INCLUDE := $(addprefix -isystem, $(SYSTEM_INCLUDE)) $(OBJ_DIR)/glitch.elf: $(autogen) $(AS_OBJ) $(CXX_OBJ) linker.ld @echo " LD $@" @@ -23,13 +23,13 @@ $(OBJ_DIR)/glitch.elf: $(autogen) $(AS_OBJ) $(CXX_OBJ) linker.ld $(AS_OBJ): $(OBJ_DIR)/%.o: %.S @mkdir -p $(@D) @echo " AS $<" - @$(AS) -target $(TARGET) -nostdlib -Wall -Wextra -c $^ -o $@ + @$(AS) -target $(TARGET) $(AS_FLAGS) $(SYSTEM_INCLUDE) -c $^ -o $@ -include $(CXX_DEP) $(CXX_OBJ): $(OBJ_DIR)/%.o : %.cc @mkdir -p $(@D) @echo " CXX $<" - @$(CXX) -target $(TARGET) $(CXX_FLAGS) $(CXX_INCLUDE) $(CXX_SYSTEM_INCLUDE) -MMD -c $< -o $@ + @$(CXX) -target $(TARGET) $(CXX_FLAGS) $(CXX_INCLUDE) $(SYSTEM_INCLUDE) -MMD -c $< -o $@ $(CXX_TEST_OBJ): $(OBJ_DIR)/%.o : %.cc @mkdir -p $(@D) diff --git a/src/boot.S b/src/boot.S index 0451066..3a07c19 100644 --- a/src/boot.S +++ b/src/boot.S @@ -1,35 +1,43 @@ -/* - Declare a multiboot header that marks the program as a kernel. - https://www.gnu.org/software/grub/manual/multiboot2/html_node/index.html - - The Multiboot2 header must be contained completely within the first - 32kB of the OS image, and must be 64-bit (8 byte) aligned. -*/ -.set MULTIBOOT_HEADER_MAGIC, 0xe85250d6 # multiboot2 magic number -.set MULTIBOOT_ARCHITECTURE, 0 # protected mode i386 -.set MULTIBOOT_HEADER_TAG_END, 0 +/* Declare a multiboot header that marks the program as a kernel. + * https://www.gnu.org/software/grub/manual/multiboot2/html_node/index.html + * The Multiboot2 header must be contained completely within the first 32kB, and must be 8 byte aligned. + */ +#define ASM_FILE +#include .section .multiboot.header, "a" .align 8 header_start: - .int MULTIBOOT_HEADER_MAGIC - .int MULTIBOOT_ARCHITECTURE + .int MULTIBOOT2_HEADER_MAGIC + .int MULTIBOOT_ARCHITECTURE_I386 .int header_end - header_start - .int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE + (header_end - header_start)) + .int -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + (header_end - header_start)) - # TODO tags go here +.align 8 +information_tag_start: + .short MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST + .short 0 + .int information_tag_end - information_tag_start + .int MULTIBOOT_TAG_TYPE_MMAP +information_tag_end: +.align 8 +module_tag_start: + .short MULTIBOOT_HEADER_TAG_MODULE_ALIGN + .short 0 + .int module_tag_end - module_tag_start +module_tag_end: + +.align 8 .short MULTIBOOT_HEADER_TAG_END .short 0 .int 8 header_end: -/* - The stack on x86 must be 16-byte aligned according to the System V ABI - standard and de-facto extensions. The compiler will assume the stack is - properly aligned and failure to align the stack will result in undefined - behavior. -*/ +/* The stack on x86 must be 16-byte aligned according to the System V ABI standard and de-facto extensions. The + * compiler will assume the stack is properly aligned and failure to align the stack will result in undefined + * behavior. + */ .section .stack, "aw", @nobits .align 16 stack_bottom: diff --git a/src/kernel.cc b/src/kernel.cc index 05e0daf..53500bc 100644 --- a/src/kernel.cc +++ b/src/kernel.cc @@ -32,7 +32,7 @@ extern "C" { void dump_multiboot(uint32_t mb_magic, uint32_t mb_addr); void dump_gdt(); -void kernel_main(uint32_t mb_magic, uint32_t mb_addr) { +void kernel_main(uint32_t mb_magic, const uint32_t mb_addr) { #ifdef HAS_SERIAL0 if constexpr (serial0_console) if (serial0.self_check()) Console::set(&serial0); @@ -54,19 +54,28 @@ void kernel_main(uint32_t mb_magic, uint32_t mb_addr) { dump_address(); // dump_gdt(); - // { - const auto mb_addr_r = kvmm.map(mb_addr, 0xc03fe000); + printk("Multiboot2 header at ", uhex{mb_addr}, '\n'); + + const auto mb_addr_r = kvmm.map(mb_addr, {768, 1020}); runtime_assert(mb_addr_r, "Failed to map mb_addr"); - mb_addr = mb_addr_r.value(); - const auto mb_size = check_multiboot(mb_magic, mb_addr); + const auto mb_addr_ = mb_addr_r.value(); + const auto mb_size = check_multiboot(mb_magic, mb_addr_); runtime_assert((mb_size != 0), "Invalid multiboot header"); - printk("Multiboot2 header at ", uhex{mb_addr}, " size: ", mb_size, '\n'); + const auto mb_addr_re = [mb_addr, mb_size]() -> Result { + if (mb_addr % 4096 + mb_size >= 4096) return kvmm.map((mb_addr % 4096 + 4096), {768, 1021}); + return {}; + }(); + + printk("Multiboot2 header mounted at ", uhex{mb_addr}, " size: ", mb_size, '\n'); + + dump_multiboot(mb_magic, mb_addr_); - // dump_multiboot(mb_magic, mb_addr); + if (mb_addr_r) kvmm.unmap(mb_addr_r.value()); + if (mb_addr_re) kvmm.unmap(mb_addr_re.value()); } GDT gdt; diff --git a/src/kernel/multiboot.cc b/src/kernel/multiboot.cc index 024916e..e0626f0 100644 --- a/src/kernel/multiboot.cc +++ b/src/kernel/multiboot.cc @@ -1,5 +1,7 @@ #include -#include + +typedef multiboot_uint16_t uint16_t; +typedef multiboot_uint32_t uint32_t; uint32_t check_multiboot(uint32_t mb_magic, uint32_t mb_addr) { if (mb_magic != MULTIBOOT2_BOOTLOADER_MAGIC) return 0; diff --git a/src/vmm.cc b/src/vmm.cc index 3c90c48..abce5b8 100644 --- a/src/vmm.cc +++ b/src/vmm.cc @@ -78,6 +78,13 @@ Result vmm::map(uint32_t addr, const vmm::address dest) { return Result{vmm::AddressAlreadyMapped}; } +void vmm::unmap(const address d) { + if (directory[d.table_idx] == 0) return; + page_table table{directory[d.table_idx]}; + table.set(d.page_idx, 0); + vmm::reload(); +} + vmm::page_table::page_table(uint32_t from) { // TODO get flags // convert physical address to a virtual address so we can read it diff --git a/src/vmm.h b/src/vmm.h index 252e5bb..1729275 100644 --- a/src/vmm.h +++ b/src/vmm.h @@ -28,13 +28,6 @@ public: vmm(uint32_t* addr = nullptr); - [[deprecated]] constexpr static size_t table_id(uint32_t offset) { - offset &= 0xfff00000; - offset /= (4 * 1024 * 1024); - return static_cast(offset); - } - [[deprecated]] constexpr static size_t page_id(uint32_t offset) { return static_cast(offset / 4096); } - static void reload() { uint32_t cr0; asm volatile("mov %%cr0, %0" : "=r"(cr0)); @@ -42,6 +35,7 @@ public: } [[nodiscard]] Result map(uint32_t phys_addr, const address dest); + void unmap(const address); private: class page_table { diff --git a/toolchain.makefile b/toolchain.makefile index a4a0667..dc6194e 100644 --- a/toolchain.makefile +++ b/toolchain.makefile @@ -5,7 +5,7 @@ NM := llvm-nm SED := sed AS := clang -AS_FLAGS := +AS_FLAGS := -nostdlib -Wall -Wextra LD := ld.lld LD_FLAGS := -nostdlib -T linker.ld @@ -22,7 +22,8 @@ CXX_FLAGS := -std=c++20 -g -O3 -flto=full \ -Wconsumed CXX_TEST_FLAGS := -std=c++20 -Wall -Wextra -Werror=pedantic CXX_INCLUDE := $(CURDIR)/libk $(CURDIR)/src $(CURDIR)/drivers -CXX_SYSTEM_INCLUDE := $(CURDIR)/grub + +SYSTEM_INCLUDE := $(CURDIR)/grub # GRUB_MKRESCUE := grub-mkrescue -- cgit v1.2.1