Kernel: Rework AML package and implement indexing in to packages
This commit is contained in:
parent
0bf45069bd
commit
693f90449f
|
@ -16,6 +16,7 @@ set(KERNEL_SOURCES
|
|||
kernel/ACPI/AML/NamedObject.cpp
|
||||
kernel/ACPI/AML/Namespace.cpp
|
||||
kernel/ACPI/AML/Node.cpp
|
||||
kernel/ACPI/AML/Package.cpp
|
||||
kernel/ACPI/AML/Scope.cpp
|
||||
kernel/APIC.cpp
|
||||
kernel/BootInfo.cpp
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <kernel/ACPI/AML/Buffer.h>
|
||||
#include <kernel/ACPI/AML/Node.h>
|
||||
#include <kernel/ACPI/AML/Package.h>
|
||||
#include <kernel/ACPI/AML/ParseContext.h>
|
||||
#include <kernel/ACPI/AML/Reference.h>
|
||||
|
||||
|
@ -52,8 +53,17 @@ namespace Kernel::ACPI::AML
|
|||
break;
|
||||
}
|
||||
case AML::Node::Type::Package:
|
||||
AML_TODO("IndexOp source Package");
|
||||
return ParseResult::Failure;
|
||||
{
|
||||
auto package = static_cast<AML::Package*>(source.ptr());
|
||||
if (index.value() >= package->elements.size())
|
||||
{
|
||||
AML_ERROR("IndexOp index is out of package bounds");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
auto package_element = package->elements[index.value()];
|
||||
result = MUST(BAN::RefPtr<AML::Reference>::create(package_element));
|
||||
break;
|
||||
}
|
||||
case AML::Node::Type::String:
|
||||
AML_TODO("IndexOp source String");
|
||||
return ParseResult::Failure;
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace Kernel::ACPI::AML
|
|||
Namespace,
|
||||
OpRegion,
|
||||
Package,
|
||||
PackageElement,
|
||||
PowerResource,
|
||||
Processor,
|
||||
Reference,
|
||||
|
|
|
@ -8,109 +8,124 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct PackageElement;
|
||||
|
||||
struct Package : public AML::Node
|
||||
{
|
||||
struct UnresolvedReference
|
||||
{
|
||||
AML::NameString name;
|
||||
size_t index;
|
||||
};
|
||||
BAN::Vector<UnresolvedReference> unresolved_references;
|
||||
AML::NameString scope; // Used for resolving references
|
||||
BAN::Vector<BAN::RefPtr<PackageElement>> elements;
|
||||
AML::NameString scope;
|
||||
|
||||
BAN::Vector<BAN::RefPtr<AML::Node>> elements;
|
||||
|
||||
Package(BAN::Vector<BAN::RefPtr<AML::Node>>&& elements, BAN::Vector<UnresolvedReference>&& unresolved_references, AML::NameString scope)
|
||||
Package(AML::NameString scope)
|
||||
: Node(Node::Type::Package)
|
||||
, elements(BAN::move(elements))
|
||||
, unresolved_references(BAN::move(unresolved_references))
|
||||
, scope(scope)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override
|
||||
{
|
||||
// resolve references
|
||||
for (auto& reference : unresolved_references)
|
||||
{
|
||||
auto object = Namespace::root_namespace()->find_object(scope, reference.name, Namespace::FindMode::Normal);
|
||||
if (!object)
|
||||
{
|
||||
AML_ERROR("Failed to resolve reference {} in package", reference.name);
|
||||
return {};
|
||||
}
|
||||
ASSERT(!elements[reference.index]);
|
||||
elements[reference.index] = object;
|
||||
}
|
||||
unresolved_references.clear();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static ParseResult parse(AML::ParseContext& context)
|
||||
static ParseResult parse(AML::ParseContext& context);
|
||||
virtual void debug_print(int indent) const override;
|
||||
};
|
||||
|
||||
struct PackageElement : public AML::Node
|
||||
{
|
||||
BAN::RefPtr<AML::Package> parent;
|
||||
BAN::RefPtr<AML::Node> element;
|
||||
AML::NameString unresolved_name;
|
||||
bool resolved = false;
|
||||
bool initialized = false;
|
||||
|
||||
PackageElement(BAN::RefPtr<AML::Package> parent, BAN::RefPtr<AML::Node> element)
|
||||
: Node(Node::Type::PackageElement)
|
||||
, parent(parent)
|
||||
, element(element)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::PackageOp);
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
ASSERT(element);
|
||||
resolved = true;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
auto package_pkg = AML::parse_pkg(context.aml_data);
|
||||
if (!package_pkg.has_value())
|
||||
return ParseResult::Failure;
|
||||
PackageElement(BAN::RefPtr<AML::Package> parent, AML::NameString unresolved_name)
|
||||
: Node(Node::Type::PackageElement)
|
||||
, parent(parent)
|
||||
, unresolved_name(unresolved_name)
|
||||
{
|
||||
resolved = false;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
auto package_context = context;
|
||||
package_context.aml_data = package_pkg.value();
|
||||
PackageElement(BAN::RefPtr<AML::Package> parent)
|
||||
: Node(Node::Type::PackageElement)
|
||||
, parent(parent)
|
||||
, unresolved_name(unresolved_name)
|
||||
{
|
||||
resolved = false;
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
if (package_pkg->size() < 1)
|
||||
return ParseResult::Failure;
|
||||
uint8_t num_elements = package_context.aml_data[0];
|
||||
package_context.aml_data = package_context.aml_data.slice(1);
|
||||
|
||||
BAN::Vector<BAN::RefPtr<AML::Node>> elements;
|
||||
BAN::Vector<UnresolvedReference> unresolved_references;
|
||||
while (elements.size() < num_elements && package_context.aml_data.size() > 0)
|
||||
BAN::RefPtr<AML::Node> evaluate() override
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
BAN::RefPtr<AML::Node> element;
|
||||
|
||||
// Store name strings as references
|
||||
if (package_context.aml_data[0] != 0x00 && AML::NameString::can_parse(package_context.aml_data))
|
||||
{
|
||||
auto name = AML::NameString::parse(package_context.aml_data);
|
||||
if (!name.has_value())
|
||||
return ParseResult::Failure;
|
||||
MUST(unresolved_references.push_back(UnresolvedReference { .name = name.value(), .index = elements.size() }));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto element_result = AML::parse_object(package_context);
|
||||
if (!element_result.success())
|
||||
return ParseResult::Failure;
|
||||
element = element_result.node();
|
||||
}
|
||||
|
||||
MUST(elements.push_back(element));
|
||||
AML_ERROR("Trying to evaluate uninitialized PackageElement");
|
||||
return {};
|
||||
}
|
||||
while (elements.size() < num_elements)
|
||||
MUST(elements.push_back(BAN::RefPtr<AML::Node>()));
|
||||
if (!resolved)
|
||||
{
|
||||
auto object = Namespace::root_namespace()->find_object(parent->scope, unresolved_name, Namespace::FindMode::Normal);
|
||||
if (!object)
|
||||
{
|
||||
AML_ERROR("Failed to resolve reference {} in package {}", unresolved_name, parent->scope);
|
||||
return {};
|
||||
}
|
||||
element = object;
|
||||
resolved = true;
|
||||
}
|
||||
return element->evaluate();
|
||||
}
|
||||
|
||||
auto package = MUST(BAN::RefPtr<Package>::create(BAN::move(elements), BAN::move(unresolved_references), context.scope));
|
||||
return ParseResult(package);
|
||||
static ParseResult parse(AML::ParseContext& context, BAN::RefPtr<AML::Package> package)
|
||||
{
|
||||
BAN::RefPtr<AML::PackageElement> element;
|
||||
if (context.aml_data[0] != 0x00 && AML::NameString::can_parse(context.aml_data))
|
||||
{
|
||||
auto name = AML::NameString::parse(context.aml_data);
|
||||
if (!name.has_value())
|
||||
return ParseResult::Failure;
|
||||
element = MUST(BAN::RefPtr<PackageElement>::create(package, name.value()));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto element_result = AML::parse_object(context);
|
||||
if (!element_result.success())
|
||||
return ParseResult::Failure;
|
||||
element = MUST(BAN::RefPtr<PackageElement>::create(package, element_result.node()));
|
||||
}
|
||||
return ParseResult(element);
|
||||
}
|
||||
|
||||
virtual void debug_print(int indent) const override
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("Package {");
|
||||
AML_DEBUG_PRINTLN("");
|
||||
for (const auto& element : elements)
|
||||
AML_DEBUG_PRINTLN("PackageElement {");
|
||||
if (!initialized)
|
||||
{
|
||||
if (element)
|
||||
element->debug_print(indent + 1);
|
||||
else
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent + 1);
|
||||
AML_DEBUG_PRINT("Uninitialized");
|
||||
}
|
||||
AML_DEBUG_PRINTLN("");
|
||||
AML_DEBUG_PRINT_INDENT(indent + 1);
|
||||
AML_DEBUG_PRINT("Uninitialized");
|
||||
}
|
||||
else if (!resolved)
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent + 1);
|
||||
AML_DEBUG_PRINT("Unresolved {}", unresolved_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
element->debug_print(indent + 1);
|
||||
}
|
||||
AML_DEBUG_PRINTLN("");
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("}");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#include <kernel/ACPI/AML/Package.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
AML::ParseResult AML::Package::parse(AML::ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::PackageOp);
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
|
||||
auto package_pkg = AML::parse_pkg(context.aml_data);
|
||||
if (!package_pkg.has_value())
|
||||
return ParseResult::Failure;
|
||||
|
||||
auto package_context = context;
|
||||
package_context.aml_data = package_pkg.value();
|
||||
|
||||
if (package_pkg->size() < 1)
|
||||
return ParseResult::Failure;
|
||||
uint8_t num_elements = package_context.aml_data[0];
|
||||
package_context.aml_data = package_context.aml_data.slice(1);
|
||||
|
||||
auto package = MUST(BAN::RefPtr<Package>::create(context.scope));
|
||||
while (package->elements.size() < num_elements && package_context.aml_data.size() > 0)
|
||||
{
|
||||
auto element_result = PackageElement::parse(package_context, package);
|
||||
if (!element_result.success())
|
||||
return ParseResult::Failure;
|
||||
ASSERT(element_result.node() && element_result.node()->type == Node::Type::PackageElement);
|
||||
auto element = static_cast<PackageElement*>(element_result.node().ptr());
|
||||
MUST(package->elements.push_back(element));
|
||||
}
|
||||
while (package->elements.size() < num_elements)
|
||||
{
|
||||
auto uninitialized = MUST(BAN::RefPtr<PackageElement>::create(package));
|
||||
MUST(package->elements.push_back(uninitialized));
|
||||
}
|
||||
|
||||
return ParseResult(package);
|
||||
}
|
||||
|
||||
void AML::Package::debug_print(int indent) const
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("Package {");
|
||||
AML_DEBUG_PRINTLN("");
|
||||
for (const auto& element : elements)
|
||||
{
|
||||
element->debug_print(indent + 1);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
}
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("}");
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue