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
+10 -10
View File
@@ -7,21 +7,21 @@
using namespace Kt;
namespace Memory {
LargestSection Scan(limine_memmap_response* mmap) {
LargestSection Scan(const montauk::boot::MemoryMap& mmap) {
LargestSection currentLargestSection{};
for (size_t i = 0; i < mmap->entry_count; i++) {
auto entry = mmap->entries[i];
for (size_t i = 0; i < mmap.count; i++) {
const auto& entry = mmap.regions[i];
if (entry->base == 0) {
if (entry.base == 0) {
continue;
}
if (entry->type == LIMINE_MEMMAP_USABLE) {
if (entry->length > currentLargestSection.size) {
if (entry.kind == montauk::boot::MemoryKind::Usable) {
if (entry.length > currentLargestSection.size) {
currentLargestSection = {
.address = (uint64_t)entry->base,
.size = entry->length
.address = entry.base,
.size = entry.length
};
}
}
@@ -33,4 +33,4 @@ namespace Memory {
return currentLargestSection;
}
};
};
+6 -5
View File
@@ -1,8 +1,7 @@
#pragma once
#include <limine.h>
#include <Boot/BootInfo.hpp>
#include <cstddef>
using namespace std;
#include <cstdint>
namespace Memory {
// Shared
@@ -11,5 +10,7 @@ namespace Memory {
size_t size;
};
LargestSection Scan(limine_memmap_response* mmap);
};
// Scan the boot contract's physical memory map for the largest single
// run of usable RAM (the page-frame allocator is seeded from it).
LargestSection Scan(const montauk::boot::MemoryMap& mmap);
};
+49 -14
View File
@@ -23,7 +23,8 @@ namespace Memory::VMM {
PML4 = (PageTable*)SubHHDM((PageTable*)Memory::g_pfa->AllocateZeroed());
}
void Paging::Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize, limine_memmap_response* memMap) {
void Paging::Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize, const montauk::boot::MemoryMap& memMap,
const montauk::boot::Framebuffer& framebuffer) {
// Map kernel
Kt::KernelLogStream(Kt::DEBUG, "VMM") << "Paging::Init called with kernelBaseVirt as 0x" << base::hex << kernelBaseVirt;
@@ -31,15 +32,31 @@ namespace Memory::VMM {
Map(GetPhysKernelAddress(pageAddr), pageAddr);
}
// Map HHDM: find the highest physical address and map everything
// from 0 to that point. This covers gaps between memory map entries
// (e.g. BIOS ROM at 0xE0000) that firmware may not list but the
// kernel still needs to access via HHDM.
// Map HHDM: map physical memory contiguously from 0 up to the top of
// real backing store, so the kernel can reach any RAM/firmware byte at
// phys+hhdmBase. Mapping from 0 (rather than per-region) also covers
// unlisted low gaps -- BIOS ROM at 0xE0000, the EBDA, etc. -- that the
// kernel still touches through the HHDM.
//
// The upper bound is computed over real backing store ONLY: RAM, ACPI
// tables, modules, the framebuffer, and so on. Reserved/Unknown
// regions are deliberately EXCLUDED from the bound. Firmware commonly
// reports the 64-bit PCI MMIO aperture as a Reserved region hundreds of
// GiB above RAM (its base scales with the CPU's physical-address width);
// letting that inflate maxPhysAddr would make this loop allocate
// gigabytes of 4 KiB page tables and exhaust the frame allocator (OOM).
// Such MMIO is mapped on demand via MapMMIO with the right cache
// attributes -- never through the HHDM -- so it is correct to leave it
// out here. Reserved regions that sit *below* the bound (e.g. low BIOS
// areas) are still mapped by the contiguous fill.
uint64_t maxPhysAddr = 0;
for (size_t i = 0; i < memMap->entry_count; i++) {
auto entry = memMap->entries[i];
uint64_t entryEnd = entry->base + entry->length;
for (size_t i = 0; i < memMap.count; i++) {
const auto& entry = memMap.regions[i];
if (entry.kind == montauk::boot::MemoryKind::Reserved
|| entry.kind == montauk::boot::MemoryKind::Unknown) {
continue;
}
uint64_t entryEnd = entry.base + entry.length;
if (entryEnd > maxPhysAddr) maxPhysAddr = entryEnd;
}
maxPhysAddr = (maxPhysAddr + 0xFFF) & ~0xFFFULL;
@@ -48,6 +65,24 @@ namespace Memory::VMM {
Map(pageAddr, HHDM(pageAddr));
}
// The linear framebuffer can sit in a PCI BAR above the RAM bound we
// just mapped (e.g. in the 32-bit MMIO hole), and it is not guaranteed
// to appear as a memory-map region. It MUST be reachable through the
// HHDM before we switch to these page tables, because the very next log
// line (and PAT setup, and Cursor init) renders to it via phys+hhdmBase.
// Map its pages explicitly (write-back for now; Cursor upgrades them to
// write-combining once PAT is reprogrammed).
if (framebuffer.address != 0) {
uint64_t fbPhys = Memory::SubHHDM(framebuffer.address);
uint64_t fbBytes = framebuffer.height * framebuffer.pitch;
uint64_t fbPages = (fbBytes + 0xFFF) / 0x1000;
fbPhys &= ~0xFFFULL;
for (uint64_t p = 0; p < fbPages; p++) {
uint64_t phys = fbPhys + p * 0x1000;
Map(phys, HHDM(phys));
}
}
LoadCR3(PML4);
Kt::KernelLogStream(Kt::OK, "VMM") << "Switched CR3";
}
@@ -455,12 +490,12 @@ namespace Memory::VMM {
return GetPhysAddr((std::uint64_t)PML4, virtualAddress, false);
}
void Paging::MapEfiRuntime(limine_efi_memmap_response* efiMemmap) {
if (!efiMemmap) return;
void Paging::MapEfiRuntime(const montauk::boot::EfiInfo& efi) {
if (efi.memoryMap == nullptr || efi.descriptorSize == 0) return;
auto* base = (uint8_t*)efiMemmap->memmap;
uint64_t descSize = efiMemmap->desc_size;
uint64_t count = efiMemmap->memmap_size / descSize;
auto* base = (uint8_t*)efi.memoryMap;
uint64_t descSize = efi.descriptorSize;
uint64_t count = efi.memoryMapSize / descSize;
struct EfiMemDesc {
uint32_t Type;
+5 -3
View File
@@ -1,6 +1,7 @@
#pragma once
#include <limine.h>
#include <Boot/BootInfo.hpp>
#include <cstdint>
#include <stddef.h>
#include <Terminal/Terminal.hpp>
namespace Memory::VMM {
@@ -87,7 +88,8 @@ public:
PageTable* PML4{};
Paging();
void Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize, limine_memmap_response* memMap);
void Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize, const montauk::boot::MemoryMap& memMap,
const montauk::boot::Framebuffer& framebuffer);
void Map(std::uint64_t physicalAddress, std::uint64_t virtualAddress);
void MapMMIO(std::uint64_t physicalAddress, std::uint64_t virtualAddress);
void MapWC(std::uint64_t physicalAddress, std::uint64_t virtualAddress);
@@ -121,7 +123,7 @@ public:
// Identity-map EFI runtime service regions so firmware code can
// reference its own data at physical addresses.
void MapEfiRuntime(limine_efi_memmap_response* efiMemmap);
void MapEfiRuntime(const montauk::boot::EfiInfo& efi);
};
extern Paging* g_paging;