From 74eaee0fcc7390d4290b41a2a92ee34346e2f7c2 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 11 Oct 2023 14:43:50 +0200 Subject: teachos: restructure file layout --- source/CMakeLists.txt | 60 +++- source/arch/x86_64/CMakeLists.txt | 66 ++++ source/arch/x86_64/include/arch/boot/pointers.hpp | 12 + source/arch/x86_64/include/arch/kernel/main.hpp | 11 + source/arch/x86_64/include/arch/video/vga/text.hpp | 12 + source/arch/x86_64/scripts/kernel.ld | 139 ++++++++ source/arch/x86_64/src/boot/boot.s | 374 +++++++++++++++++++++ source/arch/x86_64/src/boot/crti.s | 13 + source/arch/x86_64/src/boot/crtn.s | 9 + source/arch/x86_64/src/boot/multiboot.s | 26 ++ source/arch/x86_64/src/kernel/main.cpp | 15 + source/arch/x86_64/src/video/vga/text.cpp | 29 ++ source/arch/x86_64/support/grub.cfg.in | 7 + source/boot/CMakeLists.txt | 19 -- source/boot/arch/x86_64/CMakeLists.txt | 10 - source/boot/arch/x86_64/include/boot/pointers.hpp | 12 - source/boot/arch/x86_64/src/boot.s | 374 --------------------- source/boot/arch/x86_64/src/crti.s | 13 - source/boot/arch/x86_64/src/crtn.s | 9 - source/boot/arch/x86_64/src/multiboot.s | 26 -- source/boot/include/boot/asm_pointer.hpp | 43 --- source/include/memory/asm_pointer.hpp | 43 +++ source/kernel/CMakeLists.txt | 25 -- source/kernel/arch/x86_64/CMakeLists.txt | 58 ---- source/kernel/arch/x86_64/include/kernel/vga.hpp | 11 - source/kernel/arch/x86_64/kern.ld | 139 -------- source/kernel/arch/x86_64/src/entry.cpp | 9 - source/kernel/arch/x86_64/src/vga.cpp | 29 -- source/kernel/arch/x86_64/support/grub.cfg.in | 7 - source/src/kernel/main.cpp | 3 + 30 files changed, 817 insertions(+), 786 deletions(-) create mode 100644 source/arch/x86_64/CMakeLists.txt create mode 100644 source/arch/x86_64/include/arch/boot/pointers.hpp create mode 100644 source/arch/x86_64/include/arch/kernel/main.hpp create mode 100644 source/arch/x86_64/include/arch/video/vga/text.hpp create mode 100644 source/arch/x86_64/scripts/kernel.ld create mode 100644 source/arch/x86_64/src/boot/boot.s create mode 100644 source/arch/x86_64/src/boot/crti.s create mode 100644 source/arch/x86_64/src/boot/crtn.s create mode 100644 source/arch/x86_64/src/boot/multiboot.s create mode 100644 source/arch/x86_64/src/kernel/main.cpp create mode 100644 source/arch/x86_64/src/video/vga/text.cpp create mode 100644 source/arch/x86_64/support/grub.cfg.in delete mode 100644 source/boot/CMakeLists.txt delete mode 100644 source/boot/arch/x86_64/CMakeLists.txt delete mode 100644 source/boot/arch/x86_64/include/boot/pointers.hpp delete mode 100644 source/boot/arch/x86_64/src/boot.s delete mode 100644 source/boot/arch/x86_64/src/crti.s delete mode 100644 source/boot/arch/x86_64/src/crtn.s delete mode 100644 source/boot/arch/x86_64/src/multiboot.s delete mode 100644 source/boot/include/boot/asm_pointer.hpp create mode 100644 source/include/memory/asm_pointer.hpp delete mode 100644 source/kernel/CMakeLists.txt delete mode 100644 source/kernel/arch/x86_64/CMakeLists.txt delete mode 100644 source/kernel/arch/x86_64/include/kernel/vga.hpp delete mode 100644 source/kernel/arch/x86_64/kern.ld delete mode 100644 source/kernel/arch/x86_64/src/entry.cpp delete mode 100644 source/kernel/arch/x86_64/src/vga.cpp delete mode 100644 source/kernel/arch/x86_64/support/grub.cfg.in create mode 100644 source/src/kernel/main.cpp (limited to 'source') diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 326fc8d..15b4016 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -7,8 +7,64 @@ project("kernel" LANGUAGES ASM C CXX ) +#[============================================================================[ +# Global Build System Configuration +#]============================================================================] + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION YES) + +#[============================================================================[ +# Global Compiler Configuration +#]============================================================================] + +add_compile_options( + "$<$:-Wall>" + "$<$:-Wextra>" + "$<$:-Werror>" + "$<$:-pedantic-errors>" +) + +#[============================================================================[ +# Global Directories +#]============================================================================] + +include_directories( + "include" + "arch/${CMAKE_SYSTEM_PROCESSOR}/include" +) + +#[============================================================================[ +# The Bootstrap Library +#]============================================================================] + +add_library("_boot" OBJECT) +add_library("teachos::boot" ALIAS "_boot") + +#[============================================================================[ +# The Video Library +#]============================================================================] + +add_library("_video" OBJECT) +add_library("teachos::video" ALIAS "_video") + +#[============================================================================[ +# The Kernel +#]============================================================================] + +add_executable("_kernel" + "src/kernel/main.cpp" +) +add_executable("teachos::kernel" ALIAS "_kernel") + +target_link_libraries("_kernel" PRIVATE + "teachos::boot" + "teachos::video" +) + +#[============================================================================[ +# Platform Specific Components +#]============================================================================] -add_subdirectory("boot") -add_subdirectory("kernel") +add_subdirectory("arch/${CMAKE_SYSTEM_PROCESSOR}") diff --git a/source/arch/x86_64/CMakeLists.txt b/source/arch/x86_64/CMakeLists.txt new file mode 100644 index 0000000..f917cd0 --- /dev/null +++ b/source/arch/x86_64/CMakeLists.txt @@ -0,0 +1,66 @@ +#[============================================================================[ +# The Kernel Library +#]============================================================================] + +set(TEACHOS_KERNEL_LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/kernel.ld") +mark_as_advanced(TEACHOS_KERNEL_LINKER_SCRIPT) + +target_sources("_kernel" PRIVATE + "src/kernel/main.cpp" +) + +target_link_options("_kernel" PRIVATE + "-T${TEACHOS_KERNEL_LINKER_SCRIPT}" +) + +set_target_properties("_kernel" PROPERTIES + LINK_DEPENDS "${TEACHOS_KERNEL_LINKER_SCRIPT}" +) + +#[============================================================================[ +# The Bootstrap Library +#]============================================================================] + +target_sources("_boot" PRIVATE + "src/boot/boot.s" + "src/boot/crti.s" + "src/boot/crtn.s" + "src/boot/multiboot.s" +) + +#[============================================================================[ +# The Video Library +#]============================================================================] + +target_sources("_video" PRIVATE + "src/video/vga/text.cpp" +) + +#[============================================================================[ +# The Bootable ISO Image +#]============================================================================] + +find_package("grub-mkrescue") + +if(grub-mkrescue_FOUND) + set(ISO_FILE "${PROJECT_BINARY_DIR}/teachos.iso") + + file(GENERATE + OUTPUT "isofs/boot/grub/grub.cfg" + INPUT "support/grub.cfg.in" + ) + + add_custom_target("bootable-iso" + COMMAND "${GRUB_MKRESCUE_EXE}" + "-o" + "${ISO_FILE}" + "${CMAKE_CURRENT_BINARY_DIR}/isofs" + "$" + "2>/dev/null" + DEPENDS + "$" + "isofs/boot/grub/grub.cfg" + BYPRODUCTS "${ISO_FILE}" + COMMENT "Creating bootable ISO image" + ) +endif() diff --git a/source/arch/x86_64/include/arch/boot/pointers.hpp b/source/arch/x86_64/include/arch/boot/pointers.hpp new file mode 100644 index 0000000..052b115 --- /dev/null +++ b/source/arch/x86_64/include/arch/boot/pointers.hpp @@ -0,0 +1,12 @@ +#ifndef TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP +#define TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP + +#include + +namespace teachos::arch::boot +{ + extern "C" std::byte const multiboot_information_pointer; + extern "C" std::byte * vga_buffer_pointer; +} // namespace teachos::arch::boot + +#endif \ No newline at end of file diff --git a/source/arch/x86_64/include/arch/kernel/main.hpp b/source/arch/x86_64/include/arch/kernel/main.hpp new file mode 100644 index 0000000..6961594 --- /dev/null +++ b/source/arch/x86_64/include/arch/kernel/main.hpp @@ -0,0 +1,11 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP + +#include + +namespace teachos::arch::kernel +{ + auto main() -> void; +} + +#endif \ No newline at end of file diff --git a/source/arch/x86_64/include/arch/video/vga/text.hpp b/source/arch/x86_64/include/arch/video/vga/text.hpp new file mode 100644 index 0000000..04b74d1 --- /dev/null +++ b/source/arch/x86_64/include/arch/video/vga/text.hpp @@ -0,0 +1,12 @@ +#ifndef TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP +#define TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP + +#include +#include + +namespace teachos::arch::video::vga::text +{ + auto write(std::string_view text, std::byte color) -> void; +} + +#endif \ No newline at end of file diff --git a/source/arch/x86_64/scripts/kernel.ld b/source/arch/x86_64/scripts/kernel.ld new file mode 100644 index 0000000..0817081 --- /dev/null +++ b/source/arch/x86_64/scripts/kernel.ld @@ -0,0 +1,139 @@ +ENTRY(_start) + +/***************************************************************************** + * Virtual and linear start addresses of the TeachOS kernel + *****************************************************************************/ +TEACHOS_HIGH = -2048M; +TEACHOS_LOW = 1M; + +PHDRS { + boot_rodata PT_LOAD FLAGS(4); + boot_text PT_LOAD FLAGS(5); + boot_data PT_LOAD FLAGS(6); + + text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); + rodata PT_LOAD FLAGS(4); +} + +SECTIONS +{ + /*************************************************************************** + * Load the bootstrap code into low memory. We need to be accessible in + * 32-Bit mode, so we want to live down low, but we need to leave the 1MiB + * hole open since some BIOS functionality resides below it. + ***************************************************************************/ + . = TEACHOS_LOW; + + /*************************************************************************** + * We want to be able to be able to access all memory (linear and virtual) + * during bootstrapping and operation. To achieve this, we define some + * symbols at the beginning. + ***************************************************************************/ + _start_linear = .; + _start_virtual = . + TEACHOS_HIGH; + + /*************************************************************************** + * The bootstrapping infratructure goes first. We first place the read-only + * data, followed by our code, initialized mutable data, and finally our + * uninitialized mutable data. + ***************************************************************************/ + .boot_rodata : + { + KEEP(*(.boot_mbh)) + *(.boot_rodata) + } :boot_rodata + + .boot_text : + { + *(.boot_text) + } :boot_text + + .boot_data : + { + *(.boot_data) + } :boot_data + + .boot_bss : + { + *(.boot_bss) + *(.boot_stack) + } + + /*************************************************************************** + * Now it is time to load the 64-bit kernel code. We virtually load it into + * the upper 2GiB, while adjusting the linear load address appropriately. We + * also make sure to align the loaded data onto a page boundary. + ***************************************************************************/ + . = ALIGN(4K); + . += TEACHOS_HIGH; + + .init ALIGN(4K) : AT(ADDR (.init) - TEACHOS_HIGH) + { + /* + * Make sure that the crt code is wrapped around the compiler generated + * initialization code. + */ + KEEP(*crti.s.obj(.init)) + KEEP(*(EXCLUDE_FILE (*crti.s.obj crtn.s.obj) .init)) + KEEP(*crtn.s.obj(.init)) + } :text + + .fini ALIGN(4K) : AT(ADDR (.fini) - TEACHOS_HIGH) + { + /* + * Make sure that the crt code is wrapped around the compiler generated + * finalizer code. + */ + KEEP(*crti.s.obj(.fini)) + KEEP(*(EXCLUDE_FILE (*crti.s.obj crtn.s.obj).fini)) + KEEP(*crtn.s.obj(.fini)) + } + + .text ALIGN(4K) : AT(ADDR (.text) - TEACHOS_HIGH) + { + *(.text*) + } + + .rodata ALIGN(4K) : AT (ADDR (.rodata) - TEACHOS_HIGH) + { + *(.rodata) + *(.rodata.*) + } :rodata + + .ctors ALIGN(4K) : AT (ADDR (.ctors) - TEACHOS_HIGH) + { + KEEP(*crtbegin.o(.ctors)) + KEEP(*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP(*(SORT(.ctors.*))) + KEEP(*crtend.o(.ctors)) + } :data + + .dtors ALIGN(4K) : AT (ADDR (.dtors) - TEACHOS_HIGH) + { + KEEP(*crtbegin.o(.dtors)) + KEEP(*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP(*(SORT(.dtors.*))) + KEEP(*crtend.o(.dtors)) + } + + .data ALIGN(4K) : AT (ADDR (.data) - TEACHOS_HIGH) + { + *(.data*) + } + + .bss ALIGN(4K) : AT (ADDR (.bss) - TEACHOS_HIGH) + { + *(COMMON) + *(.bss*) + } + + /*************************************************************************** + * In accordance with the symbol definitions at the start, we generate some + * symbols to mark the end of our loaded image. + ***************************************************************************/ + _end_virtual = ADDR(.bss) + SIZEOF(.bss); + _end_linear = _end_virtual - TEACHOS_HIGH; + + /DISCARD/ : { *(.comment) } +} diff --git a/source/arch/x86_64/src/boot/boot.s b/source/arch/x86_64/src/boot/boot.s new file mode 100644 index 0000000..45f261e --- /dev/null +++ b/source/arch/x86_64/src/boot/boot.s @@ -0,0 +1,374 @@ +.extern _end_physical +.extern _init +.extern kernel_main + + +/** + * Uninitialized data for the bootstrapping process. + */ +.section .boot_bss, "aw", @nobits +.align 4096 + +/** + * Reserve space for the page maps we are going to used during startup. + * + * Note: We are going to use large pages to make the initial mapping code + * simpler. + * + * We need: + * - A single PML 4 (since we will only use 4-level paging) + * - 2 PML 3s (since we need to map high (-2GiB) and low (1+MiB) memory) + * - 2 PML 2s (since we need to map high (-2GiB) and low (1+MiB) memory) + */ + +.global page_map_level_4 +page_map_level_4: .skip 512 * 8 + +.global page_map_level_3_low +page_map_level_3_low: .skip 512 * 8 +.global page_map_level_3_high +page_map_level_3_high: .skip 512 * 8 + +.global page_map_level_2_low +page_map_level_2_low: .skip 512 * 8 +.global page_map_level_2_high +page_map_level_2_high: .skip 512 * 8 + +/** + * Reserve some space for the Multiboot 2 information pointer. + */ +.global multiboot_information_pointer +multiboot_information_pointer: .skip 4 + +/** + * Stack space for the bootstrapping process. + * + * Note: We are going to reserve 1 MiB for now. If/when the kernel requires + * more space to run, it will have to relocate the stack. + */ +.section .boot_stack, "aw", @nobits +.align 16 + +stack_bottom: .skip 1 << 20 +stack_top: + +/** + * Constants for the bootstrapping process. + */ +.section .boot_rodata, "a", @progbits + +/** + * A valid Global Descriptor Table is still required in long mode. However, we + * only need a single entry for the "code segment", so we will setup a single + * segment table below. + * + * Bit 43: "E" in the access byte => mark the segment as executable. + * Bit 44: "S" in the access byte => mark the segment as code or data. + * Bit 47: "P" in the access byte => mark the segment as being present. + * Bit 53: "L" in the flags byte => mark the segment as being for long mode + */ + +global_descriptor_table: .quad 0 +global_descriptor_table_code = . - global_descriptor_table +.quad (1<<43) | (1<<44) | (1<<47) | (1<<53) + +/** + * We also need a pointer that we can load into the GDTR. + * + * The pointer consists of a word describing the size of the table minus 1 and + * the pointer to the actual table. + */ +global_descriptor_table_pointer: +.word . - global_descriptor_table - 1 +.quad global_descriptor_table + +/** + * We are going to print some messages in case we panic during boot, so we are + * going to store them here as well + */ +message_prefix_panic: +.string "TeachOS Panic: " +message_not_loaded_by_multiboot2: +.string "The operating system was not loaded by a Multiboot 2 loader." +message_cpuid_instruction_no_supported: +.string "The 'cpuid' instruction is not supported on this platform." +mesage_long_mode_not_supported: +.string "Long mode is not supported by this platform." + +/** + * Mutable data for the bootstrapping process. + */ +.section .boot_data, "aw", @progbits + +/** + * We need a pointer to our current position in the VGA text buffer. + */ +.global vga_buffer_pointer +vga_buffer_pointer: .long 0xb8000 + +/** + * Code for the bootstrapping process. + */ +.section .boot_text, "ax", @progbits +.align 16 +.code32 + +/** + * Print a given panic message and then halt the machine. + * + * Parameters: + * - [stack - 0] message: the message to print + */ +_panic: + push %ebp + mov %esp, %ebp + + push message_prefix_panic + push $0x4f + call _print + add $8, %esp + + push 8(%ebp) + push 0x4f + call _print + add $8, %esp + + hlt + +/** + * Print a message via the VGA buffer. + * + * Parameters: + * - [stack - 4] message: the message to print + * - [stack - 0] color: the color of the message + */ +_print: + push %ebp + mov %esp, %ebp + + push %ebx + push %esi + mov 8(%ebp), %eax + mov 12(%ebp), %ebx + mov $0, %ecx + mov (vga_buffer_pointer), %esi + +.Lprint_loop: + mov (%ebx, %ecx), %dl + test %dl, %dl + je .Lupdate_vga_buffer_address + mov %dl, (%esi, %ecx, 2) + mov %al, 1(%esi, %ecx, 2) + inc %ecx + jmp .Lprint_loop + +.Lupdate_vga_buffer_address: + shl $1, %ecx + add %ecx, (vga_buffer_pointer) + +.Lprint_end: + pop %esi + pop %ebx + mov %ebp, %esp + pop %ebp + ret + +/** + * This is our entry point after being loaded by the bootloader. + * + * Having this in assembly makes it easier for us to keep things together. + */ +.global _start +_start: + mov $stack_top, %esp + mov %esp, %ebp + + call assert_loaded_by_multiboot2_loader + call assert_cpuid_instruction_is_supported + call assert_cpu_supports_long_mode + call prepare_page_maps + call enable_paging + call enable_sse + + lgdt (global_descriptor_table_pointer) + jmp $global_descriptor_table_code,$_transition_to_long_mode + + hlt + +/** + * Assert that the CPU supports going into long mode. + */ +assert_cpu_supports_long_mode: + mov $0x80000000, %eax + cpuid + cmp $0x80000001, %eax + jb .Llong_mode_assertion_failed + + mov $0x80000001, %eax + cpuid + test $(1 << 29), %edx + jz .Llong_mode_assertion_failed + ret +.Llong_mode_assertion_failed: + push $mesage_long_mode_not_supported + call _panic + +/** + * Assert that the CPU supports the CPUID instruction. + * + * The primary way to check for support of the instruction is to flip the ID + * bin in EFLAGS and then check if this changed was accepted. If so, the CPU + * supports the CPUID instruction, otherwise it most-likely doesn't. + */ +assert_cpuid_instruction_is_supported: + pushfl + pop %eax + mov %eax, %ecx + + xor $(1 << 21), %eax /* Flip the ID bit */ + push %eax /* Move the new bitset on the stack for loading */ + popfl /* Load the flags with ID set back into EFLAGS */ + pushfl /* Copy the flags back onto the stack */ + pop %eax /* Load the flags for further checking */ + + push %ecx + popfl + + cmp %ecx, %eax + je .Lcpuid_assertion_fail + ret +.Lcpuid_assertion_fail: + push $message_cpuid_instruction_no_supported + call _panic + +/** + * Assert that we were loaded by a Multiboot 2 compliant bootloader. + * + * This assertion will panic the system if the magic signature was not found. + * If we were loaded my an appropriate bootloader, this function also saves + * the provided MBI pointer to `multiboot_information_pointer`. + */ +assert_loaded_by_multiboot2_loader: + cmp $0x36d76289, %eax /* Check if we received the + expected magic */ + jne .Lmultiboot2_assertion_fail /* Panic otherwise */ + mov %ebx, multiboot_information_pointer /* Store the MBI pointer */ + ret +.Lmultiboot2_assertion_fail: + push $message_not_loaded_by_multiboot2 + call _panic + +/** + * Enable paging. + * + * Note: This routine expects for there to be a valid set of page maps already + * set up for use. + */ +enable_paging: + mov $page_map_level_4, %eax + mov %eax, %cr3 + + /* Enable Physical Address Extension */ + mov %cr4, %eax + or $(1 << 5), %eax + mov %eax, %cr4 + + /* Enable long mode support */ + mov $0xC0000080, %ecx + rdmsr + or $(1 << 8), %eax + wrmsr + + /* Enable paging */ + mov %cr0, %eax + or $(1 << 31), %eax + mov %eax, %cr0 + + ret + +/** + * Enable use of SSE instructions. + */ +enable_sse: + mov %cr0, %eax + and $0xfffffffb, %eax + or $0x00000002, %eax + mov %eax, %cr0 + + mov %cr4, %eax + or $(3 << 9), %eax + mov %eax, %cr4 + + ret + +/** + * Prepare the page maps. + * + * We map all physical memory we were loaded in plus one additional page. The + * mapping is done in terms of huge pages (2 MiB per page) to save on required + * page map entries. Note that we also map memory both in the low and high + * virtual address ranges, giving us two ways of accessing it. We need to do + * this, because the bootstrapping code lives in low memory, while the rest of + * the kernel will reside on the high end. + */ +prepare_page_maps: + /* Add an entry to the PML4, pointing to the low PML3 */ + mov $page_map_level_3_low, %eax + or $0x3, %eax + mov %eax, (page_map_level_4 + ((0x0000000000100000 >> 39) & 0x1ff) * 8) + + /* Add an entry to the PML4, pointing to the high PML3 */ + mov $page_map_level_3_high, %eax + or $0x3, %eax + mov %eax, (page_map_level_4 + ((0xffffffff80100000 >> 39) & 0x1ff) * 8) + + /* Add an entry to the low PML3, pointing to the low PML2 */ + mov $page_map_level_2_low, %eax + or $0x3, %eax + mov %eax, (page_map_level_3_low + ((0x0000000000100000 >> 30) & 0x1ff) * 8) + + /* Add an entry to the high PML3, pointing to the high PML2 */ + mov $page_map_level_2_high, %eax + or $0x3, %eax + mov %eax, (page_map_level_3_high + ((0xffffffff80100000 >> 30) & 0x1ff) * 8) + + xor %ecx, %ecx + + mov $_end_linear, %esi + shr $21, %esi + add $2, %esi + +.Lmap_pages: + mov $(1 << 21), %eax + mul %ecx + or $((1 << 0) | (1 << 1) | (1 << 7)), %eax + mov %eax, page_map_level_2_low(,%ecx,8) + mov %eax, page_map_level_2_high(,%ecx,8) + + inc %ecx + cmp %esi, %ecx + jne .Lmap_pages + + ret + +.section .boot_text, "ax", @progbits +.code64 + +_transition_to_long_mode: + xor %rax, %rax + mov %rax, %ss + mov %rax, %ds + mov %rax, %es + mov %rax, %fs + mov %rax, %gs + + /* Clear the screen */ + mov $0x0f200f200f200f20, %rax + mov $0x0b8000, %rdi + mov $500, %rcx + rep stosq + + call _init + + call kernel_main + hlt diff --git a/source/arch/x86_64/src/boot/crti.s b/source/arch/x86_64/src/boot/crti.s new file mode 100644 index 0000000..26878fe --- /dev/null +++ b/source/arch/x86_64/src/boot/crti.s @@ -0,0 +1,13 @@ +.code64 + +.section .init +.global _init +_init: + push %rbp + movq %rsp, %rbp + +.section .fini +.global _fini +_fini: + push %rbp + movq %rsp, %rbp diff --git a/source/arch/x86_64/src/boot/crtn.s b/source/arch/x86_64/src/boot/crtn.s new file mode 100644 index 0000000..06fb7ce --- /dev/null +++ b/source/arch/x86_64/src/boot/crtn.s @@ -0,0 +1,9 @@ +.code64 + +.section .init + popq %rbp + ret + +.section .fini + popq %rbp + ret diff --git a/source/arch/x86_64/src/boot/multiboot.s b/source/arch/x86_64/src/boot/multiboot.s new file mode 100644 index 0000000..7ccca56 --- /dev/null +++ b/source/arch/x86_64/src/boot/multiboot.s @@ -0,0 +1,26 @@ +.section .boot_mbh, "a" +.align 8 + +multiboot_header_start: +.Lmagic: + .long 0xe85250d6 +.Larch: + .long 0 +.Llength: + .long multiboot_header_end - multiboot_header_start +.Lchecksum: + .long 0x100000000 - (0xe85250d6 + 0 + (multiboot_header_end - multiboot_header_start)) +.align 8 +.Lflags_start: + .word 4 + .word 1 + .long .Lflags_end - .Lflags_start + .long 3 +.Lflags_end: +.align 8 +.Lend_start: + .word 0 + .word 0 + .long .Lend_end - .Lend_start +.Lend_end: +multiboot_header_end: diff --git a/source/arch/x86_64/src/kernel/main.cpp b/source/arch/x86_64/src/kernel/main.cpp new file mode 100644 index 0000000..9ea756a --- /dev/null +++ b/source/arch/x86_64/src/kernel/main.cpp @@ -0,0 +1,15 @@ +#include "arch/kernel/main.hpp" + +#include "arch/video/vga/text.hpp" + +namespace teachos::arch::kernel +{ + auto main() -> void + { + video::vga::text::write("TeachOS is starting up...", static_cast(0x4f)); + while (true) + { + asm volatile("hlt"); + } + } +} // namespace teachos::arch::kernel diff --git a/source/arch/x86_64/src/video/vga/text.cpp b/source/arch/x86_64/src/video/vga/text.cpp new file mode 100644 index 0000000..11e3b1a --- /dev/null +++ b/source/arch/x86_64/src/video/vga/text.cpp @@ -0,0 +1,29 @@ +#include "arch/video/vga/text.hpp" + +#include "arch/boot/pointers.hpp" +#include "memory/asm_pointer.hpp" + +#include +#include + +namespace teachos::arch::video::vga::text +{ + + namespace + { + auto constinit text_buffer = teachos::boot::asm_pointer{boot::vga_buffer_pointer}; + + auto write(char character, std::byte color) -> void + { + auto & p = *text_buffer; + (*p++) = static_cast(character); + (*p++) = color; + }; + } // namespace + + auto write(std::string_view text, std::byte color) -> void + { + std::ranges::for_each(text, [&](auto character) { write(character, color); }); + } + +} // namespace teachos::arch::video::vga::text \ No newline at end of file diff --git a/source/arch/x86_64/support/grub.cfg.in b/source/arch/x86_64/support/grub.cfg.in new file mode 100644 index 0000000..86674dd --- /dev/null +++ b/source/arch/x86_64/support/grub.cfg.in @@ -0,0 +1,7 @@ +timeout=2 +default=0 + +menuentry "TeachOS" { + multiboot2 /$ + boot +} \ No newline at end of file diff --git a/source/boot/CMakeLists.txt b/source/boot/CMakeLists.txt deleted file mode 100644 index 66f1d65..0000000 --- a/source/boot/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -#[============================================================================[ -# Configure the generic settings for the bootstrapping library. -# -# All the settings (e.g. include paths, linker flags, etc.) applied in this -# directly, are expected to be platform independent. -#]============================================================================] - -add_library("_boot" STATIC) -add_library("teachos::boot" ALIAS "_boot") - -target_include_directories("_boot" PUBLIC - "include" -) - -#[============================================================================[ -# Apply the platform dependent settings to the bootstrapping library. -#]============================================================================] - -add_subdirectory("arch/${CMAKE_SYSTEM_PROCESSOR}") \ No newline at end of file diff --git a/source/boot/arch/x86_64/CMakeLists.txt b/source/boot/arch/x86_64/CMakeLists.txt deleted file mode 100644 index 14b0610..0000000 --- a/source/boot/arch/x86_64/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -target_sources("_boot" PRIVATE - "src/boot.s" - "src/crti.s" - "src/crtn.s" - "src/multiboot.s" -) - -target_include_directories("_boot" PUBLIC - "include" -) \ No newline at end of file diff --git a/source/boot/arch/x86_64/include/boot/pointers.hpp b/source/boot/arch/x86_64/include/boot/pointers.hpp deleted file mode 100644 index 4ef0258..0000000 --- a/source/boot/arch/x86_64/include/boot/pointers.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP -#define TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP - -#include - -namespace teachos::boot::pointers -{ - extern "C" std::byte const multiboot_information_pointer; - extern "C" std::byte * vga_buffer_pointer; -} // namespace teachos::boot - -#endif \ No newline at end of file diff --git a/source/boot/arch/x86_64/src/boot.s b/source/boot/arch/x86_64/src/boot.s deleted file mode 100644 index 45f261e..0000000 --- a/source/boot/arch/x86_64/src/boot.s +++ /dev/null @@ -1,374 +0,0 @@ -.extern _end_physical -.extern _init -.extern kernel_main - - -/** - * Uninitialized data for the bootstrapping process. - */ -.section .boot_bss, "aw", @nobits -.align 4096 - -/** - * Reserve space for the page maps we are going to used during startup. - * - * Note: We are going to use large pages to make the initial mapping code - * simpler. - * - * We need: - * - A single PML 4 (since we will only use 4-level paging) - * - 2 PML 3s (since we need to map high (-2GiB) and low (1+MiB) memory) - * - 2 PML 2s (since we need to map high (-2GiB) and low (1+MiB) memory) - */ - -.global page_map_level_4 -page_map_level_4: .skip 512 * 8 - -.global page_map_level_3_low -page_map_level_3_low: .skip 512 * 8 -.global page_map_level_3_high -page_map_level_3_high: .skip 512 * 8 - -.global page_map_level_2_low -page_map_level_2_low: .skip 512 * 8 -.global page_map_level_2_high -page_map_level_2_high: .skip 512 * 8 - -/** - * Reserve some space for the Multiboot 2 information pointer. - */ -.global multiboot_information_pointer -multiboot_information_pointer: .skip 4 - -/** - * Stack space for the bootstrapping process. - * - * Note: We are going to reserve 1 MiB for now. If/when the kernel requires - * more space to run, it will have to relocate the stack. - */ -.section .boot_stack, "aw", @nobits -.align 16 - -stack_bottom: .skip 1 << 20 -stack_top: - -/** - * Constants for the bootstrapping process. - */ -.section .boot_rodata, "a", @progbits - -/** - * A valid Global Descriptor Table is still required in long mode. However, we - * only need a single entry for the "code segment", so we will setup a single - * segment table below. - * - * Bit 43: "E" in the access byte => mark the segment as executable. - * Bit 44: "S" in the access byte => mark the segment as code or data. - * Bit 47: "P" in the access byte => mark the segment as being present. - * Bit 53: "L" in the flags byte => mark the segment as being for long mode - */ - -global_descriptor_table: .quad 0 -global_descriptor_table_code = . - global_descriptor_table -.quad (1<<43) | (1<<44) | (1<<47) | (1<<53) - -/** - * We also need a pointer that we can load into the GDTR. - * - * The pointer consists of a word describing the size of the table minus 1 and - * the pointer to the actual table. - */ -global_descriptor_table_pointer: -.word . - global_descriptor_table - 1 -.quad global_descriptor_table - -/** - * We are going to print some messages in case we panic during boot, so we are - * going to store them here as well - */ -message_prefix_panic: -.string "TeachOS Panic: " -message_not_loaded_by_multiboot2: -.string "The operating system was not loaded by a Multiboot 2 loader." -message_cpuid_instruction_no_supported: -.string "The 'cpuid' instruction is not supported on this platform." -mesage_long_mode_not_supported: -.string "Long mode is not supported by this platform." - -/** - * Mutable data for the bootstrapping process. - */ -.section .boot_data, "aw", @progbits - -/** - * We need a pointer to our current position in the VGA text buffer. - */ -.global vga_buffer_pointer -vga_buffer_pointer: .long 0xb8000 - -/** - * Code for the bootstrapping process. - */ -.section .boot_text, "ax", @progbits -.align 16 -.code32 - -/** - * Print a given panic message and then halt the machine. - * - * Parameters: - * - [stack - 0] message: the message to print - */ -_panic: - push %ebp - mov %esp, %ebp - - push message_prefix_panic - push $0x4f - call _print - add $8, %esp - - push 8(%ebp) - push 0x4f - call _print - add $8, %esp - - hlt - -/** - * Print a message via the VGA buffer. - * - * Parameters: - * - [stack - 4] message: the message to print - * - [stack - 0] color: the color of the message - */ -_print: - push %ebp - mov %esp, %ebp - - push %ebx - push %esi - mov 8(%ebp), %eax - mov 12(%ebp), %ebx - mov $0, %ecx - mov (vga_buffer_pointer), %esi - -.Lprint_loop: - mov (%ebx, %ecx), %dl - test %dl, %dl - je .Lupdate_vga_buffer_address - mov %dl, (%esi, %ecx, 2) - mov %al, 1(%esi, %ecx, 2) - inc %ecx - jmp .Lprint_loop - -.Lupdate_vga_buffer_address: - shl $1, %ecx - add %ecx, (vga_buffer_pointer) - -.Lprint_end: - pop %esi - pop %ebx - mov %ebp, %esp - pop %ebp - ret - -/** - * This is our entry point after being loaded by the bootloader. - * - * Having this in assembly makes it easier for us to keep things together. - */ -.global _start -_start: - mov $stack_top, %esp - mov %esp, %ebp - - call assert_loaded_by_multiboot2_loader - call assert_cpuid_instruction_is_supported - call assert_cpu_supports_long_mode - call prepare_page_maps - call enable_paging - call enable_sse - - lgdt (global_descriptor_table_pointer) - jmp $global_descriptor_table_code,$_transition_to_long_mode - - hlt - -/** - * Assert that the CPU supports going into long mode. - */ -assert_cpu_supports_long_mode: - mov $0x80000000, %eax - cpuid - cmp $0x80000001, %eax - jb .Llong_mode_assertion_failed - - mov $0x80000001, %eax - cpuid - test $(1 << 29), %edx - jz .Llong_mode_assertion_failed - ret -.Llong_mode_assertion_failed: - push $mesage_long_mode_not_supported - call _panic - -/** - * Assert that the CPU supports the CPUID instruction. - * - * The primary way to check for support of the instruction is to flip the ID - * bin in EFLAGS and then check if this changed was accepted. If so, the CPU - * supports the CPUID instruction, otherwise it most-likely doesn't. - */ -assert_cpuid_instruction_is_supported: - pushfl - pop %eax - mov %eax, %ecx - - xor $(1 << 21), %eax /* Flip the ID bit */ - push %eax /* Move the new bitset on the stack for loading */ - popfl /* Load the flags with ID set back into EFLAGS */ - pushfl /* Copy the flags back onto the stack */ - pop %eax /* Load the flags for further checking */ - - push %ecx - popfl - - cmp %ecx, %eax - je .Lcpuid_assertion_fail - ret -.Lcpuid_assertion_fail: - push $message_cpuid_instruction_no_supported - call _panic - -/** - * Assert that we were loaded by a Multiboot 2 compliant bootloader. - * - * This assertion will panic the system if the magic signature was not found. - * If we were loaded my an appropriate bootloader, this function also saves - * the provided MBI pointer to `multiboot_information_pointer`. - */ -assert_loaded_by_multiboot2_loader: - cmp $0x36d76289, %eax /* Check if we received the - expected magic */ - jne .Lmultiboot2_assertion_fail /* Panic otherwise */ - mov %ebx, multiboot_information_pointer /* Store the MBI pointer */ - ret -.Lmultiboot2_assertion_fail: - push $message_not_loaded_by_multiboot2 - call _panic - -/** - * Enable paging. - * - * Note: This routine expects for there to be a valid set of page maps already - * set up for use. - */ -enable_paging: - mov $page_map_level_4, %eax - mov %eax, %cr3 - - /* Enable Physical Address Extension */ - mov %cr4, %eax - or $(1 << 5), %eax - mov %eax, %cr4 - - /* Enable long mode support */ - mov $0xC0000080, %ecx - rdmsr - or $(1 << 8), %eax - wrmsr - - /* Enable paging */ - mov %cr0, %eax - or $(1 << 31), %eax - mov %eax, %cr0 - - ret - -/** - * Enable use of SSE instructions. - */ -enable_sse: - mov %cr0, %eax - and $0xfffffffb, %eax - or $0x00000002, %eax - mov %eax, %cr0 - - mov %cr4, %eax - or $(3 << 9), %eax - mov %eax, %cr4 - - ret - -/** - * Prepare the page maps. - * - * We map all physical memory we were loaded in plus one additional page. The - * mapping is done in terms of huge pages (2 MiB per page) to save on required - * page map entries. Note that we also map memory both in the low and high - * virtual address ranges, giving us two ways of accessing it. We need to do - * this, because the bootstrapping code lives in low memory, while the rest of - * the kernel will reside on the high end. - */ -prepare_page_maps: - /* Add an entry to the PML4, pointing to the low PML3 */ - mov $page_map_level_3_low, %eax - or $0x3, %eax - mov %eax, (page_map_level_4 + ((0x0000000000100000 >> 39) & 0x1ff) * 8) - - /* Add an entry to the PML4, pointing to the high PML3 */ - mov $page_map_level_3_high, %eax - or $0x3, %eax - mov %eax, (page_map_level_4 + ((0xffffffff80100000 >> 39) & 0x1ff) * 8) - - /* Add an entry to the low PML3, pointing to the low PML2 */ - mov $page_map_level_2_low, %eax - or $0x3, %eax - mov %eax, (page_map_level_3_low + ((0x0000000000100000 >> 30) & 0x1ff) * 8) - - /* Add an entry to the high PML3, pointing to the high PML2 */ - mov $page_map_level_2_high, %eax - or $0x3, %eax - mov %eax, (page_map_level_3_high + ((0xffffffff80100000 >> 30) & 0x1ff) * 8) - - xor %ecx, %ecx - - mov $_end_linear, %esi - shr $21, %esi - add $2, %esi - -.Lmap_pages: - mov $(1 << 21), %eax - mul %ecx - or $((1 << 0) | (1 << 1) | (1 << 7)), %eax - mov %eax, page_map_level_2_low(,%ecx,8) - mov %eax, page_map_level_2_high(,%ecx,8) - - inc %ecx - cmp %esi, %ecx - jne .Lmap_pages - - ret - -.section .boot_text, "ax", @progbits -.code64 - -_transition_to_long_mode: - xor %rax, %rax - mov %rax, %ss - mov %rax, %ds - mov %rax, %es - mov %rax, %fs - mov %rax, %gs - - /* Clear the screen */ - mov $0x0f200f200f200f20, %rax - mov $0x0b8000, %rdi - mov $500, %rcx - rep stosq - - call _init - - call kernel_main - hlt diff --git a/source/boot/arch/x86_64/src/crti.s b/source/boot/arch/x86_64/src/crti.s deleted file mode 100644 index 26878fe..0000000 --- a/source/boot/arch/x86_64/src/crti.s +++ /dev/null @@ -1,13 +0,0 @@ -.code64 - -.section .init -.global _init -_init: - push %rbp - movq %rsp, %rbp - -.section .fini -.global _fini -_fini: - push %rbp - movq %rsp, %rbp diff --git a/source/boot/arch/x86_64/src/crtn.s b/source/boot/arch/x86_64/src/crtn.s deleted file mode 100644 index 06fb7ce..0000000 --- a/source/boot/arch/x86_64/src/crtn.s +++ /dev/null @@ -1,9 +0,0 @@ -.code64 - -.section .init - popq %rbp - ret - -.section .fini - popq %rbp - ret diff --git a/source/boot/arch/x86_64/src/multiboot.s b/source/boot/arch/x86_64/src/multiboot.s deleted file mode 100644 index 7ccca56..0000000 --- a/source/boot/arch/x86_64/src/multiboot.s +++ /dev/null @@ -1,26 +0,0 @@ -.section .boot_mbh, "a" -.align 8 - -multiboot_header_start: -.Lmagic: - .long 0xe85250d6 -.Larch: - .long 0 -.Llength: - .long multiboot_header_end - multiboot_header_start -.Lchecksum: - .long 0x100000000 - (0xe85250d6 + 0 + (multiboot_header_end - multiboot_header_start)) -.align 8 -.Lflags_start: - .word 4 - .word 1 - .long .Lflags_end - .Lflags_start - .long 3 -.Lflags_end: -.align 8 -.Lend_start: - .word 0 - .word 0 - .long .Lend_end - .Lend_start -.Lend_end: -multiboot_header_end: diff --git a/source/boot/include/boot/asm_pointer.hpp b/source/boot/include/boot/asm_pointer.hpp deleted file mode 100644 index ec7141e..0000000 --- a/source/boot/include/boot/asm_pointer.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef TEACHOS_BOOT_ASM_POINTER_HPP -#define TEACHOS_BOOT_ASM_POINTER_HPP - -namespace teachos::boot -{ - - template - struct asm_pointer - { - constexpr asm_pointer(Type & pointer) - : m_pointer{&pointer} - { - } - - auto constexpr operator->() -> Type * { return m_pointer; } - auto constexpr operator->() const -> Type const * { return m_pointer; } - auto constexpr operator*() -> Type & { return *m_pointer; } - auto constexpr operator*() const -> Type const & { return *m_pointer; } - - private: - Type * m_pointer; - }; - - template - struct asm_pointer - { - constexpr asm_pointer(Type const & pointer) - : m_pointer{&pointer} - { - } - - auto constexpr operator->() -> Type const * { return m_pointer; } - auto constexpr operator->() const -> Type const * { return m_pointer; } - auto constexpr operator*() -> Type const & { return *m_pointer; } - auto constexpr operator*() const -> Type const & { return *m_pointer; } - - private: - Type const * m_pointer; - }; - -} // namespace teachos::boot - -#endif \ No newline at end of file diff --git a/source/include/memory/asm_pointer.hpp b/source/include/memory/asm_pointer.hpp new file mode 100644 index 0000000..ec7141e --- /dev/null +++ b/source/include/memory/asm_pointer.hpp @@ -0,0 +1,43 @@ +#ifndef TEACHOS_BOOT_ASM_POINTER_HPP +#define TEACHOS_BOOT_ASM_POINTER_HPP + +namespace teachos::boot +{ + + template + struct asm_pointer + { + constexpr asm_pointer(Type & pointer) + : m_pointer{&pointer} + { + } + + auto constexpr operator->() -> Type * { return m_pointer; } + auto constexpr operator->() const -> Type const * { return m_pointer; } + auto constexpr operator*() -> Type & { return *m_pointer; } + auto constexpr operator*() const -> Type const & { return *m_pointer; } + + private: + Type * m_pointer; + }; + + template + struct asm_pointer + { + constexpr asm_pointer(Type const & pointer) + : m_pointer{&pointer} + { + } + + auto constexpr operator->() -> Type const * { return m_pointer; } + auto constexpr operator->() const -> Type const * { return m_pointer; } + auto constexpr operator*() -> Type const & { return *m_pointer; } + auto constexpr operator*() const -> Type const & { return *m_pointer; } + + private: + Type const * m_pointer; + }; + +} // namespace teachos::boot + +#endif \ No newline at end of file diff --git a/source/kernel/CMakeLists.txt b/source/kernel/CMakeLists.txt deleted file mode 100644 index bc60f6c..0000000 --- a/source/kernel/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -#[============================================================================[ -# Configure the generic settings for the kernel image. -# -# All the settings (e.g. include paths, linker flags, etc.) applied in this -# directly, are expected to be platform independent. -#]============================================================================] - -add_executable("kernel") - -target_compile_options("kernel" PRIVATE - "$<$:-Wall>" - "$<$:-Wextra>" - "$<$:-Werror>" - "$<$:-pedantic-errors>" -) - -set_target_properties("kernel" PROPERTIES - INTERPROCEDURAL_OPTIMIZATION YES -) - -#[============================================================================[ -# Apply the platform dependent settings to the kernel image. -#]============================================================================] - -add_subdirectory("arch/${CMAKE_SYSTEM_PROCESSOR}") \ No newline at end of file diff --git a/source/kernel/arch/x86_64/CMakeLists.txt b/source/kernel/arch/x86_64/CMakeLists.txt deleted file mode 100644 index ffce50c..0000000 --- a/source/kernel/arch/x86_64/CMakeLists.txt +++ /dev/null @@ -1,58 +0,0 @@ -#[============================================================================[ -# x86_64 specific configuration for the kernel image. -#]============================================================================] - -set(TEACHOS_KERNEL_LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/kern.ld") -mark_as_advanced(TEACHOS_KERNEL_LINKER_SCRIPT) - -target_sources("kernel" PRIVATE - "src/entry.cpp" - "src/vga.cpp" -) - -target_include_directories("kernel" PRIVATE - "include" -) - -target_link_options("kernel" PRIVATE - "-T${TEACHOS_KERNEL_LINKER_SCRIPT}" -) - -target_link_libraries("kernel" PRIVATE - "-Wl,--whole-archive" - "teachos::boot" - "-Wl,--no-whole-archive" -) - -set_target_properties("kernel" PROPERTIES - LINK_DEPENDS "${TEACHOS_KERNEL_LINKER_SCRIPT}" -) - -#[============================================================================[ -# Bootable ISO image generation -#]============================================================================] - -find_package("grub-mkrescue") - -if(grub-mkrescue_FOUND) - set(ISO_FILE "${PROJECT_BINARY_DIR}/teachos.iso") - - file(GENERATE - OUTPUT "isofs/boot/grub/grub.cfg" - INPUT "support/grub.cfg.in" - ) - - add_custom_target("bootable-iso" - COMMAND "${GRUB_MKRESCUE_EXE}" - "-o" - "${ISO_FILE}" - "${CMAKE_CURRENT_BINARY_DIR}/isofs" - "$" - "2>/dev/null" - DEPENDS - "$" - "isofs/boot/grub/grub.cfg" - BYPRODUCTS "${ISO_FILE}" - COMMENT "Creating bootable ISO image" - ) -endif() \ No newline at end of file diff --git a/source/kernel/arch/x86_64/include/kernel/vga.hpp b/source/kernel/arch/x86_64/include/kernel/vga.hpp deleted file mode 100644 index ee5a808..0000000 --- a/source/kernel/arch/x86_64/include/kernel/vga.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef TEACHOS_KERNEL_VGA_HPP -#define TEACHOS_KERNEL_VGA_HPP - -#include - -namespace teachos::kernel::vga -{ - auto write(std::string_view text, std::byte color) -> void; -} - -#endif \ No newline at end of file diff --git a/source/kernel/arch/x86_64/kern.ld b/source/kernel/arch/x86_64/kern.ld deleted file mode 100644 index 78cc363..0000000 --- a/source/kernel/arch/x86_64/kern.ld +++ /dev/null @@ -1,139 +0,0 @@ -ENTRY(_start) - -/***************************************************************************** - * Virtual and linear start addresses of the TeachOS kernel - *****************************************************************************/ -TEACHOS_HIGH = -2048M; -TEACHOS_LOW = 1M; - -PHDRS { - boot_rodata PT_LOAD FLAGS(4); - boot_text PT_LOAD FLAGS(5); - boot_data PT_LOAD FLAGS(6); - - text PT_LOAD FLAGS(5); - data PT_LOAD FLAGS(6); - rodata PT_LOAD FLAGS(4); -} - -SECTIONS -{ - /*************************************************************************** - * Load the bootstrap code into low memory. We need to be accessible in - * 32-Bit mode, so we want to live down low, but we need to leave the 1MiB - * hole open since some BIOS functionality resides below it. - ***************************************************************************/ - . = TEACHOS_LOW; - - /*************************************************************************** - * We want to be able to be able to access all memory (linear and virtual) - * during bootstrapping and operation. To achieve this, we define some - * symbols at the beginning. - ***************************************************************************/ - _start_linear = .; - _start_virtual = . + TEACHOS_HIGH; - - /*************************************************************************** - * The bootstrapping infratructure goes first. We first place the read-only - * data, followed by our code, initialized mutable data, and finally our - * uninitialized mutable data. - ***************************************************************************/ - .boot_rodata : - { - KEEP(*(.boot_mbh)) - *(.boot_rodata) - } :boot_rodata - - .boot_text : - { - *(.boot_text) - } :boot_text - - .boot_data : - { - *(.boot_data) - } :boot_data - - .boot_bss : - { - *(.boot_bss) - *(.boot_stack) - } - - /*************************************************************************** - * Now it is time to load the 64-bit kernel code. We virtually load it into - * the upper 2GiB, while adjusting the linear load address appropriately. We - * also make sure to align the loaded data onto a page boundary. - ***************************************************************************/ - . = ALIGN(4K); - . += TEACHOS_HIGH; - - .init ALIGN(4K) : AT(ADDR (.init) - TEACHOS_HIGH) - { - /* - * Make sure that the crt code is wrapped around the compiler generated - * initialization code. - */ - KEEP(*:crti.s.obj(.init)) - KEEP(*(EXCLUDE_FILE (*crti.s.obj crtn.s.obj) .init)) - KEEP(*:crtn.s.obj(.init)) - } :text - - .fini ALIGN(4K) : AT(ADDR (.fini) - TEACHOS_HIGH) - { - /* - * Make sure that the crt code is wrapped around the compiler generated - * finalizer code. - */ - KEEP(*:crti.s.obj(.fini)) - KEEP(*(EXCLUDE_FILE (*crti.s.obj crtn.s.obj).fini)) - KEEP(*:crtn.s.obj(.fini)) - } - - .text ALIGN(4K) : AT(ADDR (.text) - TEACHOS_HIGH) - { - *(.text*) - } - - .rodata ALIGN(4K) : AT (ADDR (.rodata) - TEACHOS_HIGH) - { - *(.rodata) - *(.rodata.*) - } :rodata - - .ctors ALIGN(4K) : AT (ADDR (.ctors) - TEACHOS_HIGH) - { - KEEP(*crtbegin.o(.ctors)) - KEEP(*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP(*(SORT(.ctors.*))) - KEEP(*crtend.o(.ctors)) - } :data - - .dtors ALIGN(4K) : AT (ADDR (.dtors) - TEACHOS_HIGH) - { - KEEP(*crtbegin.o(.dtors)) - KEEP(*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP(*(SORT(.dtors.*))) - KEEP(*crtend.o(.dtors)) - } - - .data ALIGN(4K) : AT (ADDR (.data) - TEACHOS_HIGH) - { - *(.data*) - } - - .bss ALIGN(4K) : AT (ADDR (.bss) - TEACHOS_HIGH) - { - *(COMMON) - *(.bss*) - } - - /*************************************************************************** - * In accordance with the symbol definitions at the start, we generate some - * symbols to mark the end of our loaded image. - ***************************************************************************/ - _end_virtual = ADDR(.bss) + SIZEOF(.bss); - _end_linear = _end_virtual - TEACHOS_HIGH; - - /DISCARD/ : { *(.comment) } -} diff --git a/source/kernel/arch/x86_64/src/entry.cpp b/source/kernel/arch/x86_64/src/entry.cpp deleted file mode 100644 index fd9d9d0..0000000 --- a/source/kernel/arch/x86_64/src/entry.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "kernel/vga.hpp" - -namespace teachos::kernel -{ - extern "C" auto kernel_main() -> void - { - vga::write("TeachOS is starting up...", static_cast(0x4f)); - } -} // namespace teachos diff --git a/source/kernel/arch/x86_64/src/vga.cpp b/source/kernel/arch/x86_64/src/vga.cpp deleted file mode 100644 index efa2848..0000000 --- a/source/kernel/arch/x86_64/src/vga.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "kernel/vga.hpp" - -#include "boot/asm_pointer.hpp" -#include "boot/pointers.hpp" - -#include -#include - -namespace teachos::kernel::vga -{ - - namespace - { - auto constinit text_buffer_pointer = boot::asm_pointer{boot::pointers::vga_buffer_pointer}; - - auto write(char character, std::byte color) -> void - { - auto & p = *text_buffer_pointer; - (*p++) = static_cast(character); - (*p++) = color; - }; - } // namespace - - auto write(std::string_view text, std::byte color) -> void - { - std::ranges::for_each(text, [&](auto character) { write(character, color); }); - } - -} // namespace teachos::kernel::vga \ No newline at end of file diff --git a/source/kernel/arch/x86_64/support/grub.cfg.in b/source/kernel/arch/x86_64/support/grub.cfg.in deleted file mode 100644 index 49f19ce..0000000 --- a/source/kernel/arch/x86_64/support/grub.cfg.in +++ /dev/null @@ -1,7 +0,0 @@ -timeout=2 -default=0 - -menuentry "TeachOS" { - multiboot2 /$ - boot -} \ No newline at end of file diff --git a/source/src/kernel/main.cpp b/source/src/kernel/main.cpp new file mode 100644 index 0000000..07a9955 --- /dev/null +++ b/source/src/kernel/main.cpp @@ -0,0 +1,3 @@ +#include "arch/kernel/main.hpp" + +extern "C" auto kernel_main() -> void { teachos::arch::kernel::main(); } \ No newline at end of file -- cgit v1.2.3