feat: Local/IO APIC, PS/2 keyboard & mouse
This commit is contained in:
@@ -71,7 +71,8 @@ namespace Hal {
|
||||
|
||||
if (xsdp->Revision >= 2) {
|
||||
nextTableAddress = xsdp->XSDTAddress;
|
||||
HandleXSDT((CommonSDTHeader*)Memory::HHDM(nextTableAddress));
|
||||
m_xsdt = (CommonSDTHeader*)Memory::HHDM(nextTableAddress);
|
||||
HandleXSDT(m_xsdt);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -42,5 +42,10 @@ namespace Hal {
|
||||
static bool TestChecksum(CommonSDTHeader* header);
|
||||
|
||||
CommonSDTHeader* FindNextTable(CommonSDTHeader* table);
|
||||
|
||||
CommonSDTHeader* GetXSDT() { return m_xsdt; }
|
||||
|
||||
private:
|
||||
CommonSDTHeader* m_xsdt = nullptr;
|
||||
};
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* MADT.hpp
|
||||
* Multiple APIC Description Table parsing
|
||||
* Copyright (c) 2025 Daniel Hammer
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <ACPI/ACPI.hpp>
|
||||
|
||||
namespace Hal {
|
||||
namespace MADT {
|
||||
struct Header {
|
||||
Hal::ACPI::CommonSDTHeader SDTHeader;
|
||||
uint32_t LocalApicAddress;
|
||||
uint32_t Flags;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct EntryHeader {
|
||||
uint8_t Type;
|
||||
uint8_t Length;
|
||||
}__attribute__((packed));
|
||||
|
||||
// Type 0: Processor Local APIC
|
||||
struct LocalApicEntry {
|
||||
EntryHeader Header;
|
||||
uint8_t ProcessorId;
|
||||
uint8_t ApicId;
|
||||
uint32_t Flags;
|
||||
}__attribute__((packed));
|
||||
|
||||
// Type 1: I/O APIC
|
||||
struct IoApicEntry {
|
||||
EntryHeader Header;
|
||||
uint8_t IoApicId;
|
||||
uint8_t Reserved;
|
||||
uint32_t IoApicAddress;
|
||||
uint32_t GlobalSystemInterruptBase;
|
||||
}__attribute__((packed));
|
||||
|
||||
// Type 2: Interrupt Source Override
|
||||
struct InterruptSourceOverride {
|
||||
EntryHeader Header;
|
||||
uint8_t BusSource;
|
||||
uint8_t IrqSource;
|
||||
uint32_t GlobalSystemInterrupt;
|
||||
uint16_t Flags;
|
||||
}__attribute__((packed));
|
||||
|
||||
// Type 4: Non-Maskable Interrupt
|
||||
struct NmiEntry {
|
||||
EntryHeader Header;
|
||||
uint8_t ProcessorId;
|
||||
uint16_t Flags;
|
||||
uint8_t Lint;
|
||||
}__attribute__((packed));
|
||||
|
||||
// Type 5: Local APIC Address Override
|
||||
struct LocalApicAddressOverride {
|
||||
EntryHeader Header;
|
||||
uint16_t Reserved;
|
||||
uint64_t LocalApicAddress;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct ParsedMADT {
|
||||
uint64_t LocalApicAddress;
|
||||
uint64_t IoApicAddress;
|
||||
uint8_t IoApicId;
|
||||
uint32_t IoApicGsiBase;
|
||||
|
||||
static constexpr int MaxOverrides = 16;
|
||||
InterruptSourceOverride Overrides[MaxOverrides];
|
||||
int OverrideCount;
|
||||
|
||||
static constexpr int MaxLocalApics = 16;
|
||||
LocalApicEntry LocalApics[MaxLocalApics];
|
||||
int LocalApicCount;
|
||||
};
|
||||
|
||||
bool Parse(ACPI::CommonSDTHeader* xsdt, ParsedMADT& result);
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user