2#include "pedigree/kernel/Log.h"
3#include "pedigree/kernel/machine/Machine.h"
4#include "pedigree/kernel/machine/PciFirmware.h"
5#include "pedigree/kernel/utilities/StaticString.h"
10#include "modules/Module.h"
11#include <uacpi/namespace.h>
12#include <uacpi/sleep.h>
13#include <uacpi/uacpi.h>
16#include "system/kernel/machine/mach_pc/Acpi.h"
21bool prepareShutdown(
bool powerOff);
22Acpi::PowerManagement powerManagement{&prepareShutdown,
nullptr,
nullptr};
23bool sleepPrepared =
false;
24uacpi_status sleepPreparationResult = UACPI_STATUS_OK;
26char sleepLogSnapshot[4096];
28bool prepareShutdown(
bool powerOff) {
29 if (powerOff && powerManagement.powerOff) {
31 installAcpiEcHandlersForShutdown();
32 NOTICE(
"ACPI: preparing S5 via uACPI");
33 const auto result = uacpi_prepare_for_sleep_state(UACPI_SLEEP_STATE_S5);
34 sleepPreparationResult = result;
35 sleepPrepared = result == UACPI_STATUS_OK;
36 sleepPreparationDetail.clear();
42 for (
size_t i = 0; i < bytes; ++i) {
43 if (sleepLogSnapshot[i] !=
'\n') {
48 if (entry.contains(
"ACPI: preparing S5 via uACPI")) {
49 sleepPreparationDetail.clear();
50 }
else if (entry.contains(
"unable to attach") && entry.contains(
"operation region")) {
51 sleepPreparationDetail = entry;
52 }
else if (!sleepPreparationDetail.length() && entry.contains(
"error while evaluating")) {
53 sleepPreparationDetail = entry;
56 ERROR(
"ACPI: S5 preparation failed: " << uacpi_status_to_string(result));
60 return shutdownAcpiEvents();
63const char* powerOff() {
69 message +=
"ACPI: S5 preparation failed: ";
70 message += uacpi_status_to_string(sleepPreparationResult);
71 if (sleepPreparationDetail.length()) {
73 message += sleepPreparationDetail;
77 NOTICE_NOLOCK(
"ACPI: entering S5 via uACPI");
79 const auto result = uacpi_enter_sleep_state(UACPI_SLEEP_STATE_S5);
80 message +=
"ACPI: S5 entry returned: ";
81 message += uacpi_status_to_string(result);
82 ERROR_NOLOCK(
static_cast<const char*
>(
message));
87 NOTICE_NOLOCK(
"ACPI: resetting via uACPI");
89 const auto result = uacpi_reboot();
90 ERROR_NOLOCK(
"ACPI: reset returned: " << uacpi_status_to_string(result));
95 uacpi_phys_addr rsdp = 0;
96 if (uacpi_kernel_get_rsdp(&rsdp) != UACPI_STATUS_OK) {
97 (void)PciFirmware::discover();
100 if (!initialiseAcpiEvents()) {
103 uacpi_status result = uacpi_initialize(UACPI_FLAG_BAD_CSUM_FATAL);
105 if (result == UACPI_STATUS_OK) {
106 powerManagement.reset = &reset;
109 if (result == UACPI_STATUS_OK) {
110 result = uacpi_namespace_load();
112 if (result == UACPI_STATUS_OK) {
113 result = uacpi_namespace_initialize();
115 if (result != UACPI_STATUS_OK) {
116 ERROR(
"ACPI: namespace unavailable: " << uacpi_status_to_string(result));
118 Acpi::instance().setPowerManagement(&powerManagement);
122 NOTICE(
"ACPI: AML namespace initialized");
124 uacpi_namespace_node* s5 =
nullptr;
125 if (uacpi_namespace_node_find(uacpi_namespace_root(),
"_S5", &s5) == UACPI_STATUS_OK) {
126 powerManagement.powerOff = &powerOff;
128 Acpi::instance().setPowerManagement(&powerManagement);
130 (void)PciFirmware::discover();
131 initialisePciRouting();
137MODULE_INFO_NON_UNLOADABLE(
"acpi", &entry, &exit);
static EXPORTED_PUBLIC Log & instance()
EXPORTED_PUBLIC size_t copyText(char *buffer, size_t capacity)
static void setShutdownPhase(ShutdownPhase phase, const char *detail=nullptr)