From 1a6a425d194705dfb8a227207e512c7d5cac4b8c Mon Sep 17 00:00:00 2001 From: Dennis Bonke Date: Wed, 2 Oct 2024 01:52:33 +0200 Subject: [PATCH] thor: Handle shutting down from userspace --- kernel/thor/system/acpi/pm-interface.cpp | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/kernel/thor/system/acpi/pm-interface.cpp b/kernel/thor/system/acpi/pm-interface.cpp index 3dfe4f91bd..d5542529f9 100644 --- a/kernel/thor/system/acpi/pm-interface.cpp +++ b/kernel/thor/system/acpi/pm-interface.cpp @@ -71,6 +71,53 @@ struct PmInterfaceBusObject : private KernelBusObject { infoLogger() << "thor: Reset using PS/2 controller failed" << frg::endlog; #endif panicLogger() << "thor: We do not know how to reset" << frg::endlog; + } else if(preamble.id() == bragi::message_id) { + auto req = bragi::parse_head_only(reqBuffer, *kernelAlloc); + + if(!req) { + infoLogger() << "thor: Closing lane due to illegal HW request." << frg::endlog; + co_return Error::protocolViolation; + } + + uacpi_sleep_state state = UACPI_SLEEP_STATE_S0; + switch(req->cmd()) { + case 5: + state = UACPI_SLEEP_STATE_S5; + break; + case 6: { + auto ret = uacpi_reboot(); + if(uacpi_unlikely_error(ret)) + infoLogger() << "thor: ACPI reset failed: " << uacpi_status_to_string(ret) << frg::endlog; + +#ifdef __x86_64__ + issuePs2Reset(); + infoLogger() << "thor: Reset using PS/2 controller failed" << frg::endlog; +#endif + panicLogger() << "thor: We do not know how to reset" << frg::endlog; + break; + } + default: + infoLogger() << "thor: Unhandled reboot request" << frg::endlog; + co_return frg::success; + } + + auto ret = uacpi_prepare_for_sleep_state(state); + if(uacpi_unlikely_error(ret)) + infoLogger() << "thor: Preparing to enter sleep state S" << (int)state << " failed: " << uacpi_status_to_string(ret) << frg::endlog; + + // uACPI Documentation states that you must call uacpi_enter_sleep_state with interrupts disabled. + disableInts(); + + ret = uacpi_enter_sleep_state(state); + if(uacpi_unlikely_error(ret)) + infoLogger() << "thor: Entering sleep state S" << (int)state << " failed: " << uacpi_status_to_string(ret) << frg::endlog; + + // Either reboot failed, poweroff failed, or someone is funny and thinks we can suspend. + // Either way, return succes. + + // Oops, re-enable before returning. + enableInts(); + co_return frg::success; }else{ infoLogger() << "thor: Dismissing conversation due to illegal HW request." << frg::endlog; co_await DismissSender{conversation};