banan-os/kernel/include/kernel/ACPI/AML/Package.h

86 lines
2.3 KiB
C++

#pragma once
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Pkg.h>
namespace Kernel::ACPI::AML
{
struct Package : public AML::Node
{
BAN::Vector<BAN::RefPtr<AML::Node>> elements;
Package() : Node(Node::Type::Package) {}
BAN::RefPtr<AML::Node> evaluate() override
{
BAN::Vector<BAN::RefPtr<AML::Node>> evaluated_elements;
for (auto& element : elements)
{
auto evaluated = element->evaluate();
if (!evaluated)
{
AML_ERROR("Failed to evaluate element in package");
return {};
}
evaluated_elements.push_back(evaluated);
}
auto package = MUST(BAN::RefPtr<Package>::create());
package->elements = BAN::move(evaluated_elements);
return package;
}
static ParseResult 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);
BAN::Vector<BAN::RefPtr<AML::Node>> elements;
while (elements.size() < num_elements && package_context.aml_data.size() > 0)
{
auto element_result = AML::parse_object(package_context);
if (!element_result.success())
return ParseResult::Failure;
MUST(elements.push_back(element_result.node()));
}
while (elements.size() < num_elements)
MUST(elements.push_back(BAN::RefPtr<AML::Node>()));
auto package = MUST(BAN::RefPtr<Package>::create());
package->elements = BAN::move(elements);
return ParseResult(package);
}
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)
{
element->debug_print(indent + 1);
AML_DEBUG_PRINTLN("");
}
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("}");
}
};
}