185 lines
5.2 KiB
C++
185 lines
5.2 KiB
C++
/*
|
|
* main.cpp
|
|
* Kernel entry point
|
|
* Copyright (c) 2025 Daniel Hammer.
|
|
* Further copyright information and third party notices can be found at https://montaukos.org/license.txt.
|
|
*/
|
|
|
|
#include <Fs/ProtectedPaths.hpp>
|
|
#include <Memory/UserRange.hpp>
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
#include <Boot/Boot.hpp>
|
|
#include <Terminal/Terminal.hpp>
|
|
#include <Efi/UEFI.hpp>
|
|
#include <Common/Panic.hpp>
|
|
#include <Memory/Memmap.hpp>
|
|
#include <Memory/Heap.hpp>
|
|
#include <Memory/HHDM.hpp>
|
|
#include <Memory/PageFrameAllocator.hpp>
|
|
#include <Memory/Paging.hpp>
|
|
#include <ACPI/ACPI.hpp>
|
|
#include <ACPI/AcpiShutdown.hpp>
|
|
#include <ACPI/AcpiEvents.hpp>
|
|
#include <ACPI/EmbeddedController.hpp>
|
|
#include <ACPI/Battery.hpp>
|
|
#include <ACPI/AML/AmlParser.hpp>
|
|
#include <Pci/Pci.hpp>
|
|
#include <Timekeeping/Timer.hpp>
|
|
#include <Drivers/Init.hpp>
|
|
#include <Graphics/Framebuffer.hpp>
|
|
#include <Arch/Cpu.hpp>
|
|
#include <Arch/Platform.hpp>
|
|
#include <Fs/Boot.hpp>
|
|
#include <Sched/Scheduler.hpp>
|
|
#include <Ipc/Ipc.hpp>
|
|
#include <Api/Syscall.hpp>
|
|
#include <Arch/Smp.hpp>
|
|
using namespace Kt;
|
|
|
|
namespace Memory {
|
|
HeapAllocator* g_heap;
|
|
PageFrameAllocator* g_pfa;
|
|
uint64_t HHDMBase;
|
|
};
|
|
|
|
KernelOutStream kout{};
|
|
KernelErrorStream kerr{};
|
|
|
|
// Extern declarations for global constructors array.
|
|
extern void (*__init_array[])();
|
|
extern void (*__init_array_end[])();
|
|
|
|
extern "C" uint64_t KernelStartSymbol;
|
|
extern "C" uint64_t KernelEndSymbol;
|
|
|
|
extern "C" void kmain() {
|
|
// Call global constructors.
|
|
for (std::size_t i = 0; &__init_array[i] != __init_array_end; i++) {
|
|
__init_array[i]();
|
|
}
|
|
|
|
if (!montauk::boot::Initialize()) {
|
|
Arch::HaltForever();
|
|
}
|
|
const montauk::boot::BootInfo& boot = montauk::boot::Info();
|
|
const montauk::boot::Framebuffer& framebuffer = boot.framebuffer;
|
|
|
|
Kt::Initialize(
|
|
(uint32_t*)framebuffer.address,
|
|
framebuffer.width,
|
|
framebuffer.height,
|
|
framebuffer.pitch,
|
|
framebuffer.redMaskSize,
|
|
framebuffer.redMaskShift,
|
|
framebuffer.greenMaskSize,
|
|
framebuffer.greenMaskShift,
|
|
framebuffer.blueMaskSize,
|
|
framebuffer.blueMaskShift
|
|
);
|
|
|
|
|
|
Arch::EarlyInitialize();
|
|
|
|
Memory::HHDMBase = boot.hhdmBase;
|
|
|
|
if (boot.memoryMap.regions == nullptr || boot.memoryMap.count == 0) {
|
|
Panic("System memory map missing!", nullptr);
|
|
}
|
|
|
|
Kt::KernelLogStream(OK, "Mem") << "Creating PageFrameAllocator";
|
|
Memory::PageFrameAllocator pmm(Memory::Scan(boot.memoryMap));
|
|
Memory::g_pfa = &pmm;
|
|
|
|
Kt::KernelLogStream(OK, "Mem") << "Creating HeapAllocator";
|
|
Memory::HeapAllocator heap{};
|
|
Memory::g_heap = &heap;
|
|
|
|
heap.Walk();
|
|
|
|
|
|
Arch::InitializeTraps();
|
|
|
|
Memory::VMM::Paging g_paging{};
|
|
Memory::VMM::g_paging = &g_paging;
|
|
g_paging.Init((uint64_t)&KernelStartSymbol, ((uint64_t)&KernelEndSymbol - (uint64_t)&KernelStartSymbol), boot.memoryMap, framebuffer);
|
|
|
|
Arch::InitializeMemoryAttributes();
|
|
|
|
Graphics::Framebuffer::Initialize(framebuffer);
|
|
Graphics::Framebuffer::MapWriteCombining();
|
|
|
|
Hal::ACPI g_acpi((Hal::ACPI::XSDP*)Memory::HHDM(boot.rsdpPhysical));
|
|
|
|
if (g_acpi.GetXSDT() != nullptr) {
|
|
Hal::AcpiShutdown::Initialize(g_acpi.GetXSDT());
|
|
|
|
// The EC is the transport behind battery (and most thermal) methods, so
|
|
// it has to be latched before anything evaluates them.
|
|
Hal::EmbeddedController::Initialize(g_acpi.GetXSDT());
|
|
Hal::Battery::Initialize();
|
|
|
|
// Interrupt controllers, this CPU's per-CPU data, idle and power
|
|
// management.
|
|
Arch::InitializeInterrupts(g_acpi.GetXSDT());
|
|
|
|
Arch::EnableInterrupts();
|
|
|
|
Hal::AcpiEvents::Initialize(g_acpi.GetXSDT());
|
|
|
|
Pci::Initialize(g_acpi.GetXSDT());
|
|
|
|
// _REG and _INI, once the EC and PCI config space (ECAM, for the
|
|
// extended registers PCI_Config regions reach) are both available:
|
|
// firmware settles which OS it is talking to here, and gates device
|
|
// power control on the answer.
|
|
Hal::AML::InitializeNamespaceObjects();
|
|
|
|
Drivers::ProbeEarly();
|
|
Drivers::InitializeGraphics();
|
|
|
|
Timekeeping::TimerInitialize();
|
|
|
|
Arch::InitializePlatformDevices();
|
|
|
|
// Hybrid graphics: switch off a discrete GPU nothing drives before
|
|
// the normal probe can claim its USB-C/audio functions.
|
|
Drivers::PowerDownUnusedGpus();
|
|
|
|
Drivers::ProbeNormal();
|
|
Drivers::InitializeNetwork();
|
|
Drivers::InitializeStorage();
|
|
Drivers::InitializeAudio();
|
|
}
|
|
|
|
// UEFI runtime services are optional (absent on legacy-BIOS boots).
|
|
if (boot.has(montauk::boot::FeatureEfiSystemTable)) {
|
|
Efi::SystemTable* ST = (Efi::SystemTable*)Memory::HHDM(boot.efi.systemTablePhysical);
|
|
Efi::Init(ST, boot.efi);
|
|
}
|
|
|
|
Fs::InitializeBootFilesystems(boot.modules);
|
|
|
|
Arch::PrepareUserMode();
|
|
|
|
montauk::abi::InitializeSyscalls();
|
|
|
|
Sched::Initialize();
|
|
Memory::InitUserRange();
|
|
Fs::LogProtectedPaths();
|
|
Ipc::Initialize();
|
|
|
|
Smp::BootAPs(boot.smp);
|
|
|
|
Arch::LateInitialize();
|
|
|
|
Kt::SuppressKernelLog();
|
|
Sched::Spawn("0:/os/init.elf");
|
|
|
|
Timekeeping::EnableSchedulerTick();
|
|
|
|
for (;;) {
|
|
Timekeeping::IdleOnce();
|
|
}
|
|
}
|