replace ad hoc driver loading with a proper driver manager, new DDK, new PnP manager with device matching, asynchronous startup, resource ownership and removal, add shared PCI capability helpers, replace typed, rigid services with a proper service manager, implement proper system shutdown and restart, shutting down unloads drivers and shuts down services, add simple power button, remove heavyweight boot self-tests and SMP stress runs, add monotonic timestamps to kernel debug output, fruitless USB and PS/2 fixes, make test builds opt in.

This commit is contained in:
maksw committed 2026-10-26 10:08:03 +01:00
1 parent c0ad63c27f
commit d36f19509c
160 files changed
+6563 -7366

No files matched your search

+137
View File
@@ -122,6 +122,12 @@ typedef struct ACPI_FIXED_REGISTER {
static ACPI_FIXED_REGISTER gPm1aCnt;
static ACPI_FIXED_REGISTER gPm1bCnt;
static ACPI_FIXED_REGISTER gPm1aStatus;
static ACPI_FIXED_REGISTER gPm1bStatus;
static ACPI_FIXED_REGISTER gPm1aEnable;
static ACPI_FIXED_REGISTER gPm1bEnable;
static uint16_t gSciIrq = 0;
static bool gFixedPowerButtonArmed = false;
static ACPI_FIXED_REGISTER gSleepControl;
static uint32_t gLegacyPm1aPort = 0;
static uint32_t gLegacyPm1bPort = 0;
@@ -172,6 +178,14 @@ void* HalPhysicalToVirtual(uint64_t phys) {
// FADT (Fixed ACPI Description Table) offsets used here. ACPI 2.0+
// systems may put the real DSDT and PM1 control registers in the extended
// X_* fields, so do not rely only on the legacy 32-bit fields.
#define FADT_SCI_INT_OFFSET 46u
#define FADT_PM1A_EVT_BLK_OFFSET 56u
#define FADT_PM1B_EVT_BLK_OFFSET 60u
#define FADT_PM1_EVT_LEN_OFFSET 88u
#define FADT_X_PM1A_EVT_BLK_OFFSET 148u
#define FADT_X_PM1B_EVT_BLK_OFFSET 160u
#define FADT_FLAG_POWER_BUTTON (1u << 4)
#define ACPI_PM1_POWER_BUTTON_BIT (1u << 8)
#define FADT_DSDT_OFFSET 40u
#define FADT_SMI_CMD_OFFSET 48u
#define FADT_ACPI_ENABLE_OFFSET 52u
@@ -184,6 +198,8 @@ void* HalPhysicalToVirtual(uint64_t phys) {
#define FADT_X_PM1A_CNT_BLK_OFFSET 172u
#define FADT_X_PM1B_CNT_BLK_OFFSET 184u
#define FADT_SLEEP_CONTROL_OFFSET 244u
#define FADT_RESET_REG_OFFSET 116u
#define FADT_RESET_VALUE_OFFSET 128u
#define FADT_FLAG_HW_REDUCED_ACPI (1u << 20)
#define INTEL_PCH_SMI_EN_OFFSET 0x30u
#define INTEL_PCH_SMI_ON_SLP_EN (1u << 4)
@@ -198,6 +214,9 @@ typedef struct {
} ACPI_GAS;
#pragma pack(pop)
static ACPI_FIXED_REGISTER gResetRegister;
static uint8_t gResetValue;
// Implements the acpi Read U32 operation.
static uint32_t AcpiReadU32(const void* table, uint32_t tableLen, uint32_t off) {
uint32_t value = 0;
@@ -291,6 +310,77 @@ static void AcpiWriteFixedRegister(const ACPI_FIXED_REGISTER* reg, uint32_t valu
else *(volatile uint32_t*)address = value;
}
// Selects a PM1 event block as two adjacent equal-width status and enable registers.
static void AcpiConfigurePm1EventBlock(const void* fadt, uint32_t len,
uint32_t legacyOffset, uint32_t gasOffset,
uint8_t halfLength, ACPI_FIXED_REGISTER* status,
ACPI_FIXED_REGISTER* enable) {
ACPI_FIXED_REGISTER block = {0};
uint32_t legacy = AcpiReadU32(fadt, len, legacyOffset);
if (legacy && legacy <= 0xFFFFu) {
block.AddressSpaceId = 1;
block.Address = legacy;
}
ACPI_FIXED_REGISTER extended = {0};
if (AcpiReadGasRegister(fadt, len, gasOffset, &extended)) block = extended;
if (!block.Address || (block.AddressSpaceId == 1 &&
block.Address + halfLength * 2u - 1u > 0xFFFFu)) return;
block.WidthBytes = halfLength;
*status = block;
block.Address += halfLength;
*enable = block;
}
// Reports the fixed-feature power-button interrupt supported by this HAL.
static KSTATUS AcpiQueryFixedButtonIrq(uint8_t* irqOut) {
if (!irqOut) return NTLSTATUS_INVALID_PARAMETER;
// A FADT control-method power button requires AML evaluation, not PM1 polling.
if (gHwReducedAcpi || (gFadtFlags & FADT_FLAG_POWER_BUTTON) ||
!gSciIrq || gSciIrq >= 16u || !gPm1aStatus.Address || !gPm1aEnable.Address ||
!HalApicCanRouteIrq((uint8_t)gSciIrq))
return NTLSTATUS_NOT_SUPPORTED;
*irqOut = (uint8_t)gSciIrq;
return NTLSTATUS_SUCCESS;
}
// Discards any stale press then enables the PM1 fixed power-button SCI.
static KSTATUS AcpiArmFixedButton(void) {
uint8_t irq;
KSTATUS status = AcpiQueryFixedButtonIrq(&irq);
if (!KSUCCESS(status)) return status;
// No SCI_EN means firmware still owns ACPI events. Never steal ownership
// through SMI_CMD just to install a power-button handler during boot.
if (!(AcpiReadFixedRegister(&gPm1aCnt) & 1u))
return NTLSTATUS_NOT_SUPPORTED;
AcpiWriteFixedRegister(&gPm1aStatus, ACPI_PM1_POWER_BUTTON_BIT);
if (gPm1bStatus.Address)
AcpiWriteFixedRegister(&gPm1bStatus, ACPI_PM1_POWER_BUTTON_BIT);
uint32_t enabled = AcpiReadFixedRegister(&gPm1aEnable);
AcpiWriteFixedRegister(&gPm1aEnable, enabled | ACPI_PM1_POWER_BUTTON_BIT);
if (gPm1bEnable.Address) {
enabled = AcpiReadFixedRegister(&gPm1bEnable);
AcpiWriteFixedRegister(&gPm1bEnable, enabled | ACPI_PM1_POWER_BUTTON_BIT);
}
gFixedPowerButtonArmed = true;
return NTLSTATUS_SUCCESS;
}
// Acknowledges the fixed-button source only; the SCI may carry unrelated events.
static bool AcpiConsumeFixedButton(void) {
if (!gFixedPowerButtonArmed) return false;
bool pressed = false;
if (AcpiReadFixedRegister(&gPm1aStatus) & ACPI_PM1_POWER_BUTTON_BIT) {
AcpiWriteFixedRegister(&gPm1aStatus, ACPI_PM1_POWER_BUTTON_BIT);
pressed = true;
}
if (gPm1bStatus.Address &&
(AcpiReadFixedRegister(&gPm1bStatus) & ACPI_PM1_POWER_BUTTON_BIT)) {
AcpiWriteFixedRegister(&gPm1bStatus, ACPI_PM1_POWER_BUTTON_BIT);
pressed = true;
}
return pressed;
}
// Detects whether PM1 control is using the standard Intel PCH PMBASE layout.
static void AcpiDetectIntelPchPmBase(void) {
gIntelPchPmBase = 0;
@@ -490,10 +580,20 @@ static void ParseFadt(const ACPISDTHeader* header) {
memset(&gPm1aCnt, 0, sizeof(gPm1aCnt));
memset(&gPm1bCnt, 0, sizeof(gPm1bCnt));
memset(&gPm1aStatus, 0, sizeof(gPm1aStatus));
memset(&gPm1bStatus, 0, sizeof(gPm1bStatus));
memset(&gPm1aEnable, 0, sizeof(gPm1aEnable));
memset(&gPm1bEnable, 0, sizeof(gPm1bEnable));
gSciIrq = 0;
if (len >= FADT_SCI_INT_OFFSET + sizeof(gSciIrq))
memcpy(&gSciIrq, (const uint8_t*)fadt + FADT_SCI_INT_OFFSET, sizeof(gSciIrq));
memset(&gSleepControl, 0, sizeof(gSleepControl));
gLegacyPm1aPort = 0;
gLegacyPm1bPort = 0;
gFadtFlags = AcpiReadU32(fadt, len, FADT_FLAGS_OFFSET);
if (AcpiReadByteGasRegister(fadt, len, FADT_RESET_REG_OFFSET, &gResetRegister) &&
FADT_RESET_VALUE_OFFSET < len)
gResetValue = *((const uint8_t*)fadt + FADT_RESET_VALUE_OFFSET);
gHwReducedAcpi = (gFadtFlags & FADT_FLAG_HW_REDUCED_ACPI) != 0;
uint8_t pm1CntLength = FADT_PM1_CNT_LEN_OFFSET < len
@@ -528,6 +628,16 @@ static void ParseFadt(const ACPISDTHeader* header) {
if (gHwReducedAcpi)
(void)AcpiReadByteGasRegister(fadt, len, FADT_SLEEP_CONTROL_OFFSET, &gSleepControl);
uint8_t eventLength = FADT_PM1_EVT_LEN_OFFSET < len ?
*((const uint8_t*)fadt + FADT_PM1_EVT_LEN_OFFSET) : 0u;
if (!gHwReducedAcpi && (eventLength == 4u || eventLength == 8u)) {
uint8_t half = eventLength / 2u;
AcpiConfigurePm1EventBlock(fadt, len, FADT_PM1A_EVT_BLK_OFFSET,
FADT_X_PM1A_EVT_BLK_OFFSET, half, &gPm1aStatus, &gPm1aEnable);
AcpiConfigurePm1EventBlock(fadt, len, FADT_PM1B_EVT_BLK_OFFSET,
FADT_X_PM1B_EVT_BLK_OFFSET, half, &gPm1bStatus, &gPm1bEnable);
}
gSmiCommandPort = AcpiReadU32(fadt, len, FADT_SMI_CMD_OFFSET);
gAcpiEnableValue = FADT_ACPI_ENABLE_OFFSET < len
? *((const uint8_t*)fadt + FADT_ACPI_ENABLE_OFFSET)
@@ -599,6 +709,15 @@ static void ParseMadt(MADT* madt) {
HalAddCpuRecord(uid, lapicId, flags);
} else if (type == 1 && len >= 12) { // I/O APIC entry
gIoapicPhys = *(uint32_t*)(p + 4);
uint32_t base;
memcpy(&base, p + 8, sizeof(base));
HalApicSetGsiBase(base);
} else if (type == 2 && len >= 10 && p[2] == 0) { // ISA source override
uint32_t gsi;
uint16_t flags;
memcpy(&gsi, p + 4, sizeof(gsi));
memcpy(&flags, p + 8, sizeof(flags));
HalApicSetIsaOverride(p[3], gsi, flags);
} else if (type == 5 && len >= 12) { // Local APIC Address Override
gLapicPhys = (uintptr_t)*(uint64_t*)(p + 4);
} else if (type == 9 && len >= 16) { // Processor Local x2APIC
@@ -796,6 +915,19 @@ static void HalShutdown(void) {
HalStopProcessor();
}
static void HalReset(void) {
(void)HalDisableInterrupts();
if (gResetRegister.Address && gResetValue)
AcpiWriteFixedRegister(&gResetRegister, gResetValue);
if (gApi.Timer.Stall) gApi.Timer.Stall(100000u);
__outbyte(0xCF9u, 0x06u);
if (gApi.Timer.Stall) gApi.Timer.Stall(100000u);
__outbyte(0x64u, 0xFEu);
if (gApi.Timer.Stall) gApi.Timer.Stall(100000u);
HalDbgPrint("HAL: reset failed\n");
HalStopProcessor();
}
static KSTATUS HalQueryProcessorTopology(HAL_PROCESSOR_TOPOLOGY* out) {
if (!out) return NTLSTATUS_INVALID_PARAMETER;
@@ -863,6 +995,7 @@ HAL_ENTRY KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) {
HalDbgPrint("HAL: LAPIC=%016llx IOAPIC=%016llx HPET=%016llx\n",
gLapicPhys, gIoapicPhys, gHpetPhys);
HalApicSetSciIrq(gSciIrq);
HalApicInitialize(gLapicPhys, gIoapicPhys);
HalDbgPrint("HAL: local APIC mode=%s BSP_ID=%u\n",
HalApicUsingX2Apic() ? "x2APIC" : "xAPIC",
@@ -874,6 +1007,10 @@ HAL_ENTRY KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) {
HalRtcInitialize(&gApi.Rtc);
HalPciInitialize(&gApi.Pci);
gApi.Power.Shutdown = HalShutdown;
gApi.Power.Reset = HalReset;
gApi.Power.QueryFixedButtonIrq = AcpiQueryFixedButtonIrq;
gApi.Power.ArmFixedButton = AcpiArmFixedButton;
gApi.Power.ConsumeFixedButton = AcpiConsumeFixedButton;
AcpiDetectIntelPchPmBase();
gInitialised = 1;