extern "C" void multiboot_main(unsigned int magic, void* mbi) { // 0x00000000 - 0x000003FF - Interrupt Vector Table // 0x00000400 - 0x000004FF - BIOS Data Area (BDA) // 0x00000500 - 0x000005FF - ROM BASIC (still used / reclaimed by some BIOS) g_memoryMap.AddBytes(MemoryType_Bootloader, 0, 0, 0x600); // Process multiboot info bool gotMultibootInfo = false; // Add bootloader (ourself) to memory map extern const char ImageBase[]; extern const char ImageEnd[]; const physaddr_t start = (physaddr_t)&ImageBase; const physaddr_t end = (physaddr_t)&ImageEnd; g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, start, end - start); if (magic == MULTIBOOT_BOOTLOADER_MAGIC && mbi) { ProcessMultibootInfo(static_cast<multiboot_info*>(mbi)); gotMultibootInfo = true; } else if (magic== MULTIBOOT2_BOOTLOADER_MAGIC && mbi) { ProcessMultibootInfo(static_cast<multiboot2_info*>(mbi)); gotMultibootInfo = true; } // Now that the memory allocator is initialized, we can create GraphicsConsole if (gotMultibootInfo) { if (g_frameBuffer.format != PIXFMT_UNKNOWN) { g_graphicsConsole.Initialize(&g_frameBuffer); g_console = &g_graphicsConsole; Framebuffer* fb = &g_bootInfo.framebuffers[g_bootInfo.framebufferCount]; fb->width = g_frameBuffer.width; fb->height = g_frameBuffer.height; fb->pitch = g_frameBuffer.pitch; fb->format = g_frameBuffer.format; fb->pixels = (uintptr_t)g_frameBuffer.pixels; g_bootInfo.framebufferCount += 1; } else if (!g_console) { // // Assume a standard VGA card at 0xB8000 // g_vgaConsole.Initialize((void*)0x000B8000, 80, 25); // g_console = &g_vgaConsole; } } g_console->Rainbow(); Log(" BIOS Bootloader (" STRINGIZE(KERNEL_ARCH) ")\n\n"); if (gotMultibootInfo) { // InstallBiosTrampoline(); // g_display.Initialize(); // for (int i = 0; i != g_display.GetModeCount(); ++i) // { // DisplayMode mode; // g_display.GetMode(i, &mode); // if (mode.format == PIXFMT_X8R8G8B8) // { // //Log("Mode %d: %d x %d - %d\n", i, mode.width, mode.height, mode.format); // } // } // Boot! Boot((void*)g_bootInfo.initrdAddress, g_bootInfo.initrdSize); } else { Fatal(" No multiboot information!\n"); } }
static void ProcessMultibootInfo(multiboot_info const * const mbi) { // Add multiboot data header g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, (uintptr_t)mbi, sizeof(*mbi)); if (mbi->flags & MULTIBOOT_MEMORY_INFO) { // Add memory map itself g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, mbi->mmap_addr, mbi->mmap_length); const multiboot_mmap_entry* entry = (multiboot_mmap_entry*)mbi->mmap_addr; const multiboot_mmap_entry* end = (multiboot_mmap_entry*)(mbi->mmap_addr + mbi->mmap_length); while (entry < end) { MemoryType type; uint32_t flags; switch (entry->type) { case MULTIBOOT_MEMORY_AVAILABLE: type = MemoryType_Available; flags = 0; break; case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: type = MemoryType_AcpiReclaimable; flags = 0; break; case MULTIBOOT_MEMORY_NVS: type = MemoryType_AcpiNvs; flags = 0; break; case MULTIBOOT_MEMORY_BADRAM: type = MemoryType_Unusable; flags = 0; break; case MULTIBOOT_MEMORY_RESERVED: default: type = MemoryType_Reserved; flags = 0; break; } g_memoryMap.AddBytes(type, flags, entry->addr, entry->len); // Go to next entry entry = (multiboot_mmap_entry*) ((uintptr_t)entry + entry->size + sizeof(entry->size)); } } else if (mbi->flags & MULTIBOOT_INFO_MEMORY) { g_memoryMap.AddBytes(MemoryType_Available, 0, 0, (uint64_t)mbi->mem_lower * 1024); g_memoryMap.AddBytes(MemoryType_Available, 0, 1024*1024, (uint64_t)mbi->mem_upper * 1024); } if (mbi->flags & MULTIBOOT_INFO_MODS) { const multiboot_module* modules = (multiboot_module*)mbi->mods_addr; for (uint32_t i = 0; i != mbi->mods_count; ++i) { const multiboot_module* module = &modules[i]; if (strcmp(module->string, "initrd")==0) { g_bootInfo.initrdAddress = module->mod_start; g_bootInfo.initrdSize = module->mod_end - module->mod_start; } g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, module->mod_start, module->mod_end - module->mod_start); } } if (mbi->flags & MULTIBOOT_INFO_FRAMEBUFFER_INFO) { switch (mbi->framebuffer_type) { case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: { const auto redMask = ((1 << mbi->framebuffer_red_mask_size) - 1) << mbi->framebuffer_red_field_position; const auto greenMask = ((1 << mbi->framebuffer_green_mask_size) - 1) << mbi->framebuffer_green_field_position; const auto blueMask = ((1 << mbi->framebuffer_blue_mask_size) - 1) << mbi->framebuffer_blue_field_position; const auto pixelMask = mbi->framebuffer_bpp < 32 ? (1 << mbi->framebuffer_bpp) - 1 : -1; const auto reservedMask = pixelMask ^ redMask ^ greenMask ^ blueMask; g_frameBuffer.width = mbi->framebuffer_width; g_frameBuffer.height = mbi->framebuffer_height; g_frameBuffer.pitch = mbi->framebuffer_pitch; g_frameBuffer.pixels = (void*)mbi->framebuffer_addr; g_frameBuffer.format = DeterminePixelFormat(redMask, greenMask, blueMask, reservedMask); } break; case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: { // OK to initialize VgaConsole here since it doesn't allocate any memory // g_vgaConsole.Initialize((void*)mbi->framebuffer_addr, mbi->framebuffer_width, mbi->framebuffer_height); // g_console = &g_vgaConsole; } break; } } }
static void ProcessMultibootInfo(multiboot2_info const * const mbi) { // Add multiboot data header g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, (uintptr_t)mbi, mbi->total_size); const multiboot2_tag_basic_meminfo* meminfo = NULL; const multiboot2_tag_mmap* mmap = NULL; for (multiboot2_tag* tag = (multiboot2_tag*)(mbi + 1); tag->type != MULTIBOOT2_TAG_TYPE_END; tag = (multiboot2_tag*) align_up((uintptr_t)tag + tag->size, MULTIBOOT2_TAG_ALIGN)) { switch (tag->type) { case MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO: meminfo = (multiboot2_tag_basic_meminfo*)tag; break; case MULTIBOOT2_TAG_TYPE_MMAP: mmap = (multiboot2_tag_mmap*)tag; break; case MULTIBOOT2_TAG_TYPE_MODULE: { const multiboot2_module* module = (multiboot2_module*)tag; if (strcmp(module->string, "initrd")==0) { g_bootInfo.initrdAddress = module->mod_start; g_bootInfo.initrdSize = module->mod_end - module->mod_start; } g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, module->mod_start, module->mod_end - module->mod_start); } break; case MULTIBOOT2_TAG_TYPE_FRAMEBUFFER: { const multiboot2_tag_framebuffer* mbi = (multiboot2_tag_framebuffer*)tag; switch (mbi->common.framebuffer_type) { case MULTIBOOT2_FRAMEBUFFER_TYPE_RGB: { const auto redMask = ((1 << mbi->framebuffer_red_mask_size) - 1) << mbi->framebuffer_red_field_position; const auto greenMask = ((1 << mbi->framebuffer_green_mask_size) - 1) << mbi->framebuffer_green_field_position; const auto blueMask = ((1 << mbi->framebuffer_blue_mask_size) - 1) << mbi->framebuffer_blue_field_position; const auto pixelMask = mbi->common.framebuffer_bpp < 32 ? (1 << mbi->common.framebuffer_bpp) - 1 : -1; const auto reservedMask = pixelMask ^ redMask ^ greenMask ^ blueMask; g_frameBuffer.width = mbi->common.framebuffer_width; g_frameBuffer.height = mbi->common.framebuffer_height; g_frameBuffer.pitch = mbi->common.framebuffer_pitch; g_frameBuffer.pixels = (void*)mbi->common.framebuffer_addr; g_frameBuffer.format = DeterminePixelFormat(redMask, greenMask, blueMask, reservedMask); } break; case MULTIBOOT2_FRAMEBUFFER_TYPE_EGA_TEXT: { // OK to initialize VgaConsole here since it doesn't allocate any memory // g_vgaConsole.Initialize((void*)mbi->common.framebuffer_addr, mbi->common.framebuffer_width, mbi->common.framebuffer_height); // g_console = &g_vgaConsole; } break; } } break; } } if (mmap) { // Add memory map itself g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, (uintptr_t)mmap->entries, mmap->size); const multiboot2_mmap_entry* entry = mmap->entries; const multiboot2_mmap_entry* end = (multiboot2_mmap_entry*) ((uintptr_t)mmap + mmap->size); while (entry < end) { MemoryType type; uint32_t flags; switch (entry->type) { case MULTIBOOT2_MEMORY_AVAILABLE: type = MemoryType_Available; flags = 0; break; case MULTIBOOT2_MEMORY_ACPI_RECLAIMABLE: type = MemoryType_AcpiReclaimable; flags = 0; break; case MULTIBOOT2_MEMORY_NVS: type = MemoryType_AcpiNvs; flags = 0; break; case MULTIBOOT2_MEMORY_BADRAM: type = MemoryType_Unusable; flags = 0; break; case MULTIBOOT2_MEMORY_RESERVED: default: type = MemoryType_Reserved; flags = 0; break; } g_memoryMap.AddBytes(type, flags, entry->addr, entry->len); // Go to next entry entry = (multiboot2_mmap_entry*) ((uintptr_t)entry + mmap->entry_size); } } else if (meminfo) { g_memoryMap.AddBytes(MemoryType_Available, 0, 0, (uint64_t)meminfo->mem_lower * 1024); g_memoryMap.AddBytes(MemoryType_Available, 0, 1024*1024, (uint64_t)meminfo->mem_upper * 1024); } }