forked from Bananymous/banan-os
169 lines
4.0 KiB
C++
169 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include <kernel/ACPI/AML/Bytes.h>
|
|
#include <kernel/ACPI/AML/Integer.h>
|
|
#include <kernel/ACPI/AML/Node.h>
|
|
#include <kernel/ACPI/AML/ParseContext.h>
|
|
#include <kernel/ACPI/AML/Pkg.h>
|
|
#include <kernel/ACPI/AML/Reference.h>
|
|
|
|
namespace Kernel::ACPI::AML
|
|
{
|
|
|
|
struct PackageElement;
|
|
|
|
struct Package final : public AML::Node
|
|
{
|
|
BAN::Vector<BAN::RefPtr<PackageElement>> elements;
|
|
AML::NameString scope;
|
|
|
|
Package(AML::NameString scope)
|
|
: Node(Node::Type::Package)
|
|
, elements(BAN::move(elements))
|
|
, scope(scope)
|
|
{}
|
|
|
|
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
|
|
|
static ParseResult parse(AML::ParseContext& context);
|
|
virtual void debug_print(int indent) const override;
|
|
};
|
|
|
|
struct PackageElement final : 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(element);
|
|
resolved = true;
|
|
initialized = true;
|
|
}
|
|
|
|
PackageElement(BAN::RefPtr<AML::Package> parent, AML::NameString unresolved_name)
|
|
: Node(Node::Type::PackageElement)
|
|
, parent(parent)
|
|
, unresolved_name(unresolved_name)
|
|
{
|
|
resolved = false;
|
|
initialized = true;
|
|
}
|
|
|
|
PackageElement(BAN::RefPtr<AML::Package> parent)
|
|
: Node(Node::Type::PackageElement)
|
|
, parent(parent)
|
|
{
|
|
resolved = false;
|
|
initialized = false;
|
|
}
|
|
|
|
bool resolve()
|
|
{
|
|
ASSERT(!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 false;
|
|
}
|
|
element = object;
|
|
resolved = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
BAN::RefPtr<AML::Node> convert(uint8_t mask) override
|
|
{
|
|
if (!initialized)
|
|
{
|
|
AML_ERROR("Trying to store into uninitialized PackageElement");
|
|
return {};
|
|
}
|
|
if (!resolved && !resolve())
|
|
return {};
|
|
return element->convert(mask);
|
|
}
|
|
|
|
BAN::RefPtr<AML::Node> to_underlying() override
|
|
{
|
|
if (!initialized)
|
|
{
|
|
AML_ERROR("Trying to store into uninitialized PackageElement");
|
|
return {};
|
|
}
|
|
if (!resolved && !resolve())
|
|
return {};
|
|
return element;
|
|
}
|
|
|
|
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> node) override
|
|
{
|
|
if (!initialized)
|
|
{
|
|
AML_ERROR("Trying to store into uninitialized PackageElement");
|
|
return {};
|
|
}
|
|
if (!resolved && !resolve())
|
|
return {};
|
|
ASSERT(element->type != AML::Node::Type::Reference);
|
|
if (node->type == AML::Node::Type::Reference)
|
|
element = static_cast<AML::Reference*>(element.ptr())->node;
|
|
else
|
|
element = element->copy();
|
|
return element;
|
|
}
|
|
|
|
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_PRINTLN("PackageElement {");
|
|
if (!initialized)
|
|
{
|
|
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("}");
|
|
}
|
|
};
|
|
|
|
}
|