From ba667148af04963f5d70c647511ea1fad1add21d Mon Sep 17 00:00:00 2001 From: salmonik Date: Fri, 31 Jul 2026 16:01:46 +0200 Subject: power: proper shutdown via UEFI ResetSystem (ACPI S5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - uefi.rs: full EFI_RUNTIME_SERVICES layout with reset_system at index 10 (spec order); EfiResetSystem type + RESET_* constants - power.rs: stash the runtime-services table pre-EBS; poweroff() calls ResetSystem(EfiResetShutdown) — still callable after ExitBootServices because we never call SetVirtualAddressMap, so the pointers keep working with physical addresses; falls back to the hlt loop - shell: 'poweroff' and 'exit' shut the machine down (QEMU exits), 'halt' keeps the plain hlt loop --- rsnix/src/uefi.rs | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'rsnix/src/uefi.rs') diff --git a/rsnix/src/uefi.rs b/rsnix/src/uefi.rs index 619739e..b1b5e48 100644 --- a/rsnix/src/uefi.rs +++ b/rsnix/src/uefi.rs @@ -86,12 +86,42 @@ pub struct SimpleTextInput { } // --------------------------------------------------------------------------- -// Runtime services (stub — we don't use them) +// Runtime services // --------------------------------------------------------------------------- + +/// `EFI_RESET_SYSTEM` — ResetType, ResetStatus, DataSize, ResetData. +/// ResetType: 0 cold, 1 warm, 2 shutdown, 3 platform-specific. +pub type EfiResetSystem = + unsafe extern "efiapi" fn(u32, u64, usize, *const u16) -> Status; + +pub const RESET_COLD: u32 = 0; +#[allow(dead_code)] +pub const RESET_WARM: u32 = 1; +pub const RESET_SHUTDOWN: u32 = 2; +#[allow(dead_code)] +pub const RESET_PLATFORM_SPECIFIC: u32 = 3; + +/// EFI_RUNTIME_SERVICES — function pointers in spec order after the header. +/// We only use ResetSystem; the rest stay opaque. The table remains +/// callable after ExitBootServices because we never call SetVirtualAddressMap, +/// so the pointers keep working with physical (identity) addresses. #[repr(C)] pub struct RuntimeServices { _hdr: TableHeader, - _reserved: [*mut c_void; 30], + _get_time: *mut c_void, // 0 + _set_time: *mut c_void, // 1 + _get_wakeup_time: *mut c_void, // 2 + _set_wakeup_time: *mut c_void, // 3 + _set_virtual_address_map: *mut c_void, // 4 + _convert_pointer: *mut c_void, // 5 + _get_variable: *mut c_void, // 6 + _get_next_variable_name: *mut c_void, // 7 + _set_variable: *mut c_void, // 8 + _get_next_high_monotonic_count: *mut c_void, // 9 + pub reset_system: EfiResetSystem, // 10 + _update_capsule: *mut c_void, // 11 + _query_capsule_capabilities: *mut c_void, // 12 + _query_variable_info: *mut c_void, // 13 } // --------------------------------------------------------------------------- -- cgit v1.2.3