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/NamedObject.cpp
|
||||||
kernel/ACPI/AML/Namespace.cpp
|
kernel/ACPI/AML/Namespace.cpp
|
||||||
kernel/ACPI/AML/Node.cpp
|
kernel/ACPI/AML/Node.cpp
|
||||||
|
kernel/ACPI/AML/Package.cpp
|
||||||
kernel/ACPI/AML/Scope.cpp
|
kernel/ACPI/AML/Scope.cpp
|
||||||
kernel/APIC.cpp
|
kernel/APIC.cpp
|
||||||
kernel/BootInfo.cpp
|
kernel/BootInfo.cpp
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <kernel/ACPI/AML/Buffer.h>
|
#include <kernel/ACPI/AML/Buffer.h>
|
||||||
#include <kernel/ACPI/AML/Node.h>
|
#include <kernel/ACPI/AML/Node.h>
|
||||||
|
#include <kernel/ACPI/AML/Package.h>
|
||||||
#include <kernel/ACPI/AML/ParseContext.h>
|
#include <kernel/ACPI/AML/ParseContext.h>
|
||||||
#include <kernel/ACPI/AML/Reference.h>
|
#include <kernel/ACPI/AML/Reference.h>
|
||||||
|
|
||||||
|
@ -52,8 +53,17 @@ namespace Kernel::ACPI::AML
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AML::Node::Type::Package:
|
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:
|
case AML::Node::Type::String:
|
||||||
AML_TODO("IndexOp source String");
|
AML_TODO("IndexOp source String");
|
||||||
return ParseResult::Failure;
|
return ParseResult::Failure;
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace Kernel::ACPI::AML
|
||||||
Namespace,
|
Namespace,
|
||||||
OpRegion,
|
OpRegion,
|
||||||
Package,
|
Package,
|
||||||
|
PackageElement,
|
||||||
PowerResource,
|
PowerResource,
|
||||||
Processor,
|
Processor,
|
||||||
Reference,
|
Reference,
|
||||||
|
|
|
@ -8,109 +8,124 @@
|
||||||
namespace Kernel::ACPI::AML
|
namespace Kernel::ACPI::AML
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct PackageElement;
|
||||||
|
|
||||||
struct Package : public AML::Node
|
struct Package : public AML::Node
|
||||||
{
|
{
|
||||||
struct UnresolvedReference
|
BAN::Vector<BAN::RefPtr<PackageElement>> elements;
|
||||||
{
|
AML::NameString scope;
|
||||||
AML::NameString name;
|
|
||||||
size_t index;
|
|
||||||
};
|
|
||||||
BAN::Vector<UnresolvedReference> unresolved_references;
|
|
||||||
AML::NameString scope; // Used for resolving references
|
|
||||||
|
|
||||||
BAN::Vector<BAN::RefPtr<AML::Node>> elements;
|
Package(AML::NameString scope)
|
||||||
|
|
||||||
Package(BAN::Vector<BAN::RefPtr<AML::Node>>&& elements, BAN::Vector<UnresolvedReference>&& unresolved_references, AML::NameString scope)
|
|
||||||
: Node(Node::Type::Package)
|
: Node(Node::Type::Package)
|
||||||
, elements(BAN::move(elements))
|
, elements(BAN::move(elements))
|
||||||
, unresolved_references(BAN::move(unresolved_references))
|
|
||||||
, scope(scope)
|
, scope(scope)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
BAN::RefPtr<AML::Node> evaluate() override
|
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;
|
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(element);
|
||||||
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::PackageOp);
|
resolved = true;
|
||||||
context.aml_data = context.aml_data.slice(1);
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
auto package_pkg = AML::parse_pkg(context.aml_data);
|
PackageElement(BAN::RefPtr<AML::Package> parent, AML::NameString unresolved_name)
|
||||||
if (!package_pkg.has_value())
|
: Node(Node::Type::PackageElement)
|
||||||
return ParseResult::Failure;
|
, parent(parent)
|
||||||
|
, unresolved_name(unresolved_name)
|
||||||
|
{
|
||||||
|
resolved = false;
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
auto package_context = context;
|
PackageElement(BAN::RefPtr<AML::Package> parent)
|
||||||
package_context.aml_data = package_pkg.value();
|
: Node(Node::Type::PackageElement)
|
||||||
|
, parent(parent)
|
||||||
|
, unresolved_name(unresolved_name)
|
||||||
|
{
|
||||||
|
resolved = false;
|
||||||
|
initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (package_pkg->size() < 1)
|
BAN::RefPtr<AML::Node> evaluate() override
|
||||||
return ParseResult::Failure;
|
{
|
||||||
uint8_t num_elements = package_context.aml_data[0];
|
if (!initialized)
|
||||||
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> element;
|
AML_ERROR("Trying to evaluate uninitialized PackageElement");
|
||||||
|
return {};
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
while (elements.size() < num_elements)
|
if (!resolved)
|
||||||
MUST(elements.push_back(BAN::RefPtr<AML::Node>()));
|
{
|
||||||
|
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));
|
static ParseResult parse(AML::ParseContext& context, BAN::RefPtr<AML::Package> package)
|
||||||
return ParseResult(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
|
virtual void debug_print(int indent) const override
|
||||||
{
|
{
|
||||||
AML_DEBUG_PRINT_INDENT(indent);
|
AML_DEBUG_PRINT_INDENT(indent);
|
||||||
AML_DEBUG_PRINT("Package {");
|
AML_DEBUG_PRINTLN("PackageElement {");
|
||||||
AML_DEBUG_PRINTLN("");
|
if (!initialized)
|
||||||
for (const auto& element : elements)
|
|
||||||
{
|
{
|
||||||
if (element)
|
AML_DEBUG_PRINT_INDENT(indent + 1);
|
||||||
element->debug_print(indent + 1);
|
AML_DEBUG_PRINT("Uninitialized");
|
||||||
else
|
|
||||||
{
|
|
||||||
AML_DEBUG_PRINT_INDENT(indent + 1);
|
|
||||||
AML_DEBUG_PRINT("Uninitialized");
|
|
||||||
}
|
|
||||||
AML_DEBUG_PRINTLN("");
|
|
||||||
}
|
}
|
||||||
|
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_INDENT(indent);
|
||||||
AML_DEBUG_PRINT("}");
|
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