/* Check if the compiler thinks you are targeting the wrong operating system. */ #if defined(__linux__) #error "You are not using a cross-compiler" #endif /* This tutorial will only work for the 32-bit ix86 targets. */ #if !defined(__i386__) #error "This tutorial needs to be compiled with a ix86-elf compiler" #endif #include #include #include "allocator.h" #include "cga.h" #include "cpu/cpu.h" #include "gdt.h" #include "idt.h" #include "keyboard.h" #include "scheduler.h" #include "serial.h" #include "vmm.h" /* hardware */ vmm kvmm; #include "hardware.h" char buffer[4096]; uint32_t check_multiboot(uint32_t, uint32_t); extern "C" { void dump_multiboot(uint32_t mb_magic, uint32_t mb_addr); void dump_gdt(); [[noreturn]] 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); #endif #ifdef HAS_VIDEO0 if (const auto cga_buffer_r = kvmm.map(0xb8000, 0xc03f3000)) { video0.set_buffer(cga_buffer_r.value()); if constexpr (video0_console) Console::set(&video0); } #endif printk("Hello, kernel World!\n"); CPU core0; printk("cpuid: ", core0.manufacturer(), " family ", core0.family(), " model ", core0.model(), " stepping ", core0.stepping(), '\n'); runtime_assert(core0.features().fpu, "CPU lacks fpu"); runtime_assert(core0.features().cx8, "CPU lacks cx8"); dump_address(); dump_gdt(); { 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"); 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"); 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_); if (mb_addr_r) kvmm.unmap(mb_addr_r.value()); if (mb_addr_re) kvmm.unmap(mb_addr_re.value()); } GDT gdt; IDT idt{gdt.descriptor(GDT::kcode)}; // Scheduler s{gdt.descriptor(GDT::kcode)}; Keyboard kb; MemoryAllocator ma(reinterpret_cast(buffer), sizeof(buffer)); printk("memory free: ", ma.free_space(), '\n'); idt.enable(); while (true) asm volatile("hlt"); } } // extern "C"