feat: Local/IO APIC, PS/2 keyboard & mouse

This commit is contained in:
2026-02-17 12:44:31 +01:00
parent e2f059bf90
commit 641ec4681b
26 changed files with 1730 additions and 3 deletions
+135
View File
@@ -0,0 +1,135 @@
/*
* MADT.cpp
* Multiple APIC Description Table parsing
* Copyright (c) 2025 Daniel Hammer
*/
#include "MADT.hpp"
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <Memory/HHDM.hpp>
#include <Libraries/Memory.hpp>
using namespace Kt;
namespace Hal {
namespace MADT {
static bool SignatureMatch(const char* sig, const char* target, int len) {
for (int i = 0; i < len; i++) {
if (sig[i] != target[i]) return false;
}
return true;
}
static ACPI::CommonSDTHeader* FindMADTInXSDT(ACPI::CommonSDTHeader* xsdt) {
uint32_t entryCount = (xsdt->Length - sizeof(ACPI::CommonSDTHeader)) / 8;
uint64_t* entries = (uint64_t*)((uint64_t)xsdt + sizeof(ACPI::CommonSDTHeader));
for (uint32_t i = 0; i < entryCount; i++) {
auto* header = (ACPI::CommonSDTHeader*)Memory::HHDM(entries[i]);
if (SignatureMatch(header->Signature, "APIC", 4)) {
return header;
}
}
return nullptr;
}
bool Parse(ACPI::CommonSDTHeader* xsdt, ParsedMADT& result) {
auto* madtHeader = FindMADTInXSDT(xsdt);
if (madtHeader == nullptr) {
KernelLogStream(ERROR, "MADT") << "MADT table not found in XSDT";
return false;
}
if (!ACPI::TestChecksum(madtHeader)) {
KernelLogStream(ERROR, "MADT") << "MADT checksum failed";
return false;
}
KernelLogStream(OK, "MADT") << "Found MADT table";
auto* madt = (Header*)madtHeader;
result.LocalApicAddress = madt->LocalApicAddress;
result.OverrideCount = 0;
result.LocalApicCount = 0;
result.IoApicAddress = 0;
result.IoApicId = 0;
result.IoApicGsiBase = 0;
KernelLogStream(INFO, "MADT") << "Local APIC address: " << base::hex << (uint64_t)result.LocalApicAddress;
uint32_t offset = sizeof(Header);
uint32_t length = madt->SDTHeader.Length;
while (offset < length) {
auto* entry = (EntryHeader*)((uint64_t)madt + offset);
switch (entry->Type) {
case 0: { // Processor Local APIC
auto* lapic = (LocalApicEntry*)entry;
if (result.LocalApicCount < ParsedMADT::MaxLocalApics) {
result.LocalApics[result.LocalApicCount] = *lapic;
result.LocalApicCount++;
}
KernelLogStream(DEBUG, "MADT") << "Local APIC: processor=" << (uint64_t)lapic->ProcessorId
<< " id=" << (uint64_t)lapic->ApicId
<< " flags=" << base::hex << (uint64_t)lapic->Flags;
break;
}
case 1: { // I/O APIC
auto* ioapic = (IoApicEntry*)entry;
result.IoApicAddress = ioapic->IoApicAddress;
result.IoApicId = ioapic->IoApicId;
result.IoApicGsiBase = ioapic->GlobalSystemInterruptBase;
KernelLogStream(DEBUG, "MADT") << "IOAPIC: id=" << (uint64_t)ioapic->IoApicId
<< " address=" << base::hex << (uint64_t)ioapic->IoApicAddress
<< " GSI base=" << base::dec << (uint64_t)ioapic->GlobalSystemInterruptBase;
break;
}
case 2: { // Interrupt Source Override
auto* iso = (InterruptSourceOverride*)entry;
if (result.OverrideCount < ParsedMADT::MaxOverrides) {
result.Overrides[result.OverrideCount] = *iso;
result.OverrideCount++;
}
KernelLogStream(DEBUG, "MADT") << "IRQ Override: bus=" << (uint64_t)iso->BusSource
<< " irq=" << (uint64_t)iso->IrqSource
<< " -> GSI " << (uint64_t)iso->GlobalSystemInterrupt
<< " flags=" << base::hex << (uint64_t)iso->Flags;
break;
}
case 4: { // NMI
auto* nmi = (NmiEntry*)entry;
KernelLogStream(DEBUG, "MADT") << "NMI: processor=" << (uint64_t)nmi->ProcessorId
<< " lint=" << (uint64_t)nmi->Lint;
break;
}
case 5: { // Local APIC Address Override
auto* override = (LocalApicAddressOverride*)entry;
result.LocalApicAddress = override->LocalApicAddress;
KernelLogStream(DEBUG, "MADT") << "Local APIC address override: " << base::hex << result.LocalApicAddress;
break;
}
default:
KernelLogStream(DEBUG, "MADT") << "Unknown MADT entry type: " << (uint64_t)entry->Type;
break;
}
offset += entry->Length;
}
KernelLogStream(OK, "MADT") << "Parsed " << base::dec
<< (uint64_t)result.LocalApicCount << " local APICs, "
<< (uint64_t)result.OverrideCount << " overrides";
return true;
}
};
};