temp
This commit is contained in:
1 parent
d36f19509c
commit
30d20457f0
309 files changed
+121746
-1963
No files matched your search
+85
-48
@@ -1,14 +1,13 @@
|
||||
#include <ntlite/atomic.h>
|
||||
// Kernel power coordinator and optional firmware-provider binding.
|
||||
|
||||
#include <ntlite/syscall.h>
|
||||
#include <ntlite/ddk/power.h>
|
||||
#include <kernel/ke_power.h>
|
||||
#include <kernel/ke_process.h>
|
||||
#include <kernel/ke_event.h>
|
||||
#include <kernel/ke_spinlock.h>
|
||||
#include <kernel/ke_irq.h>
|
||||
#include <kernel/ke_dpc.h>
|
||||
#include <kernel/ke_settings.h>
|
||||
#include <kernel/ke_debug.h>
|
||||
#include <kernel/hal/hal_api.h>
|
||||
#include <string.h>
|
||||
|
||||
static SPINLOCK gPowerLock = SPINLOCK_INIT;
|
||||
@@ -17,9 +16,12 @@ static EVENT* gPowerComplete;
|
||||
static PROCESS* gInit;
|
||||
static uint32_t gAction;
|
||||
static bool gCommitted;
|
||||
static const HAL_API* gButtonHal;
|
||||
static bool gPolicyReady;
|
||||
static bool gEarlyButtonPressed;
|
||||
static uint32_t gButtonAction;
|
||||
static KDPC gPowerButtonDpc;
|
||||
static NTL_FIRMWARE_POWER_PROVIDER gFirmwareProvider;
|
||||
static bool gFirmwarePrepared;
|
||||
static uint32_t gPreparedAction;
|
||||
|
||||
KSTATUS KePowerInitialize(void) {
|
||||
if (gPowerRequest) return NTLSTATUS_ALREADY_EXISTS;
|
||||
@@ -29,58 +31,93 @@ KSTATUS KePowerInitialize(void) {
|
||||
return st;
|
||||
}
|
||||
|
||||
// Delivers the physical action after interrupt-exit processing.
|
||||
static void KiPowerButtonDpc(KDPC* dpc, void* context, void* arg1, void* arg2) {
|
||||
(void)dpc;
|
||||
(void)context;
|
||||
(void)arg1;
|
||||
(void)arg2;
|
||||
(void)KePowerRequestHardware(gButtonAction);
|
||||
// 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;
|
||||
}
|
||||
|
||||
// The ACPI SCI handler only acknowledges the fixed event and queues normal work.
|
||||
static void KiPowerButtonIsr(void) {
|
||||
if (!gButtonHal || !gButtonHal->Power.ConsumeFixedButton ||
|
||||
!gButtonHal->Power.ConsumeFixedButton()) return;
|
||||
(void)KeInsertQueueDpc(&gPowerButtonDpc, NULL, NULL);
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Reads immutable boot-time button policy and attaches it to the fixed ACPI SCI.
|
||||
void KePowerInitializeButton(const HAL_API* hal) {
|
||||
// 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);
|
||||
if (strcmp(mode, "ignore") == 0) {
|
||||
DbgPrint("power: ACPI power button ignored by policy\n");
|
||||
return;
|
||||
}
|
||||
if (strcmp(mode, "shutdown") == 0) gButtonAction = SYS_POWER_ACTION_SHUTDOWN;
|
||||
else if (strcmp(mode, "restart") == 0) gButtonAction = SYS_POWER_ACTION_RESTART;
|
||||
else KePanic(KE_PANIC_CODE_INIT, "power: invalid [power] button=%s\n", mode);
|
||||
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);
|
||||
|
||||
if (!hal || !hal->Power.QueryFixedButtonIrq || !hal->Power.ArmFixedButton ||
|
||||
!hal->Power.ConsumeFixedButton) {
|
||||
DbgPrint("power: no ACPI fixed power button HAL support\n");
|
||||
return;
|
||||
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);
|
||||
}
|
||||
uint8_t irq = 0;
|
||||
status = hal->Power.QueryFixedButtonIrq(&irq);
|
||||
if (!KSUCCESS(status)) {
|
||||
DbgPrint("power: ACPI fixed button unavailable (0x%x); AML button not yet supported\n", status);
|
||||
return;
|
||||
}
|
||||
// The IOAPIC is still masked for this IRQ. Arm the firmware source first,
|
||||
// then install the kernel handler and finally unmask via KeIrqRegister.
|
||||
status = hal->Power.ArmFixedButton();
|
||||
if (!KSUCCESS(status)) {
|
||||
DbgPrint("power: cannot arm fixed button IRQ %u, status=0x%x\n", irq, status);
|
||||
return;
|
||||
}
|
||||
KeInitializeDpc(&gPowerButtonDpc, KiPowerButtonDpc, NULL);
|
||||
gButtonHal = hal;
|
||||
KeIrqRegister(irq, KiPowerButtonIsr);
|
||||
DbgPrint("power: ACPI fixed button armed on IRQ %u, action=%s\n", irq, mode);
|
||||
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) {
|
||||
|
||||
Reference in new issue
Block a user