// Kernel power coordinator and optional firmware-provider binding. #include #include #include #include #include #include #include #include #include static SPINLOCK gPowerLock = SPINLOCK_INIT; static EVENT* gPowerRequest; static EVENT* gPowerComplete; static PROCESS* gInit; static uint32_t gAction; static bool gCommitted; static bool gPolicyReady; static bool gEarlyButtonPressed; static uint32_t gButtonAction; static NTL_FIRMWARE_POWER_PROVIDER gFirmwareProvider; static bool gFirmwarePrepared; static uint32_t gPreparedAction; KSTATUS KePowerInitialize(void) { if (gPowerRequest) return NTLSTATUS_ALREADY_EXISTS; KSTATUS st = KeEventCreate(EventManualReset, false, &gPowerRequest); if (!KSUCCESS(st)) return st; st = KeEventCreate(EventManualReset, false, &gPowerComplete); return st; } // The resident firmware owner may be ACPICA or another platform implementation. __declspec(dllexport) KSTATUS KeRegisterFirmwarePowerProvider( const NTL_FIRMWARE_POWER_PROVIDER* provider) { if (!provider || provider->Size != sizeof(*provider) || !provider->Prepare || !provider->Enter) return NTLSTATUS_INVALID_PARAMETER; uintptr_t flags = KeAcquireSpinlock(&gPowerLock); KSTATUS status = gFirmwareProvider.Size ? NTLSTATUS_ALREADY_EXISTS : NTLSTATUS_SUCCESS; if (KSUCCESS(status)) gFirmwareProvider = *provider; KeReleaseSpinlock(&gPowerLock, flags); if (KSUCCESS(status)) DbgPrint("power: firmware provider registered\n"); return status; } // Events before system-root policy becomes available are retained once. __declspec(dllexport) KSTATUS KeNotifyPowerButton(void) { uintptr_t flags = KeAcquireSpinlock(&gPowerLock); if (!gPowerRequest) { KeReleaseSpinlock(&gPowerLock, flags); return NTLSTATUS_NOT_SUPPORTED; } if (!gPolicyReady) { gEarlyButtonPressed = true; KeReleaseSpinlock(&gPowerLock, flags); return NTLSTATUS_SUCCESS; } uint32_t action = gButtonAction; KeReleaseSpinlock(&gPowerLock, flags); return action ? KePowerRequestHardware(action) : NTLSTATUS_SUCCESS; } // System-root policy is loaded independently of the presence of a firmware driver. void KePowerInitializePolicy(void) { char mode[24]; KSTATUS status = KeGetSettingString("power", "button", mode, sizeof(mode)); if (!KSUCCESS(status)) KePanic(KE_PANIC_CODE_INIT, "power: missing [power] button, status=0x%x\n", status); uint32_t action = 0; if (strcmp(mode, "shutdown") == 0) action = SYS_POWER_ACTION_SHUTDOWN; else if (strcmp(mode, "restart") == 0) action = SYS_POWER_ACTION_RESTART; else if (strcmp(mode, "ignore") != 0) KePanic(KE_PANIC_CODE_INIT, "power: invalid [power] button=%s\n", mode); uintptr_t flags = KeAcquireSpinlock(&gPowerLock); gButtonAction = action; gPolicyReady = true; bool pending = gEarlyButtonPressed; bool providerPresent = gFirmwareProvider.Size != 0; gEarlyButtonPressed = false; KeReleaseSpinlock(&gPowerLock, flags); DbgPrint("power: button policy=%s firmware provider=%s\n", mode, providerPresent ? "present" : "absent"); if (pending && action) (void)KePowerRequestHardware(action); } // A provider prepares firmware while threads, device resources and AML can run. KSTATUS KePowerPrepareFirmware(uint32_t action) { if (action != SYS_POWER_ACTION_SHUTDOWN && action != SYS_POWER_ACTION_RESTART) return NTLSTATUS_INVALID_PARAMETER; NTL_FIRMWARE_POWER_PROVIDER provider; uintptr_t flags = KeAcquireSpinlock(&gPowerLock); provider = gFirmwareProvider; KeReleaseSpinlock(&gPowerLock, flags); if (!provider.Size) return NTLSTATUS_NOT_SUPPORTED; flags = KeAcquireSpinlock(&gPowerLock); gFirmwarePrepared = false; gPreparedAction = 0; KeReleaseSpinlock(&gPowerLock, flags); KSTATUS status = provider.Prepare(provider.Context, action); if (KSUCCESS(status)) { flags = KeAcquireSpinlock(&gPowerLock); gFirmwarePrepared = true; gPreparedAction = action; KeReleaseSpinlock(&gPowerLock, flags); } return status; } // Any returned transition leaves the HAL as the supported final fallback. KSTATUS KePowerEnterFirmware(uint32_t action) { NTL_FIRMWARE_POWER_PROVIDER provider; uintptr_t flags = KeAcquireSpinlock(&gPowerLock); bool prepared = gFirmwarePrepared && gPreparedAction == action; provider = gFirmwareProvider; KeReleaseSpinlock(&gPowerLock, flags); if (!prepared || !provider.Size) return NTLSTATUS_NOT_SUPPORTED; return provider.Enter(provider.Context, action); } void KePowerSetInitProcess(PROCESS* init) { uintptr_t flags = KeAcquireSpinlock(&gPowerLock); gInit = init; KeReleaseSpinlock(&gPowerLock, flags); } // Records one power transition under the coordinator lock. The hardware event // may arrive before init exists; syscall-originated requests require init. static KSTATUS KiPowerQueueRequest(uint32_t action, bool requireInit) { if (action != SYS_POWER_ACTION_SHUTDOWN && action != SYS_POWER_ACTION_RESTART) return NTLSTATUS_INVALID_PARAMETER; uintptr_t flags = KeAcquireSpinlock(&gPowerLock); KSTATUS status = NTLSTATUS_SUCCESS; if (!gPowerRequest || (requireInit && !gInit)) status = NTLSTATUS_NOT_SUPPORTED; else if (gAction) status = NTLSTATUS_ALREADY_EXISTS; else gAction = action; KeReleaseSpinlock(&gPowerLock, flags); if (KSUCCESS(status)) KeSignalEvent(gPowerRequest); return status; } // Accepts a privileged explicit power request only after init exists. KSTATUS KePowerRequest(uint32_t action) { return KiPowerQueueRequest(action, true); } // Latches a physical power-button request even during init startup. KSTATUS KePowerRequestHardware(uint32_t action) { return KiPowerQueueRequest(action, false); } EVENT* KePowerRequestEvent(PROCESS* caller) { uintptr_t flags = KeAcquireSpinlock(&gPowerLock); EVENT* event = caller && caller == gInit ? gPowerRequest : (EVENT*)0; KeReleaseSpinlock(&gPowerLock, flags); return event; } KSTATUS KePowerGetRequest(PROCESS* caller, uint32_t* actionOut) { if (!actionOut) return NTLSTATUS_INVALID_PARAMETER; uintptr_t flags = KeAcquireSpinlock(&gPowerLock); KSTATUS st = caller && caller == gInit ? NTLSTATUS_SUCCESS : NTLSTATUS_ACCESS_DENIED; if (KSUCCESS(st)) *actionOut = gAction; KeReleaseSpinlock(&gPowerLock, flags); return st; } KSTATUS KePowerComplete(PROCESS* caller, uint32_t action) { uintptr_t flags = KeAcquireSpinlock(&gPowerLock); KSTATUS st = caller && caller == gInit ? NTLSTATUS_SUCCESS : NTLSTATUS_ACCESS_DENIED; if (KSUCCESS(st) && (!gAction || action != gAction || gCommitted)) st = NTLSTATUS_INVALID_PARAMETER; if (KSUCCESS(st)) gCommitted = true; KeReleaseSpinlock(&gPowerLock, flags); if (KSUCCESS(st)) KeSignalEvent(gPowerComplete); return st; } EVENT* KePowerCompletionEvent(void) { return gPowerComplete; } uint32_t KePowerCommittedAction(void) { uintptr_t flags = KeAcquireSpinlock(&gPowerLock); uint32_t result = gCommitted ? gAction : 0; KeReleaseSpinlock(&gPowerLock, flags); return result; }