#include "console.hpp" #include "pmm.hpp" #include "numeric.hpp" #include "pointer.hpp" #include "multiboot.hpp" #include "gdt.hpp" #include "idt.hpp" #include "compat.h" #include "io.hpp" #include "vmm.hpp" #include "driver/timer.hpp" #include "driver/keyboard.hpp" #include "driver/scheduler.hpp" #include #include using namespace multiboot; using namespace console_tools; struct dummy; // Symbols generated by linker, no useful content in there... extern dummy kernelStartMarker; extern dummy kernelEndMarker; driver::Timer timer; driver::Keyboard keyboardDriver; driver::Scheduler scheduler; VMMContext *kernelContext; void run_program0(Module const & module) { for(uint32_t ptr = 0; ptr < module.size(); ptr += 0x1000) { kernelContext->provide( virtual_t(0x40000000 + ptr), VMMFlags::Writable | VMMFlags::UserSpace); } char * src = module.start.data(); char * dst = (char*)0x40000000; for(uint32_t ptr = 0; ptr < module.size(); ptr++) { dst[ptr] = src[ptr]; } using EntryPoint = void (*)(); EntryPoint ep = (EntryPoint)0x40000000; ep(); } extern "C" void init(Structure const & data) { Console::main << "Hello World!\n" << FColor(Color::Yellow) << "Hello color!" << FColor() << "\n" << BColor(Color::Blue) << "Hello blue!" << BColor() << "\n" << "Hello default color.\n"; GDT::initialize(); Console::main << "bootloader name: " << data.bootLoaderName << "\n" << "command line: " << data.commandline << "\n" << "count of modules: " << data.modules.length << "\n" << "count of mmaps: " << data.memoryMaps.length << "\n"; for(auto &mmap : data.memoryMaps) { if(mmap.length == 0) { continue; } if(mmap.isFree() == false) { continue; } Console::main << "mmap: " << "start: " << hex(mmap.base) << ", length: " << hex(mmap.length) << ", " << mmap.entry_size << ", " << sizeof(mmap) << "\n"; if(mmap.base > 0xFFFFFFFF) { Console::main << "mmap out of 4 gigabyte range." << "\n"; continue; } if(mmap.isFree()) { // Mark all free memory free... physical_t lower = physical_t(mmap.base).alignUpper(4096); physical_t upper = physical_t(mmap.base + mmap.length).alignLower(4096); uint32_t ptr = lower.numeric(); while (ptr < upper.numeric()) { PMM::markFree(physical_t(ptr)); ptr += 0x1000; } } } // Mark all memory used by the kernel used... physical_t lower = physical_t(&kernelStartMarker).alignLower(4096); physical_t upper = physical_t(&kernelEndMarker).alignUpper(4096); uint32_t ptr = lower.numeric(); while (ptr < upper.numeric()) { PMM::markUsed(physical_t(ptr)); ptr += 0x1000; } // nullptr is not valid. PMM::markUsed(physical_t(nullptr)); auto freeMemory = PMM::getFreeMemory(); Console::main << "Free: " << (freeMemory >> 20) << "MB, " << (freeMemory >> 10) << "KB, " << (freeMemory >> 0) << "B, " << (freeMemory >> 12) << "Pages\n"; IDT::initialize(); Console::main << "Interrupts set up.\n"; Console::main << "Creating VMM Context...\n"; kernelContext = new (PMM::alloc().data()) VMMContext(); Console::main << "Mapping memory...\n"; for(uint32_t addr = 0; addr < 4096 * 1024; addr += 0x1000) { kernelContext->map( virtual_t(addr), physical_t(addr), VMMFlags::Writable | VMMFlags::UserSpace); } kernelContext->map( virtual_t(kernelContext), physical_t(kernelContext), VMMFlags::Writable); Console::main << "Active Context...\n"; VMM::activate(*kernelContext); Console::main << "Active Paging...\n"; VMM::enable(); Console::main << "Virtual Memory Management ready.\n"; timer.install(); keyboardDriver.install(); scheduler.install(); Console::main << "Drivers installed.\n"; asm volatile("sti"); Console::main << "Interrupts enabled.\n"; if(data.modules.length > 0) { run_program0(data.modules[0]); } while(true); } static_assert(sizeof(void*) == 4, "Target platform is not 32 bit.");