feat: introduce bootloader-agnostic Boot Contract, add btlist command to list connected Bluetooth devices

This commit is contained in:
2026-06-20 21:25:24 +02:00
parent de871ac402
commit 772eaee9f4
20 changed files with 904 additions and 213 deletions
+21 -23
View File
@@ -17,11 +17,7 @@
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <limine.h>
// Defined in Platform/Limine.hpp (included only by Main.cpp to avoid
// duplicating the LIMINE_BASE_REVISION tag).
extern volatile limine_mp_request mp_request;
#include <Boot/BootInfo.hpp>
#include <Libraries/Memory.hpp>
// Verify assembly offsets match struct layout
@@ -153,14 +149,15 @@ namespace Smp {
// ====================================================================
// AP entry point
// Called by Limine when goto_address is written.
// RDI = pointer to limine_mp_info for this CPU.
// Runs on a 64KiB Limine-provided stack.
// Invoked by the boot contract (montauk::boot::SmpInfo::startCpu) when
// the AP is woken. Receives the BootCpu for this processor; the kernel
// stashed this CPU's CpuData* in BootCpu::extraArgument before starting
// it. Runs on a bootloader-provided stack.
// ====================================================================
static void ApEntry(limine_mp_info* info) {
// Find our CpuData (stored in extra_argument by BootAPs)
CpuData* cpu = (CpuData*)info->extra_argument;
static void ApEntry(montauk::boot::BootCpu* bootCpu) {
// Find our CpuData (stashed in extraArgument by BootAPs)
CpuData* cpu = (CpuData*)bootCpu->extraArgument;
// --- Load per-CPU GDT ---
Hal::GDTPointer gdtPtr {
@@ -223,17 +220,16 @@ namespace Smp {
// Boot all APs
// ====================================================================
void BootAPs() {
if (mp_request.response == nullptr) {
KernelLogStream(WARNING, "SMP") << "No MP response from bootloader - single CPU mode";
void BootAPs(const montauk::boot::SmpInfo& smp) {
if (smp.cpus == nullptr || smp.startCpu == nullptr) {
KernelLogStream(WARNING, "SMP") << "No SMP info from bootloader - single CPU mode";
return;
}
auto* resp = mp_request.response;
uint64_t cpuCount = resp->cpu_count;
uint64_t cpuCount = smp.cpuCount;
KernelLogStream(INFO, "SMP") << "Bootloader reports " << cpuCount << " CPU(s), BSP LAPIC ID "
<< (uint64_t)resp->bsp_lapic_id;
<< (uint64_t)smp.bspLapicId;
if (cpuCount <= 1) {
KernelLogStream(INFO, "SMP") << "Single CPU system - no APs to boot";
@@ -251,23 +247,25 @@ namespace Smp {
// - Each AP's init is purely local (GDT, TSS, APIC, MSRs)
int apIndex = 1; // BSP is index 0
for (uint64_t i = 0; i < cpuCount; i++) {
limine_mp_info* info = resp->cpus[i];
montauk::boot::BootCpu& info = smp.cpus[i];
if (info->lapic_id == resp->bsp_lapic_id) continue;
if (info.lapicId == smp.bspLapicId) continue;
if (apIndex >= MaxCPUs) break;
CpuData& ap = g_cpus[apIndex];
ap.selfPtr = (uint64_t)&ap;
ap.cpuIndex = apIndex;
ap.lapicId = info->lapic_id;
ap.lapicId = info.lapicId;
ap.currentSlot = -1;
ap.started = false;
SetupPerCpuGdtTss(ap);
info->extra_argument = (uint64_t)&ap;
// Wake this AP (it runs ApEntry in parallel with other APs)
__atomic_store_n(&info->goto_address, (limine_goto_address)ApEntry, __ATOMIC_SEQ_CST);
// Stash this AP's CpuData* where ApEntry will recover it, then
// ask the bootloader to wake the AP into ApEntry. APs run in
// parallel with each other.
info.extraArgument = (uint64_t)&ap;
smp.startCpu(&info, ApEntry);
apIndex++;
}