Kernel: AML add flag to force absolute lookup for ACPI namespace

This commit is contained in:
Bananymous 2024-04-16 17:37:08 +03:00
parent e667326df5
commit 7707e01352
9 changed files with 32 additions and 37 deletions

View File

@ -54,12 +54,7 @@ namespace Kernel::ACPI::AML
)); ));
if (!Namespace::root_namespace()->add_named_object(context, name_string.value(), method)) if (!Namespace::root_namespace()->add_named_object(context, name_string.value(), method))
return ParseResult::Failure; return ParseResult::Failure;
auto method_scope = Namespace::root_namespace()->resolve_path(context.scope, name_string.value());
if (!method_scope.has_value())
return ParseResult::Failure;
method->term_list = method_pkg.value(); method->term_list = method_pkg.value();
method->scope = AML::NameString(method_scope.release_value());
#if AML_DEBUG_LEVEL >= 2 #if AML_DEBUG_LEVEL >= 2
method->debug_print(0); method->debug_print(0);

View File

@ -15,7 +15,7 @@ namespace Kernel::ACPI::AML
template<typename F> template<typename F>
static void for_each_child(const AML::NameString& scope, const F& callback) static void for_each_child(const AML::NameString& scope, const F& callback)
{ {
auto canonical_path = root_namespace()->resolve_path({}, scope); auto canonical_path = root_namespace()->resolve_path(scope, {}, FindMode::ForceAbsolute);
ASSERT(canonical_path.has_value()); ASSERT(canonical_path.has_value());
for (auto& [path, child] : root_namespace()->m_objects) for (auto& [path, child] : root_namespace()->m_objects)
@ -39,10 +39,15 @@ namespace Kernel::ACPI::AML
void debug_print(int indent) const override; void debug_print(int indent) const override;
BAN::Optional<BAN::String> resolve_path(const AML::NameString& relative_base, const AML::NameString& relative_path, bool allow_nonexistent = false); enum class FindMode
{
Normal,
ForceAbsolute,
};
BAN::Optional<BAN::String> resolve_path(const AML::NameString& relative_base, const AML::NameString& relative_path, FindMode mode, bool check_existence = true) const;
// Find an object in the namespace. Returns nullptr if the object is not found. // Find an object in the namespace. Returns nullptr if the object is not found.
BAN::RefPtr<NamedObject> find_object(const AML::NameString& relative_base, const AML::NameString& relative_path); BAN::RefPtr<NamedObject> find_object(const AML::NameString& relative_base, const AML::NameString& relative_path, FindMode mode);
// Add an object to the namespace. Returns false if the parent object could not be added. // Add an object to the namespace. Returns false if the parent object could not be added.
bool add_named_object(ParseContext&, const AML::NameString& object_path, BAN::RefPtr<NamedObject> object); bool add_named_object(ParseContext&, const AML::NameString& object_path, BAN::RefPtr<NamedObject> object);

View File

@ -32,7 +32,7 @@ namespace Kernel::ACPI::AML
// resolve references // resolve references
for (auto& reference : unresolved_references) for (auto& reference : unresolved_references)
{ {
auto object = Namespace::root_namespace()->find_object(scope, reference.name); auto object = Namespace::root_namespace()->find_object(scope, reference.name, Namespace::FindMode::Normal);
if (!object) if (!object)
{ {
AML_ERROR("Failed to resolve reference {} in package", reference.name); AML_ERROR("Failed to resolve reference {} in package", reference.name);

View File

@ -54,7 +54,7 @@ namespace Kernel::ACPI::AML
auto name = NameString::parse(context.aml_data); auto name = NameString::parse(context.aml_data);
if (!name.has_value()) if (!name.has_value())
return ParseResult::Failure; return ParseResult::Failure;
object = Namespace::root_namespace()->find_object(context.scope, name.value()); object = Namespace::root_namespace()->find_object(context.scope, name.value(), Namespace::FindMode::Normal);
} }
else else
{ {

View File

@ -354,7 +354,7 @@ acpi_release_global_lock:
return; return;
} }
auto s5_object = m_namespace->find_object({}, AML::NameString("\\_S5")); auto s5_object = m_namespace->find_object({}, AML::NameString("_S5"), AML::Namespace::FindMode::ForceAbsolute);
if (!s5_object) if (!s5_object)
{ {
dwarnln("\\_S5 not found"); dwarnln("\\_S5 not found");
@ -386,7 +386,7 @@ acpi_release_global_lock:
return; return;
} }
auto pts_object = m_namespace->find_object({}, AML::NameString("\\_PTS")); auto pts_object = m_namespace->find_object({}, AML::NameString("_PTS"), AML::Namespace::FindMode::ForceAbsolute);
if (pts_object && pts_object->type == AML::Node::Type::Method) if (pts_object && pts_object->type == AML::Node::Type::Method)
{ {
auto* method = static_cast<AML::Method*>(pts_object.ptr()); auto* method = static_cast<AML::Method*>(pts_object.ptr());
@ -465,7 +465,7 @@ acpi_release_global_lock:
dprintln("Initializing devices"); dprintln("Initializing devices");
// Initialize \\_SB // Initialize \\_SB
auto _sb = m_namespace->find_object({}, AML::NameString("\\_SB")); auto _sb = m_namespace->find_object({}, AML::NameString("_SB"), AML::Namespace::FindMode::ForceAbsolute);
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());
@ -473,7 +473,7 @@ acpi_release_global_lock:
} }
// Evaluate \\_PIC (mode) // Evaluate \\_PIC (mode)
auto _pic = m_namespace->find_object({}, AML::NameString("\\_PIC")); auto _pic = m_namespace->find_object({}, AML::NameString("_PIC"), AML::Namespace::FindMode::ForceAbsolute);
if (_pic && _pic->type == AML::Node::Type::Method) if (_pic && _pic->type == AML::Node::Type::Method)
{ {
auto* method = static_cast<AML::Method*>(_pic.ptr()); auto* method = static_cast<AML::Method*>(_pic.ptr());

View File

@ -404,7 +404,7 @@ namespace Kernel::ACPI
if (!name_string.has_value()) if (!name_string.has_value())
return ParseResult::Failure; return ParseResult::Failure;
auto op_region = Namespace::root_namespace()->find_object(context.scope, name_string.value()); auto op_region = Namespace::root_namespace()->find_object(context.scope, name_string.value(), Namespace::FindMode::Normal);
if (!op_region || op_region->type != AML::Node::Type::OpRegion) if (!op_region || op_region->type != AML::Node::Type::OpRegion)
{ {
AML_ERROR("FieldOp: {} does not name a valid OpRegion", name_string.value()); AML_ERROR("FieldOp: {} does not name a valid OpRegion", name_string.value());
@ -532,7 +532,7 @@ namespace Kernel::ACPI
auto index_field_element_name = NameString::parse(field_pkg); auto index_field_element_name = NameString::parse(field_pkg);
if (!index_field_element_name.has_value()) if (!index_field_element_name.has_value())
return ParseResult::Failure; return ParseResult::Failure;
auto index_field_element = Namespace::root_namespace()->find_object(context.scope, index_field_element_name.value()); auto index_field_element = Namespace::root_namespace()->find_object(context.scope, index_field_element_name.value(), Namespace::FindMode::Normal);
if (!index_field_element || index_field_element->type != AML::Node::Type::FieldElement) if (!index_field_element || index_field_element->type != AML::Node::Type::FieldElement)
{ {
AML_ERROR("IndexField IndexName does not name a valid FieldElement"); AML_ERROR("IndexField IndexName does not name a valid FieldElement");
@ -542,7 +542,7 @@ namespace Kernel::ACPI
auto data_field_element_name = NameString::parse(field_pkg); auto data_field_element_name = NameString::parse(field_pkg);
if (!data_field_element_name.has_value()) if (!data_field_element_name.has_value())
return ParseResult::Failure; return ParseResult::Failure;
auto data_field_element = Namespace::root_namespace()->find_object(context.scope, data_field_element_name.value()); auto data_field_element = Namespace::root_namespace()->find_object(context.scope, data_field_element_name.value(), Namespace::FindMode::Normal);
if (!data_field_element || data_field_element->type != AML::Node::Type::FieldElement) if (!data_field_element || data_field_element->type != AML::Node::Type::FieldElement)
{ {
AML_ERROR("IndexField DataName does not name a valid FieldElement"); AML_ERROR("IndexField DataName does not name a valid FieldElement");
@ -694,7 +694,7 @@ namespace Kernel::ACPI
auto op_region_name = NameString::parse(field_pkg); auto op_region_name = NameString::parse(field_pkg);
if (!op_region_name.has_value()) if (!op_region_name.has_value())
return ParseResult::Failure; return ParseResult::Failure;
auto op_region = Namespace::root_namespace()->find_object(context.scope, op_region_name.value()); auto op_region = Namespace::root_namespace()->find_object(context.scope, op_region_name.value(), Namespace::FindMode::Normal);
if (!op_region || op_region->type != AML::Node::Type::OpRegion) if (!op_region || op_region->type != AML::Node::Type::OpRegion)
{ {
AML_ERROR("BankField RegionName {} does not name a valid OpRegion", op_region_name.value()); AML_ERROR("BankField RegionName {} does not name a valid OpRegion", op_region_name.value());
@ -704,7 +704,7 @@ namespace Kernel::ACPI
auto bank_selector_name = NameString::parse(field_pkg); auto bank_selector_name = NameString::parse(field_pkg);
if (!bank_selector_name.has_value()) if (!bank_selector_name.has_value())
return ParseResult::Failure; return ParseResult::Failure;
auto bank_selector = Namespace::root_namespace()->find_object(context.scope, bank_selector_name.value()); auto bank_selector = Namespace::root_namespace()->find_object(context.scope, bank_selector_name.value(), Namespace::FindMode::Normal);
if (!bank_selector) if (!bank_selector)
{ {
AML_ERROR("BankField BankSelector {} does not name a valid object", bank_selector_name.value()); AML_ERROR("BankField BankSelector {} does not name a valid object", bank_selector_name.value());

View File

@ -37,7 +37,7 @@ namespace Kernel::ACPI
} }
BAN::Optional<BAN::String> AML::Namespace::resolve_path(const AML::NameString& relative_base, const AML::NameString& relative_path, bool allow_nonexistent) BAN::Optional<BAN::String> AML::Namespace::resolve_path(const AML::NameString& relative_base, const AML::NameString& relative_path, FindMode mode, bool check_existence) const
{ {
LockGuard _(m_object_mutex); LockGuard _(m_object_mutex);
@ -45,7 +45,7 @@ namespace Kernel::ACPI
ASSERT(relative_base.prefix == "\\"sv || relative_base.path.empty()); ASSERT(relative_base.prefix == "\\"sv || relative_base.path.empty());
// Do absolute path lookup // Do absolute path lookup
if (!relative_path.prefix.empty() || relative_path.path.size() != 1 || allow_nonexistent) if (!relative_path.prefix.empty() || relative_path.path.size() != 1 || mode == FindMode::ForceAbsolute)
{ {
BAN::String absolute_path; BAN::String absolute_path;
MUST(absolute_path.push_back('\\')); MUST(absolute_path.push_back('\\'));
@ -77,7 +77,7 @@ namespace Kernel::ACPI
if (absolute_path.back() == '.') if (absolute_path.back() == '.')
absolute_path.pop_back(); absolute_path.pop_back();
if (allow_nonexistent || m_objects.contains(absolute_path)) if (!check_existence || m_objects.contains(absolute_path))
return absolute_path; return absolute_path;
return {}; return {};
} }
@ -118,11 +118,11 @@ namespace Kernel::ACPI
return {}; return {};
} }
BAN::RefPtr<AML::NamedObject> AML::Namespace::find_object(const AML::NameString& relative_base, const AML::NameString& relative_path) BAN::RefPtr<AML::NamedObject> AML::Namespace::find_object(const AML::NameString& relative_base, const AML::NameString& relative_path, FindMode mode)
{ {
LockGuard _(m_object_mutex); LockGuard _(m_object_mutex);
auto canonical_path = resolve_path(relative_base, relative_path); auto canonical_path = resolve_path(relative_base, relative_path, mode);
if (!canonical_path.has_value()) if (!canonical_path.has_value())
return nullptr; return nullptr;
@ -139,14 +139,9 @@ namespace Kernel::ACPI
ASSERT(!object_path.path.empty()); ASSERT(!object_path.path.empty());
ASSERT(object_path.path.back() == object->name); ASSERT(object_path.path.back() == object->name);
auto canonical_path = resolve_path(parse_context.scope, object_path, true); auto canonical_path = resolve_path(parse_context.scope, object_path, FindMode::ForceAbsolute, false);
ASSERT(canonical_path.has_value()); ASSERT(canonical_path.has_value());
ASSERT(!canonical_path->empty());
if (canonical_path->empty())
{
AML_ERROR("Trying to add root namespace");
return false;
}
if (m_objects.contains(canonical_path.value())) if (m_objects.contains(canonical_path.value()))
{ {
@ -172,7 +167,7 @@ namespace Kernel::ACPI
{ {
LockGuard _(m_object_mutex); LockGuard _(m_object_mutex);
auto canonical_path = resolve_path({}, absolute_path); auto canonical_path = resolve_path({}, absolute_path, FindMode::ForceAbsolute);
if (!canonical_path.has_value()) if (!canonical_path.has_value())
{ {
AML_ERROR("Trying to delete non-existent object '{}'", absolute_path); AML_ERROR("Trying to delete non-existent object '{}'", absolute_path);

View File

@ -191,7 +191,7 @@ namespace Kernel::ACPI
auto name_string = AML::NameString::parse(context.aml_data); auto name_string = AML::NameString::parse(context.aml_data);
if (!name_string.has_value()) if (!name_string.has_value())
return ParseResult::Failure; return ParseResult::Failure;
auto aml_object = Namespace::root_namespace()->find_object(context.scope, name_string.value()); auto aml_object = Namespace::root_namespace()->find_object(context.scope, name_string.value(), Namespace::FindMode::Normal);
if (!aml_object) if (!aml_object)
{ {
AML_ERROR("NameString {} not found in namespace", name_string.value()); AML_ERROR("NameString {} not found in namespace", name_string.value());

View File

@ -20,7 +20,7 @@ namespace Kernel::ACPI
if (!name_string.has_value()) if (!name_string.has_value())
return ParseResult::Failure; return ParseResult::Failure;
auto named_object = Namespace::root_namespace()->find_object(context.scope, name_string.value()); auto named_object = Namespace::root_namespace()->find_object(context.scope, name_string.value(), Namespace::FindMode::Normal);
if (!named_object) if (!named_object)
{ {
AML_ERROR("Scope '{}' not found in namespace", name_string.value()); AML_ERROR("Scope '{}' not found in namespace", name_string.value());
@ -38,7 +38,7 @@ namespace Kernel::ACPI
AML::ParseResult AML::Scope::enter_context_and_parse_term_list(ParseContext& outer_context, const AML::NameString& name_string, BAN::ConstByteSpan aml_data) AML::ParseResult AML::Scope::enter_context_and_parse_term_list(ParseContext& outer_context, const AML::NameString& name_string, BAN::ConstByteSpan aml_data)
{ {
auto resolved_scope = Namespace::root_namespace()->resolve_path(outer_context.scope, name_string); auto resolved_scope = Namespace::root_namespace()->resolve_path(outer_context.scope, name_string, Namespace::FindMode::Normal);
if (!resolved_scope.has_value()) if (!resolved_scope.has_value())
return ParseResult::Failure; return ParseResult::Failure;
@ -96,7 +96,7 @@ namespace Kernel::ACPI
bool run_ini = true; bool run_ini = true;
bool init_children = true; bool init_children = true;
if (auto sta = Namespace::root_namespace()->find_object(scope->scope, AML::NameString("_STA"sv))) if (auto sta = Namespace::root_namespace()->find_object(scope->scope, AML::NameString("_STA"sv), Namespace::FindMode::ForceAbsolute))
{ {
auto result = evaluate_or_invoke(sta); auto result = evaluate_or_invoke(sta);
if (!result.has_value()) if (!result.has_value())
@ -111,7 +111,7 @@ namespace Kernel::ACPI
if (run_ini) if (run_ini)
{ {
auto ini = Namespace::root_namespace()->find_object(scope->scope, AML::NameString("_INI"sv)); auto ini = Namespace::root_namespace()->find_object(scope->scope, AML::NameString("_INI"sv), Namespace::FindMode::ForceAbsolute);
if (ini) if (ini)
{ {
if (ini->type != AML::Node::Type::Method) if (ini->type != AML::Node::Type::Method)