Kernel: Rework AML namespace and object hierarchy
Remove tree-like structure from AML. This allows more spec compliant parsing of named objects inside not yet declared devices. This also allows AML to be run thread safely. All object adds/removes are now guarded by a mutex.
This commit is contained in:
@@ -42,11 +42,13 @@ namespace Kernel::ACPI::AML
|
||||
AML_DEBUG_PRINT("Device ");
|
||||
name.debug_print();
|
||||
AML_DEBUG_PRINTLN(" {");
|
||||
for (const auto& [name, object] : objects)
|
||||
{
|
||||
object->debug_print(indent + 1);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
}
|
||||
Namespace::root_namespace()->for_each_child(scope,
|
||||
[&](const auto&, const auto& child)
|
||||
{
|
||||
child->debug_print(indent + 1);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
}
|
||||
);
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("}");
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Kernel::ACPI::AML
|
||||
if (!method_scope.has_value())
|
||||
return ParseResult::Failure;
|
||||
method->term_list = method_pkg.value();
|
||||
method->scope = method_scope.release_value();
|
||||
method->scope = AML::NameString(method_scope.release_value());
|
||||
|
||||
#if AML_DEBUG_LEVEL >= 2
|
||||
method->debug_print(0);
|
||||
|
||||
@@ -36,6 +36,14 @@ namespace Kernel::ACPI::AML
|
||||
aml_data = aml_data.slice(4);
|
||||
}
|
||||
|
||||
BAN::StringView sv() const
|
||||
{
|
||||
size_t len = 4;
|
||||
while (len > 0 && chars[len - 1] == '_')
|
||||
len--;
|
||||
return BAN::StringView(chars, len);
|
||||
}
|
||||
|
||||
static BAN::Optional<NameSeg> parse(BAN::ConstByteSpan& aml_data)
|
||||
{
|
||||
if (aml_data.size() < 4)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/HashMap.h>
|
||||
#include <kernel/ACPI/AML/Scope.h>
|
||||
#include <kernel/ACPI/Headers.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
@@ -11,12 +12,34 @@ namespace Kernel::ACPI::AML
|
||||
{
|
||||
static BAN::RefPtr<AML::Namespace> root_namespace();
|
||||
|
||||
template<typename F>
|
||||
static void for_each_child(const AML::NameString& scope, const F& callback)
|
||||
{
|
||||
auto canonical_path = root_namespace()->resolve_path({}, scope);
|
||||
ASSERT(canonical_path.has_value());
|
||||
|
||||
for (auto& [path, child] : root_namespace()->m_objects)
|
||||
{
|
||||
if (path.size() < canonical_path->size() + 1)
|
||||
continue;
|
||||
if (path[canonical_path->size()] != '.')
|
||||
continue;
|
||||
if (path.sv().substring(0, canonical_path->size()) != canonical_path->sv())
|
||||
continue;
|
||||
if (path.sv().substring(canonical_path->size() + 1).contains('.'))
|
||||
continue;
|
||||
callback(path, child);
|
||||
}
|
||||
}
|
||||
|
||||
Namespace(NameSeg name) : AML::Scope(Node::Type::Namespace, name) {}
|
||||
|
||||
static BAN::RefPtr<AML::Namespace> create_root_namespace();
|
||||
bool parse(const SDTHeader& header);
|
||||
|
||||
BAN::Optional<AML::NameString> resolve_path(const AML::NameString& relative_base, const AML::NameString& relative_path);
|
||||
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);
|
||||
|
||||
// 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);
|
||||
@@ -26,6 +49,10 @@ namespace Kernel::ACPI::AML
|
||||
|
||||
// Remove an object from the namespace. Returns false if the object could not be removed.
|
||||
bool remove_named_object(const AML::NameString& absolute_path);
|
||||
|
||||
private:
|
||||
BAN::HashMap<BAN::String, BAN::RefPtr<NamedObject>> m_objects;
|
||||
mutable Mutex m_object_mutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/HashMap.h>
|
||||
#include <kernel/ACPI/AML/NamedObject.h>
|
||||
#include <kernel/ACPI/AML/Names.h>
|
||||
|
||||
@@ -9,7 +8,6 @@ namespace Kernel::ACPI::AML
|
||||
|
||||
struct Scope : public AML::NamedObject
|
||||
{
|
||||
BAN::HashMap<NameSeg, BAN::RefPtr<NamedObject>> objects;
|
||||
AML::NameString scope;
|
||||
|
||||
Scope(Node::Type type, NameSeg name)
|
||||
@@ -19,7 +17,6 @@ namespace Kernel::ACPI::AML
|
||||
virtual bool is_scope() const override { return true; }
|
||||
|
||||
static ParseResult parse(ParseContext& context);
|
||||
virtual void debug_print(int indent) const override;
|
||||
|
||||
protected:
|
||||
ParseResult enter_context_and_parse_term_list(ParseContext& outer_context, const AML::NameString& name, BAN::ConstByteSpan aml_data);
|
||||
|
||||
Reference in New Issue
Block a user