Kernel: Cleanup AML device initialization

_STA and _INI are now properly called on call devices
This commit is contained in:
Bananymous 2024-04-12 02:00:30 +03:00
parent 46b5a7697c
commit 89c4abc07a
6 changed files with 77 additions and 94 deletions

View File

@ -12,7 +12,6 @@ set(KERNEL_SOURCES
font/prefs.psf.o font/prefs.psf.o
kernel/ACPI/ACPI.cpp kernel/ACPI/ACPI.cpp
kernel/ACPI/AML.cpp kernel/ACPI/AML.cpp
kernel/ACPI/AML/Device.cpp
kernel/ACPI/AML/Field.cpp kernel/ACPI/AML/Field.cpp
kernel/ACPI/AML/NamedObject.cpp kernel/ACPI/AML/NamedObject.cpp
kernel/ACPI/AML/Namespace.cpp kernel/ACPI/AML/Namespace.cpp

View File

@ -52,6 +52,4 @@ namespace Kernel::ACPI::AML
} }
}; };
bool initialize_device(BAN::RefPtr<NamedObject> device);
} }

View File

@ -25,4 +25,6 @@ namespace Kernel::ACPI::AML
ParseResult enter_context_and_parse_term_list(ParseContext& outer_context, const AML::NameString& name, BAN::ConstByteSpan aml_data); ParseResult enter_context_and_parse_term_list(ParseContext& outer_context, const AML::NameString& name, BAN::ConstByteSpan aml_data);
}; };
bool initialize_scope(BAN::RefPtr<Scope> scope);
} }

View File

@ -462,28 +462,12 @@ acpi_release_global_lock:
dprintln("Initializing devices"); dprintln("Initializing devices");
// Evaluate \\_SB._INI // Initialize \\_SB
auto _sb_ini = m_namespace->find_object({}, AML::NameString("\\_SB._INI"));
if (_sb_ini && _sb_ini->type == AML::Node::Type::Method)
{
auto* method = static_cast<AML::Method*>(_sb_ini.ptr());
if (method->arg_count != 0)
{
dwarnln("Method \\_SB._INI has {} arguments, expected 0", method->arg_count);
return BAN::Error::from_errno(EINVAL);
}
BAN::Vector<uint8_t> sync_stack;
method->evaluate({}, sync_stack);
}
// Initialize devices
auto _sb = m_namespace->find_object({}, AML::NameString("\\_SB")); auto _sb = m_namespace->find_object({}, AML::NameString("\\_SB"));
if (_sb && _sb->is_scope()) if (_sb && _sb->is_scope())
{ {
auto* scope = static_cast<AML::Scope*>(_sb.ptr()); auto* scope = static_cast<AML::Scope*>(_sb.ptr());
for (auto& [name, object] : scope->objects) AML::initialize_scope(scope);
if (object->type == AML::Node::Type::Device || object->type == AML::Node::Type::Processor)
AML::initialize_device(object);
} }
// Evaluate \\_PIC (mode) // Evaluate \\_PIC (mode)

View File

@ -1,73 +0,0 @@
#include <kernel/ACPI/AML/Device.h>
namespace Kernel::ACPI
{
bool AML::initialize_device(BAN::RefPtr<AML::NamedObject> device)
{
bool run_ini = true;
bool init_children = true;
ASSERT(device->type == Node::Type::Device || device->type == Node::Type::Processor);
ASSERT(device->is_scope());
auto* scope = static_cast<Scope*>(device.ptr());
auto it = scope->objects.find(NameSeg("_STA"sv));
if (it != scope->objects.end() && it->value->type == Node::Type::Method)
{
auto* method = static_cast<Method*>(it->value.ptr());
if (method->arg_count != 0)
{
AML_ERROR("Method {}._STA has {} arguments, expected 0", scope, method->arg_count);
return false;
}
BAN::Vector<uint8_t> sync_stack;
auto result = method->evaluate({}, sync_stack);
if (!result.has_value())
{
AML_ERROR("Failed to evaluate {}._STA", scope);
return false;
}
if (!result.value())
{
AML_ERROR("Failed to evaluate {}._STA, return value is null", scope);
return false;
}
auto result_val = result.value()->as_integer();
if (!result_val.has_value())
{
AML_ERROR("Failed to evaluate {}._STA, return value could not be resolved to integer", scope);
AML_ERROR(" Return value: ");
result.value()->debug_print(0);
return false;
}
run_ini = (result_val.value() & 0x01);
init_children = run_ini || (result_val.value() & 0x02);
}
if (run_ini)
{
auto it = scope->objects.find(NameSeg("_STA"sv));
if (it != scope->objects.end() && it->value->type == Node::Type::Method)
{
auto* method = static_cast<Method*>(it->value.ptr());
if (method->arg_count != 0)
{
AML_ERROR("Method {}._INI has {} arguments, expected 0", scope, method->arg_count);
return false;
}
BAN::Vector<uint8_t> sync_stack;
method->evaluate({}, sync_stack);
}
}
bool success = true;
if (init_children)
for (auto& [_, child] : scope->objects)
if (child->type == Node::Type::Device || child->type == Node::Type::Processor)
if (!initialize_device(child))
success = false;
return success;
}
}

View File

@ -79,4 +79,77 @@ namespace Kernel::ACPI
AML_DEBUG_PRINT("}"); AML_DEBUG_PRINT("}");
} }
bool AML::initialize_scope(BAN::RefPtr<AML::Scope> scope)
{
#if AML_DEBUG_LEVEL >= 2
AML_DEBUG_PRINTLN("Initializing {}", scope->scope);
#endif
bool run_ini = true;
bool init_children = true;
auto it = scope->objects.find(NameSeg("_STA"sv));
if (scope->type != AML::Node::Type::Namespace && it != scope->objects.end() && it->value->type == Node::Type::Method)
{
auto* method = static_cast<Method*>(it->value.ptr());
if (method->arg_count != 0)
{
AML_ERROR("Method {}._STA has {} arguments, expected 0", scope->scope, method->arg_count);
return false;
}
BAN::Vector<uint8_t> sync_stack;
auto result = method->evaluate({}, sync_stack);
if (!result.has_value())
{
AML_ERROR("Failed to evaluate {}._STA", scope->scope);
return false;
}
if (!result.value())
{
AML_ERROR("Failed to evaluate {}._STA, return value is null", scope->scope);
return false;
}
auto result_val = result.value()->as_integer();
if (!result_val.has_value())
{
AML_ERROR("Failed to evaluate {}._STA, return value could not be resolved to integer", scope->scope);
AML_ERROR(" Return value: ");
result.value()->debug_print(0);
return false;
}
run_ini = (result_val.value() & 0x01);
init_children = run_ini || (result_val.value() & 0x02);
}
if (run_ini)
{
auto it = scope->objects.find(NameSeg("_STA"sv));
if (it != scope->objects.end() && it->value->type == Node::Type::Method)
{
auto* method = static_cast<Method*>(it->value.ptr());
if (method->arg_count != 0)
{
AML_ERROR("Method {}._INI has {} arguments, expected 0", scope->scope, method->arg_count);
return false;
}
BAN::Vector<uint8_t> sync_stack;
method->evaluate({}, sync_stack);
}
}
bool success = true;
if (init_children)
{
for (auto& [_, child] : scope->objects)
{
if (!child->is_scope())
continue;
auto* child_scope = static_cast<Scope*>(child.ptr());
if (!initialize_scope(child_scope))
success = false;
}
}
return success;
}
} }