// ============================================================================ // core/kernel_main.cpp - Kernel entry point // // Called by arch-specific entry.S after stack setup. // Receives BootInfo* by the UEFI loader (or in future from other loader). // ============================================================================ #include #include #include #include #include "Processor.h" using namespace kernel; // ── Memory region type names ─────────────────────────────────────────────── namespace { //TODO: Move it to another cpp/h file //TODO: use reflection to get field name [[nodiscard]] constexpr const char* mem_type_name(MemoryRegionType type) { switch (type) { case MemoryRegionType::Usable: return "Usable"; case MemoryRegionType::Reserved: return "Reserved"; case MemoryRegionType::AcpiReclaimable: return "ACPI Reclaimable"; case MemoryRegionType::AcpiNvs: return "ACPI NVS"; case MemoryRegionType::BootloaderReclaimable: return "Boot Reclaimable"; case MemoryRegionType::KernelAndModules: return "Kernel"; case MemoryRegionType::Framebuffer: return "Framebuffer"; } return "Unknown"; } } // anonymous namespace // ── Kernel entry ─────────────────────────────────────────────────────────── // Called from entry.S with BootInfo* in RDI (x86_64) / X0 (AArch64). extern "C" void kernel_main(BootInfo* boot_info) { // Validate magic — if wrong we can't print, just halt. if (boot_info->magic != BOOT_INFO_MAGIC) arch::halt(); // Initialize framebuffer console (needed before Kernel::init for logging). // TODO: Add driver skeleton and move framebuffer to early drivers. kcon::init(boot_info->framebuffer); // Initialize the kernel object — copies boot data, safe to use after this. GetKernel().init(*boot_info); // Store arch-specific per-CPU state (Phase 2: GDT/IDT, VBAR/GIC, etc.). processor().InitEarly(*boot_info); // ── Banner ───────────────────────────────────────────────────────── kcon::println("========================================"); kcon::kprintf(" Bastion Kernel %s\n", GetKernel().GetVersion().string); kcon::kprintf(" Architecture: %s\n", GetKernel().GetArchName()); kcon::println("========================================"); kcon::putchar('\n'); // ── Framebuffer info ─────────────────────────────────────────────── kcon::kprintf("Framebuffer: %ux%u, pitch=%u, base=%x\n", GetKernel().GetFramebuffer().width, GetKernel().GetFramebuffer().height, GetKernel().GetFramebuffer().pitch, GetKernel().GetFramebuffer().base); kcon::putchar('\n'); // ── Firmware tables ──────────────────────────────────────────────── if (GetKernel().GetAcpiTables() && GetKernel().GetAcpiTables()->GetRsdpAddress()) kcon::kprintf("ACPI RSDP at: %x\n", GetKernel().GetAcpiTables()->GetRsdpAddress()); if (GetKernel().GetDeviceTree() && GetKernel().GetDeviceTree()->GetFdtAddress()) kcon::kprintf("Device Tree at: %x\n", GetKernel().GetDeviceTree()->GetFdtAddress()); kcon::putchar('\n'); // ── Memory map (read directly from boot_info, consumed by PMM later) ── kcon::kprintf("Memory map (%u entries):\n", boot_info->memory_map_count); uint64_t total_usable = 0; for (uint64_t i = 0; i < boot_info->memory_map_count; i++) { const auto& region = boot_info->memory_map[i]; // Skip tiny reserved regions to avoid flooding the console. if (region.type == MemoryRegionType::Reserved && region.length < 0x10000) continue; kcon::kprintf(" %x - %x [%s]\n", region.base, region.base + region.length, mem_type_name(region.type)); if (region.type == MemoryRegionType::Usable) total_usable += region.length; } kcon::putchar('\n'); kcon::kprintf("Total usable memory: %u MiB\n", total_usable / (1024u * 1024u)); // ── Kernel info ──────────────────────────────────────────────────── kcon::putchar('\n'); kcon::kprintf("Kernel loaded at phys %x, virt %x, size %u KiB\n", GetKernel().GetKernelPhysBase(), GetKernel().GetKernelPhysBase(), GetKernel().GetKernelSize() / 1024u); // ── Done (for now) ───────────────────────────────────────────────── GetKernel().SetRunning(); kcon::putchar('\n'); kcon::println("Hello, World from BastionOS!"); kcon::putchar('\n'); kcon::println("Kernel initialized successfully."); kcon::println("Next: GDT, IDT, paging, memory allocator..."); kcon::println("Halting."); //KERNEL_PANIC("panic test"); GetKernel().SetHalt(); arch::halt(); }