Files
MontaukOS/kernel/src/Api/Power.hpp
T

75 lines
2.4 KiB
C++

/*
* Power.hpp
* SYS_RESET, SYS_SHUTDOWN, SYS_SUSPEND syscalls
* Copyright (c) 2026 Daniel Hammer
*/
#pragma once
#include <cstdint>
#include <Efi/UEFI.hpp>
#include <Memory/Paging.hpp>
#include <Io/IoPort.hpp>
#include <Graphics/Cursor.hpp>
#include <ACPI/AcpiShutdown.hpp>
#include <ACPI/AcpiSleep.hpp>
#include "Syscall.hpp"
namespace Montauk {
// Pending graceful power-off request, set by the desktop and consumed by
// login.elf. Kernel-global IPC channel (one outstanding request system-wide).
// `inline` so the single definition is shared across translation units.
inline int g_pendingPowerAction = POWER_REQ_QUERY;
// SYS_POWER_REQUEST. action == POWER_REQ_QUERY reads and clears the pending
// action; any other value records it as the pending action. Returns the
// pending action for queries, or 0 when recording one.
static int64_t Sys_PowerRequest(int action) {
if (action == POWER_REQ_QUERY) {
int pending = g_pendingPowerAction;
g_pendingPowerAction = POWER_REQ_QUERY;
return (int64_t)pending;
}
g_pendingPowerAction = action;
return 0;
}
static void Sys_Reset() {
if (Efi::g_ResetSystem) {
/* Switch to kernel PML4 which has identity-mapped UEFI runtime regions */
Memory::VMM::LoadCR3(Memory::VMM::g_paging->PML4);
Efi::g_ResetSystem(Efi::EfiResetCold, 0, 0, nullptr);
}
/* Fallback: triple fault via null IDT */
struct [[gnu::packed]] { uint16_t limit; uint64_t base; } nullIdt = {0, 0};
asm volatile("lidt %0; int $0x03" :: "m"(nullIdt));
__builtin_unreachable();
}
static void Sys_Shutdown() {
/* Primary: ACPI S5 shutdown via PM1 control registers */
if (Hal::AcpiShutdown::IsAvailable()) {
Hal::AcpiShutdown::Shutdown();
}
/* Fallback: EFI ResetSystem */
if (Efi::g_ResetSystem) {
Memory::VMM::LoadCR3(Memory::VMM::g_paging->PML4);
Efi::g_ResetSystem(Efi::EfiResetShutdown, 0, 0, nullptr);
}
/* Last resort: halt the CPU */
asm volatile("cli; hlt");
__builtin_unreachable();
}
static int64_t Sys_Suspend() {
if (!Hal::AcpiSleep::IsS3Available()) {
return -1; // S3 not supported
}
return (int64_t)Hal::AcpiSleep::Suspend();
}
};