feat: add support for shutdown/reboot via UEFI Runtime Services
This commit is contained in:
+20
-10
@@ -6,23 +6,33 @@
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <Efi/UEFI.hpp>
|
||||
#include <Memory/Paging.hpp>
|
||||
|
||||
namespace Zenith {
|
||||
|
||||
static void Sys_Reset() {
|
||||
/*
|
||||
Triple fault for now; TODO: implement UEFI runtime function for clean reboot.
|
||||
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);
|
||||
}
|
||||
|
||||
We implement the triple fault by loading a null IDT into the IDT register,
|
||||
and then immediately triggering an interrupt.
|
||||
|
||||
This technique should pretty much work across the board but it's of course
|
||||
better to use the UEFI runtime API as it has a method for this purpose,
|
||||
along with shutdown.
|
||||
*/
|
||||
|
||||
/* 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() {
|
||||
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::EfiResetShutdown, 0, 0, nullptr);
|
||||
}
|
||||
|
||||
/* No fallback for shutdown; halt the CPU */
|
||||
asm volatile("cli; hlt");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user