#include #include #include namespace Kernel { BootInfo g_boot_info; static void parse_boot_info_multiboot2(uint32_t info) { const auto& multiboot2_info = *reinterpret_cast(info); for (const auto* tag = multiboot2_info.tags; tag->type != MULTIBOOT2_TAG_END; tag = tag->next()) { if (tag->type == MULTIBOOT2_TAG_CMDLINE) { const auto& command_line_tag = *static_cast(tag); MUST(g_boot_info.command_line.append(command_line_tag.cmdline)); } else if (tag->type == MULTIBOOT2_TAG_FRAMEBUFFER) { const auto& framebuffer_tag = *static_cast(tag); g_boot_info.framebuffer.address = framebuffer_tag.framebuffer_addr; g_boot_info.framebuffer.pitch = framebuffer_tag.framebuffer_pitch; g_boot_info.framebuffer.width = framebuffer_tag.framebuffer_width; g_boot_info.framebuffer.height = framebuffer_tag.framebuffer_height; g_boot_info.framebuffer.bpp = framebuffer_tag.framebuffer_bpp; if (framebuffer_tag.framebuffer_type == MULTIBOOT2_FRAMEBUFFER_TYPE_RGB) g_boot_info.framebuffer.type = FramebufferType::RGB; else g_boot_info.framebuffer.type = FramebufferType::UNKNOWN; } else if (tag->type == MULTIBOOT2_TAG_MMAP) { const auto& mmap_tag = *static_cast(tag); const size_t entry_count = (mmap_tag.size - sizeof(multiboot2_mmap_tag_t)) / mmap_tag.entry_size; MUST(g_boot_info.memory_map_entries.resize(entry_count)); for (size_t i = 0; i < entry_count; i++) { const auto& mmap_entry = *reinterpret_cast(reinterpret_cast(tag) + sizeof(multiboot2_mmap_tag_t) + i * mmap_tag.entry_size); dprintln("entry {16H} {16H} {8H}", (uint64_t)mmap_entry.base_addr, (uint64_t)mmap_entry.length, (uint64_t)mmap_entry.type ); g_boot_info.memory_map_entries[i].address = mmap_entry.base_addr; g_boot_info.memory_map_entries[i].length = mmap_entry.length; g_boot_info.memory_map_entries[i].type = mmap_entry.type; } } else if (tag->type == MULTIBOOT2_TAG_OLD_RSDP) { if (g_boot_info.rsdp.length == 0) { memcpy(&g_boot_info.rsdp, static_cast(tag)->data, 20); g_boot_info.rsdp.length = 20; } } else if (tag->type == MULTIBOOT2_TAG_NEW_RSDP) { const auto& rsdp = *reinterpret_cast(static_cast(tag)->data); memcpy(&g_boot_info.rsdp, &rsdp, BAN::Math::min(rsdp.length, sizeof(g_boot_info.rsdp))); } } } static BAN::StringView get_early_boot_command_line_multiboot2(uint32_t info) { const auto& multiboot2_info = *reinterpret_cast(info); for (const auto* tag = multiboot2_info.tags; tag->type != MULTIBOOT2_TAG_END; tag = tag->next()) if (tag->type == MULTIBOOT2_TAG_CMDLINE) return static_cast(tag)->cmdline; return {}; } static void parse_boot_info_banan_bootloader(uint32_t info) { const auto& banan_bootloader_info = *reinterpret_cast(info); const char* command_line = reinterpret_cast(banan_bootloader_info.command_line_addr); MUST(g_boot_info.command_line.append(command_line)); const auto& framebuffer = *reinterpret_cast(banan_bootloader_info.framebuffer_addr); if (framebuffer.type == BANAN_BOOTLOADER_FB_RGB) { g_boot_info.framebuffer.address = framebuffer.address; g_boot_info.framebuffer.width = framebuffer.width; g_boot_info.framebuffer.height = framebuffer.height; g_boot_info.framebuffer.pitch = framebuffer.pitch; g_boot_info.framebuffer.bpp = framebuffer.bpp; g_boot_info.framebuffer.type = FramebufferType::RGB; } const auto& memory_map = *reinterpret_cast(banan_bootloader_info.memory_map_addr); MUST(g_boot_info.memory_map_entries.resize(memory_map.entry_count)); for (size_t i = 0; i < memory_map.entry_count; i++) { const auto& mmap_entry = memory_map.entries[i]; g_boot_info.memory_map_entries[i].address = mmap_entry.address; g_boot_info.memory_map_entries[i].length = mmap_entry.length; g_boot_info.memory_map_entries[i].type = mmap_entry.type; } } static BAN::StringView get_early_boot_command_line_banan_bootloader(uint32_t info) { const auto& banan_bootloader_info = *reinterpret_cast(info); return reinterpret_cast(banan_bootloader_info.command_line_addr); } bool validate_boot_magic(uint32_t magic) { if (magic == MULTIBOOT2_MAGIC) return true; if (magic == BANAN_BOOTLOADER_MAGIC) return true; return false; } void parse_boot_info(uint32_t magic, uint32_t info) { switch (magic) { case MULTIBOOT2_MAGIC: return parse_boot_info_multiboot2(info); case BANAN_BOOTLOADER_MAGIC: return parse_boot_info_banan_bootloader(info); } ASSERT_NOT_REACHED(); } BAN::StringView get_early_boot_command_line(uint32_t magic, uint32_t info) { switch (magic) { case MULTIBOOT2_MAGIC: return get_early_boot_command_line_multiboot2(info); case BANAN_BOOTLOADER_MAGIC: return get_early_boot_command_line_banan_bootloader(info); } ASSERT_NOT_REACHED(); } }