#include #include #include #include #include #include #include #include #include #include #include #include #include "driver/timer.hpp" #include "driver/keyboard.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; VMMContext * kernelContext; static void initializePMM(Structure const & data) { 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)); // Mark the video memory as used. PMM::markUsed(physical_t(0xB8000)); } extern "C" void init(Structure const & data) { Console::main.clear(); 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"; initializePMM(data); 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(); Console::main << "Drivers installed.\n"; ASM::sti(); Console::main << "Interrupts enabled.\n"; while(true); } static_assert(sizeof(void*) == 4, "Target platform is not 32 bit.");