forked from Bananymous/banan-os
Kernel: Rewrite whole AML parser
Now AML parsing is actually done while respecting namespaces and scopes. I implemented the minimal functionality to parse qemu's AML. Next step is to implement AML interpreting and then we can drop lai as a dependency.
This commit is contained in:
@@ -35,7 +35,7 @@ namespace Kernel::ACPI
|
||||
|
||||
auto dsdt = s_instance->get_header("DSDT", 0);
|
||||
ASSERT(dsdt);
|
||||
AMLParser::parse_table(*dsdt);
|
||||
s_instance->m_namespace = AMLParser::parse_table(*dsdt);
|
||||
|
||||
#if ARCH(x86_64)
|
||||
lai_create_namespace();
|
||||
|
||||
@@ -3,33 +3,34 @@
|
||||
#include <kernel/ACPI/ACPI.h>
|
||||
#include <kernel/ACPI/AML.h>
|
||||
|
||||
#include <kernel/ACPI/AML/TermObject.h>
|
||||
|
||||
namespace Kernel::ACPI::AML { size_t g_depth = 0; }
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
AMLParser::AMLParser() = default;
|
||||
AMLParser::~AMLParser() = default;
|
||||
|
||||
AMLParser AMLParser::parse_table(const SDTHeader& header)
|
||||
BAN::RefPtr<AML::Namespace> AMLParser::parse_table(const SDTHeader& header)
|
||||
{
|
||||
dprintln("Parsing {}, {} bytes of AML", header, header.length - sizeof(header));
|
||||
dprintln("Parsing {}, {} bytes of AML", header, header.length);
|
||||
|
||||
auto aml_raw = BAN::ConstByteSpan { reinterpret_cast<const uint8_t*>(&header), header.length };
|
||||
aml_raw = aml_raw.slice(sizeof(header));
|
||||
|
||||
if (!AML::TermList::can_parse(aml_raw))
|
||||
dwarnln("Can not AML term_list");
|
||||
else
|
||||
auto ns = AML::Namespace::parse(aml_raw);
|
||||
if (!ns)
|
||||
{
|
||||
auto term_list = AML::TermList::parse(aml_raw);
|
||||
if (!term_list.has_value())
|
||||
dwarnln("Failed to parse AML term_list");
|
||||
dwarnln("Failed to parse ACPI namespace");
|
||||
return {};
|
||||
}
|
||||
|
||||
return {};
|
||||
#if AML_DEBUG_LEVEL >= 1
|
||||
ns->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
#endif
|
||||
|
||||
dprintln("Parsed ACPI namespace");
|
||||
|
||||
return ns;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,278 +0,0 @@
|
||||
#include <kernel/ACPI/AML/Bytes.h>
|
||||
#include <kernel/ACPI/AML/DataObject.h>
|
||||
#include <kernel/ACPI/AML/PackageLength.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
// Integer
|
||||
|
||||
bool AML::Integer::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (span.size() < 1)
|
||||
return false;
|
||||
switch (static_cast<AML::Byte>(span[0]))
|
||||
{
|
||||
case AML::Byte::BytePrefix:
|
||||
case AML::Byte::WordPrefix:
|
||||
case AML::Byte::DWordPrefix:
|
||||
case AML::Byte::QWordPrefix:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BAN::Optional<AML::Integer> AML::Integer::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
|
||||
switch (static_cast<AML::Byte>(span[0]))
|
||||
{
|
||||
#define AML_PARSE_INTEGER_CASE(TYPE, BYTES) \
|
||||
case AML::Byte::TYPE##Prefix: \
|
||||
{ \
|
||||
span = span.slice(1); \
|
||||
if (span.size() < BYTES) \
|
||||
{ \
|
||||
AML_DEBUG_CANNOT_PARSE(#TYPE, span); \
|
||||
return {}; \
|
||||
} \
|
||||
uint64_t value = 0; \
|
||||
for (size_t i = 0; i < BYTES; i++) \
|
||||
value |= static_cast<uint64_t>(span[i]) << (i * 8); \
|
||||
AML_DEBUG_PRINT("0x{H}", value); \
|
||||
span = span.slice(BYTES); \
|
||||
return Integer { .value = value }; \
|
||||
}
|
||||
AML_PARSE_INTEGER_CASE(Byte, 1)
|
||||
AML_PARSE_INTEGER_CASE(Word, 2)
|
||||
AML_PARSE_INTEGER_CASE(DWord, 4)
|
||||
AML_PARSE_INTEGER_CASE(QWord, 8)
|
||||
#undef AML_PARSE_INTEGER_CASE
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Buffer
|
||||
|
||||
bool AML::Buffer::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (span.size() < 1)
|
||||
return false;
|
||||
if (static_cast<AML::Byte>(span[0]) == AML::Byte::BufferOp)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
BAN::Optional<AML::Buffer> AML::Buffer::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
|
||||
span = span.slice(1);
|
||||
|
||||
AML_TRY_PARSE_PACKAGE(buffer_span);
|
||||
|
||||
AML_TRY_PARSE(buffer_size, AML::Integer, buffer_span);
|
||||
|
||||
BAN::Vector<uint8_t> data;
|
||||
MUST(data.resize(BAN::Math::max(buffer_size->value, buffer_span.size())));
|
||||
for (size_t i = 0; i < buffer_span.size(); i++)
|
||||
data[i] = buffer_span[i];
|
||||
|
||||
return Buffer { .buffer_size = buffer_size.release_value(), .data = BAN::move(data) };
|
||||
}
|
||||
|
||||
|
||||
// ComputationalData
|
||||
|
||||
bool AML::ComputationalData::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (span.size() < 1)
|
||||
return false;
|
||||
if (static_cast<AML::Byte>(span[0]) == AML::Byte::ExtOpPrefix)
|
||||
{
|
||||
if (span.size() < 2)
|
||||
return false;
|
||||
switch (static_cast<AML::Byte>(span[1]))
|
||||
{
|
||||
case AML::Byte::ExtRevisionOp:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch (static_cast<AML::Byte>(span[0]))
|
||||
{
|
||||
case AML::Byte::ZeroOp:
|
||||
case AML::Byte::OneOp:
|
||||
case AML::Byte::OnesOp:
|
||||
case AML::Byte::BytePrefix:
|
||||
case AML::Byte::WordPrefix:
|
||||
case AML::Byte::DWordPrefix:
|
||||
case AML::Byte::StringPrefix:
|
||||
case AML::Byte::QWordPrefix:
|
||||
case AML::Byte::BufferOp:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BAN::Optional<AML::ComputationalData> AML::ComputationalData::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
|
||||
AML_TRY_PARSE_IF_CAN(AML::Buffer);
|
||||
AML_TRY_PARSE_IF_CAN(AML::Integer);
|
||||
|
||||
switch (static_cast<AML::Byte>(span[0]))
|
||||
{
|
||||
#define AML_PARSE_CONST(TYPE) \
|
||||
case AML::Byte::TYPE##Op: \
|
||||
{ \
|
||||
span = span.slice(1); \
|
||||
AML_DEBUG_PRINT("{}", #TYPE); \
|
||||
return ConstObj { .type = ConstObj::Type::TYPE }; \
|
||||
}
|
||||
AML_PARSE_CONST(Zero);
|
||||
AML_PARSE_CONST(One);
|
||||
AML_PARSE_CONST(Ones);
|
||||
#undef AML_PARSE_CONST
|
||||
case AML::Byte::StringPrefix:
|
||||
{
|
||||
span = span.slice(1);
|
||||
|
||||
BAN::String value;
|
||||
while (span.size() > 0)
|
||||
{
|
||||
if (span[0] == 0x00 || span[0] > 0x7F)
|
||||
break;
|
||||
MUST(value.push_back(span[0]));
|
||||
span = span.slice(1);
|
||||
}
|
||||
|
||||
if (span.size() == 0 || span[0] != 0x00)
|
||||
return {};
|
||||
span = span.slice(1);
|
||||
|
||||
AML_DEBUG_PRINT("\"{}\"", value);
|
||||
return String { .value = BAN::move(value) };
|
||||
}
|
||||
GEN_PARSE_CASE_TODO(BufferOp)
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
|
||||
#define AML_GEN_PACKAGE(NAME) \
|
||||
bool AML::NAME::can_parse(BAN::ConstByteSpan span) \
|
||||
{ \
|
||||
if (span.size() < 1) \
|
||||
return false; \
|
||||
if (static_cast<AML::Byte>(span[0]) == AML::Byte::NAME##Op) \
|
||||
return true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
BAN::Optional<AML::NAME> AML::NAME::parse(BAN::ConstByteSpan& span) \
|
||||
{ \
|
||||
AML_DEBUG_PRINT_FN(); \
|
||||
ASSERT(can_parse(span)); \
|
||||
\
|
||||
span = span.slice(1); \
|
||||
\
|
||||
AML_TRY_PARSE_PACKAGE(package_span); \
|
||||
\
|
||||
uint8_t count = package_span[0]; \
|
||||
package_span = package_span.slice(1); \
|
||||
\
|
||||
AML_DEBUG_PRINT("Count: {}", count); \
|
||||
\
|
||||
BAN::Vector<PackageElement> elements; \
|
||||
for (uint8_t i = 0; package_span.size() > 0 && i < count; i++) \
|
||||
{ \
|
||||
if (DataRefObject::can_parse(package_span)) \
|
||||
{ \
|
||||
AML_TRY_PARSE(element, DataRefObject, package_span); \
|
||||
MUST(elements.push_back(PackageElement { \
|
||||
MUST(BAN::UniqPtr<DataRefObject>::create(element.release_value())) \
|
||||
})); \
|
||||
} \
|
||||
else if (NameString::can_parse(package_span)) \
|
||||
{ \
|
||||
AML_TRY_PARSE(element, NameString, package_span); \
|
||||
MUST(elements.push_back(PackageElement { \
|
||||
element.release_value() \
|
||||
})); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
AML_DEBUG_CANNOT_PARSE("PackageElement", package_span); \
|
||||
return {}; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
while (elements.size() < count) \
|
||||
MUST(elements.push_back(PackageElement { Uninitialized {} })); \
|
||||
\
|
||||
return NAME { .elements = BAN::move(elements) }; \
|
||||
}
|
||||
|
||||
AML_GEN_PACKAGE(Package)
|
||||
AML_GEN_PACKAGE(VarPackage)
|
||||
#undef AML_GEN_PACKAGE
|
||||
|
||||
// DataObject
|
||||
|
||||
bool AML::DataObject::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (ComputationalData::can_parse(span))
|
||||
return true;
|
||||
if (Package::can_parse(span))
|
||||
return true;
|
||||
if (VarPackage::can_parse(span))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
BAN::Optional<AML::DataObject> AML::DataObject::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
AML_TRY_PARSE_IF_CAN(ComputationalData);
|
||||
AML_TRY_PARSE_IF_CAN(Package);
|
||||
AML_TRY_PARSE_IF_CAN(VarPackage);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
|
||||
// DataRefObject
|
||||
|
||||
bool AML::DataRefObject::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (DataObject::can_parse(span))
|
||||
return true;
|
||||
if (Integer::can_parse(span))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
BAN::Optional<AML::DataRefObject> AML::DataRefObject::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
AML_TRY_PARSE_IF_CAN(DataObject);
|
||||
AML_TRY_PARSE_IF_CAN(Integer);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
}
|
||||
224
kernel/kernel/ACPI/AML/Field.cpp
Normal file
224
kernel/kernel/ACPI/AML/Field.cpp
Normal file
@@ -0,0 +1,224 @@
|
||||
#include <kernel/ACPI/AML/Field.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
template<typename Element>
|
||||
struct ParseFieldElementContext
|
||||
{
|
||||
AML::FieldRules field_rules;
|
||||
uint64_t field_bit_offset;
|
||||
BAN::ConstByteSpan field_pkg;
|
||||
BAN::HashMap<AML::NameSeg, BAN::RefPtr<Element>> elements;
|
||||
};
|
||||
|
||||
template<typename Element>
|
||||
static bool parse_field_element(ParseFieldElementContext<Element>& context)
|
||||
{
|
||||
ASSERT(context.field_pkg.size() >= 1);
|
||||
switch (context.field_pkg[0])
|
||||
{
|
||||
case 0x00:
|
||||
{
|
||||
context.field_pkg = context.field_pkg.slice(1);
|
||||
|
||||
auto reserved_length = AML::parse_pkg_length(context.field_pkg);
|
||||
if (!reserved_length.has_value())
|
||||
{
|
||||
AML_ERROR("Invalid FieldElement length for reserved field");
|
||||
return false;
|
||||
}
|
||||
AML::trim_pkg_length(context.field_pkg);
|
||||
|
||||
context.field_bit_offset += reserved_length.value();
|
||||
return true;
|
||||
}
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
AML_TODO("Field element {2H}", context.field_pkg[0]);
|
||||
return false;
|
||||
default:
|
||||
{
|
||||
auto element_name = AML::NameSeg::parse(context.field_pkg);
|
||||
if (!element_name.has_value())
|
||||
{
|
||||
AML_ERROR("Invalid FieldElement name for named field");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto element_length = AML::parse_pkg_length(context.field_pkg);
|
||||
if (!element_length.has_value())
|
||||
{
|
||||
AML_ERROR("Invalid FieldElement length for named field");
|
||||
return false;
|
||||
}
|
||||
AML::trim_pkg_length(context.field_pkg);
|
||||
|
||||
if (context.elements.contains(element_name.value()))
|
||||
{
|
||||
AML_ERROR("Field element already exists");
|
||||
return false;
|
||||
}
|
||||
|
||||
MUST(context.elements.emplace(
|
||||
element_name.value(),
|
||||
MUST(BAN::RefPtr<Element>::create(
|
||||
element_name.value(),
|
||||
context.field_bit_offset,
|
||||
element_length.value(),
|
||||
context.field_rules
|
||||
))
|
||||
));
|
||||
context.field_bit_offset += element_length.value();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AML::ParseResult AML::Field::parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 2);
|
||||
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix);
|
||||
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::FieldOp);
|
||||
context.aml_data = context.aml_data.slice(2);
|
||||
|
||||
auto opt_field_pkg = AML::parse_pkg(context.aml_data);
|
||||
if (!opt_field_pkg.has_value())
|
||||
return ParseResult::Failure;
|
||||
auto field_pkg = opt_field_pkg.release_value();
|
||||
|
||||
auto name_string = NameString::parse(field_pkg);
|
||||
if (!name_string.has_value())
|
||||
return ParseResult::Failure;
|
||||
|
||||
auto op_region = context.root_namespace->find_object(context.scope.span(), name_string.value());
|
||||
if (!op_region || op_region->type != AML::Node::Type::OpRegion)
|
||||
{
|
||||
AML_ERROR("Field RegionName does not name a valid OpRegion");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
if (field_pkg.size() < 1)
|
||||
return ParseResult::Failure;
|
||||
auto field_flags = field_pkg[0];
|
||||
field_pkg = field_pkg.slice(1);
|
||||
|
||||
ParseFieldElementContext<FieldElement> field_context;
|
||||
field_context.field_rules.access_type = static_cast<FieldRules::AccessType>(field_flags & 0x0F);
|
||||
field_context.field_rules.lock_rule = static_cast<FieldRules::LockRule>((field_flags >> 4) & 0x01);
|
||||
field_context.field_rules.update_rule = static_cast<FieldRules::UpdateRule>((field_flags >> 5) & 0x03);
|
||||
field_context.field_bit_offset = 0;
|
||||
field_context.field_pkg = field_pkg;
|
||||
while (field_context.field_pkg.size() > 0)
|
||||
if (!parse_field_element(field_context))
|
||||
return ParseResult::Failure;
|
||||
|
||||
for (auto& [_, element] : field_context.elements)
|
||||
{
|
||||
element->op_region = static_cast<OpRegion*>(op_region.ptr());
|
||||
|
||||
NameString element_name;
|
||||
MUST(element_name.path.push_back(element->name));
|
||||
if (!context.root_namespace->add_named_object(context.scope.span(), element_name, element))
|
||||
return ParseResult::Failure;
|
||||
|
||||
#if AML_DEBUG_LEVEL >= 2
|
||||
element->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
#endif
|
||||
}
|
||||
|
||||
return ParseResult::Success;
|
||||
}
|
||||
|
||||
void AML::FieldElement::debug_print(int indent) const
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("FieldElement ");
|
||||
name.debug_print();
|
||||
AML_DEBUG_PRINT("({}, offset {}, OpRegion ", bit_count, bit_offset);
|
||||
op_region->name.debug_print();
|
||||
AML_DEBUG_PRINT(")");
|
||||
}
|
||||
|
||||
AML::ParseResult AML::IndexField::parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 2);
|
||||
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix);
|
||||
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::IndexFieldOp);
|
||||
context.aml_data = context.aml_data.slice(2);
|
||||
|
||||
auto opt_field_pkg = AML::parse_pkg(context.aml_data);
|
||||
if (!opt_field_pkg.has_value())
|
||||
return ParseResult::Failure;
|
||||
auto field_pkg = opt_field_pkg.release_value();
|
||||
|
||||
auto index_field_element_name = NameString::parse(field_pkg);
|
||||
if (!index_field_element_name.has_value())
|
||||
return ParseResult::Failure;
|
||||
auto index_field_element = context.root_namespace->find_object(context.scope.span(), index_field_element_name.value());
|
||||
if (!index_field_element || index_field_element->type != AML::Node::Type::FieldElement)
|
||||
{
|
||||
AML_ERROR("IndexField IndexName does not name a valid FieldElement");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
auto data_field_element_name = NameString::parse(field_pkg);
|
||||
if (!data_field_element_name.has_value())
|
||||
return ParseResult::Failure;
|
||||
auto data_field_element = context.root_namespace->find_object(context.scope.span(), data_field_element_name.value());
|
||||
if (!data_field_element || data_field_element->type != AML::Node::Type::FieldElement)
|
||||
{
|
||||
AML_ERROR("IndexField DataName does not name a valid FieldElement");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
if (field_pkg.size() < 1)
|
||||
return ParseResult::Failure;
|
||||
auto field_flags = field_pkg[0];
|
||||
field_pkg = field_pkg.slice(1);
|
||||
|
||||
ParseFieldElementContext<IndexFieldElement> field_context;
|
||||
field_context.field_rules.access_type = static_cast<FieldRules::AccessType>(field_flags & 0x0F);
|
||||
field_context.field_rules.lock_rule = static_cast<FieldRules::LockRule>((field_flags >> 4) & 0x01);
|
||||
field_context.field_rules.update_rule = static_cast<FieldRules::UpdateRule>((field_flags >> 5) & 0x03);
|
||||
field_context.field_bit_offset = 0;
|
||||
field_context.field_pkg = field_pkg;
|
||||
while (field_context.field_pkg.size() > 0)
|
||||
if (!parse_field_element(field_context))
|
||||
return ParseResult::Failure;
|
||||
|
||||
for (auto& [_, element] : field_context.elements)
|
||||
{
|
||||
element->index_element = static_cast<FieldElement*>(index_field_element.ptr());
|
||||
element->data_element = static_cast<FieldElement*>(data_field_element.ptr());
|
||||
|
||||
NameString element_name;
|
||||
MUST(element_name.path.push_back(element->name));
|
||||
if (!context.root_namespace->add_named_object(context.scope.span(), element_name, element))
|
||||
return ParseResult::Failure;
|
||||
|
||||
#if AML_DEBUG_LEVEL >= 2
|
||||
element->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
#endif
|
||||
}
|
||||
|
||||
return AML::ParseResult::Success;
|
||||
}
|
||||
|
||||
void AML::IndexFieldElement::debug_print(int indent) const
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("IndexFieldElement ");
|
||||
name.debug_print();
|
||||
AML_DEBUG_PRINT("({}, offset {}, IndexName ", bit_count, bit_offset);
|
||||
index_element->name.debug_print();
|
||||
AML_DEBUG_PRINT(", DataName ");
|
||||
data_element->name.debug_print();
|
||||
AML_DEBUG_PRINT(")");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
#include <kernel/ACPI/AML/Bytes.h>
|
||||
#include <kernel/ACPI/AML/MiscObject.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
// ArgObj
|
||||
|
||||
bool AML::ArgObj::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (span.size() < 1)
|
||||
return false;
|
||||
switch (static_cast<AML::Byte>(span[0]))
|
||||
{
|
||||
case AML::Byte::Arg0Op:
|
||||
case AML::Byte::Arg1Op:
|
||||
case AML::Byte::Arg2Op:
|
||||
case AML::Byte::Arg3Op:
|
||||
case AML::Byte::Arg4Op:
|
||||
case AML::Byte::Arg5Op:
|
||||
case AML::Byte::Arg6Op:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BAN::Optional<AML::ArgObj> AML::ArgObj::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
|
||||
uint8_t type = static_cast<uint8_t>(span[0]) - static_cast<uint8_t>(AML::Byte::Arg0Op);
|
||||
span = span.slice(1);
|
||||
|
||||
AML_DEBUG_PRINT("Arg{}", type);
|
||||
|
||||
return ArgObj { .type = static_cast<Type>(type) };
|
||||
}
|
||||
|
||||
|
||||
// LocalObj
|
||||
|
||||
bool AML::LocalObj::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (span.size() < 1)
|
||||
return false;
|
||||
switch (static_cast<AML::Byte>(span[0]))
|
||||
{
|
||||
case AML::Byte::Local0Op:
|
||||
case AML::Byte::Local1Op:
|
||||
case AML::Byte::Local2Op:
|
||||
case AML::Byte::Local3Op:
|
||||
case AML::Byte::Local4Op:
|
||||
case AML::Byte::Local5Op:
|
||||
case AML::Byte::Local6Op:
|
||||
case AML::Byte::Local7Op:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BAN::Optional<AML::LocalObj> AML::LocalObj::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
|
||||
uint8_t type = static_cast<uint8_t>(span[0]) - static_cast<uint8_t>(AML::Byte::Local0Op);
|
||||
span = span.slice(1);
|
||||
|
||||
AML_DEBUG_PRINT("Local{}", type);
|
||||
|
||||
return LocalObj { .type = static_cast<Type>(type) };
|
||||
}
|
||||
|
||||
// DebugObj
|
||||
|
||||
bool AML::DebugObj::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (span.size() < 2)
|
||||
return false;
|
||||
if (static_cast<AML::Byte>(span[0]) != AML::Byte::ExtOpPrefix)
|
||||
return false;
|
||||
if (static_cast<AML::Byte>(span[1]) != AML::Byte::ExtDebugOp)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
BAN::Optional<AML::DebugObj> AML::DebugObj::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
|
||||
span = span.slice(2);
|
||||
return DebugObj {};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
#include <kernel/ACPI/AML/Bytes.h>
|
||||
#include <kernel/ACPI/AML/NameObject.h>
|
||||
#include <kernel/ACPI/AML/TermObject.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
static constexpr bool is_lead_name_char(uint8_t ch)
|
||||
{
|
||||
return ('A' <= ch && ch <= 'Z') || ch == '_';
|
||||
}
|
||||
|
||||
static constexpr bool is_name_char(uint8_t ch)
|
||||
{
|
||||
return is_lead_name_char(ch) || ('0' <= ch && ch <= '9');
|
||||
}
|
||||
|
||||
|
||||
// NameString
|
||||
|
||||
bool AML::NameString::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (span.size() < 1)
|
||||
return false;
|
||||
if (span[0] == '\\' || span[0] == '^' || span[0] == 0x00)
|
||||
return true;
|
||||
if (static_cast<AML::Byte>(span[0]) == AML::Byte::DualNamePrefix)
|
||||
return true;
|
||||
if (static_cast<AML::Byte>(span[0]) == AML::Byte::MultiNamePrefix)
|
||||
return true;
|
||||
if (is_lead_name_char(span[0]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
BAN::Optional<AML::NameString> AML::NameString::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
|
||||
NameString name_string;
|
||||
|
||||
if (span[0] == '\\')
|
||||
{
|
||||
MUST(name_string.prefix.push_back('\\'));
|
||||
span = span.slice(1);
|
||||
}
|
||||
else if (span[0] == '^')
|
||||
{
|
||||
while (span[0] == '^')
|
||||
{
|
||||
MUST(name_string.prefix.push_back('^'));
|
||||
span = span.slice(1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t name_count = 1;
|
||||
switch (span[0])
|
||||
{
|
||||
case 0x00:
|
||||
name_count = 0;
|
||||
span = span.slice(1);
|
||||
break;
|
||||
case static_cast<uint8_t>(AML::Byte::DualNamePrefix):
|
||||
name_count = 2;
|
||||
span = span.slice(1);
|
||||
break;
|
||||
case static_cast<uint8_t>(AML::Byte::MultiNamePrefix):
|
||||
name_count = span[1];
|
||||
span = span.slice(2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (span.size() < name_count * 4)
|
||||
return {};
|
||||
|
||||
MUST(name_string.path.resize(name_count));
|
||||
|
||||
for (size_t i = 0; i < name_count; i++)
|
||||
{
|
||||
if (!is_lead_name_char(span[0]) || !is_name_char(span[1]) || !is_name_char(span[2]) || !is_name_char(span[3]))
|
||||
{
|
||||
AML_DEBUG_ERROR("Invalid NameSeg {2H} {2H} {2H} {2H}", span[0], span[1], span[2], span[3]);
|
||||
ASSERT_NOT_REACHED();
|
||||
return {};
|
||||
}
|
||||
MUST(name_string.path[i].append(BAN::StringView(reinterpret_cast<const char*>(span.data()), 4)));
|
||||
while (name_string.path[i].back() == '_')
|
||||
name_string.path[i].pop_back();
|
||||
span = span.slice(4);
|
||||
}
|
||||
|
||||
if constexpr(DUMP_AML)
|
||||
{
|
||||
BAN::String full_string;
|
||||
MUST(full_string.append(name_string.prefix));
|
||||
for (size_t i = 0; i < name_string.path.size(); i++)
|
||||
{
|
||||
if (i != 0)
|
||||
MUST(full_string.push_back('.'));
|
||||
MUST(full_string.append(name_string.path[i]));
|
||||
}
|
||||
AML_DEBUG_PRINT("'{}'", full_string);
|
||||
}
|
||||
|
||||
return name_string;
|
||||
}
|
||||
|
||||
|
||||
// SimpleName
|
||||
|
||||
bool AML::SimpleName::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (NameString::can_parse(span))
|
||||
return true;
|
||||
if (ArgObj::can_parse(span))
|
||||
return true;
|
||||
if (LocalObj::can_parse(span))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
BAN::Optional<AML::SimpleName> AML::SimpleName::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
AML_TRY_PARSE_IF_CAN(NameString);
|
||||
AML_TRY_PARSE_IF_CAN(ArgObj);
|
||||
AML_TRY_PARSE_IF_CAN(LocalObj);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
|
||||
// SuperName
|
||||
|
||||
bool AML::SuperName::can_parse(BAN::ConstByteSpan span)
|
||||
{
|
||||
if (SimpleName::can_parse(span))
|
||||
return true;
|
||||
if (DebugObj::can_parse(span))
|
||||
return true;
|
||||
if (ReferenceTypeOpcode::can_parse(span))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
BAN::Optional<AML::SuperName> AML::SuperName::parse(BAN::ConstByteSpan& span)
|
||||
{
|
||||
AML_DEBUG_PRINT_FN();
|
||||
ASSERT(can_parse(span));
|
||||
|
||||
AML_TRY_PARSE_IF_CAN(SimpleName);
|
||||
AML_TRY_PARSE_IF_CAN(DebugObj);
|
||||
|
||||
ASSERT(ReferenceTypeOpcode::can_parse(span));
|
||||
auto opcode = ReferenceTypeOpcode::parse(span);
|
||||
if (!opcode.has_value())
|
||||
return {};
|
||||
return SuperName { .name = MUST(BAN::UniqPtr<ReferenceTypeOpcode>::create(opcode.release_value())) };
|
||||
}
|
||||
|
||||
}
|
||||
45
kernel/kernel/ACPI/AML/NamedObject.cpp
Normal file
45
kernel/kernel/ACPI/AML/NamedObject.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <kernel/ACPI/AML/NamedObject.h>
|
||||
#include <kernel/ACPI/AML/ParseContext.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
AML::ParseResult AML::Name::parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::NameOp);
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
|
||||
auto name_string = AML::NameString::parse(context.aml_data);
|
||||
if (!name_string.has_value())
|
||||
return ParseResult::Failure;
|
||||
|
||||
auto object = AML::parse_object(context);
|
||||
if (!object.success())
|
||||
return ParseResult::Failure;
|
||||
|
||||
auto name = MUST(BAN::RefPtr<Name>::create(name_string.value().path.back(), object.node()));
|
||||
if (!context.root_namespace->add_named_object(context.scope.span(), name_string.value(), name))
|
||||
return ParseResult::Failure;
|
||||
|
||||
#if AML_DEBUG_LEVEL >= 2
|
||||
name->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
#endif
|
||||
|
||||
return ParseResult::Success;
|
||||
}
|
||||
|
||||
void AML::Name::debug_print(int indent) const
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("Name ");
|
||||
name.debug_print();
|
||||
AML_DEBUG_PRINTLN(" {");
|
||||
object->debug_print(indent + 1);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("}");
|
||||
}
|
||||
|
||||
}
|
||||
123
kernel/kernel/ACPI/AML/Namespace.cpp
Normal file
123
kernel/kernel/ACPI/AML/Namespace.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#include <kernel/ACPI/AML/Namespace.h>
|
||||
#include <kernel/ACPI/AML/ParseContext.h>
|
||||
#include <kernel/ACPI/AML/Region.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
BAN::Optional<BAN::Vector<AML::NameSeg>> AML::Namespace::resolve_path(BAN::Span<const AML::NameSeg> parsing_scope, const AML::NameString& relative_path)
|
||||
{
|
||||
BAN::Vector<NameSeg> canonical_path;
|
||||
|
||||
if (!relative_path.prefix.empty())
|
||||
{
|
||||
if (relative_path.prefix[0] == '\\')
|
||||
;
|
||||
else
|
||||
{
|
||||
if (parsing_scope.size() < relative_path.prefix.size())
|
||||
{
|
||||
AML_ERROR("Trying to resolve parent of root object");
|
||||
return {};
|
||||
}
|
||||
for (size_t i = 0; i < parsing_scope.size() - relative_path.prefix.size(); i++)
|
||||
MUST(canonical_path.push_back(parsing_scope[i]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto seg : parsing_scope)
|
||||
MUST(canonical_path.push_back(seg));
|
||||
}
|
||||
|
||||
for (const auto& seg : relative_path.path)
|
||||
MUST(canonical_path.push_back(seg));
|
||||
|
||||
return canonical_path;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::NamedObject> AML::Namespace::find_object(BAN::Span<const AML::NameSeg> parsing_scope, const AML::NameString& relative_path)
|
||||
{
|
||||
auto canonical_path = resolve_path(parsing_scope, relative_path);
|
||||
if (!canonical_path.has_value())
|
||||
return nullptr;
|
||||
if (canonical_path->empty())
|
||||
return this;
|
||||
|
||||
BAN::RefPtr<NamedObject> parent_object = this;
|
||||
|
||||
for (const auto& seg : canonical_path.value())
|
||||
{
|
||||
if (!parent_object->is_scope())
|
||||
{
|
||||
AML_ERROR("Parent object is not a scope");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* parent_scope = static_cast<Scope*>(parent_object.ptr());
|
||||
|
||||
auto it = parent_scope->objects.find(seg);
|
||||
if (it == parent_scope->objects.end())
|
||||
return nullptr;
|
||||
|
||||
parent_object = it->value;
|
||||
ASSERT(parent_object);
|
||||
}
|
||||
|
||||
return parent_object;
|
||||
}
|
||||
|
||||
bool AML::Namespace::add_named_object(BAN::Span<const NameSeg> parsing_scope, const AML::NameString& object_path, BAN::RefPtr<NamedObject> object)
|
||||
{
|
||||
ASSERT(!object_path.path.empty());
|
||||
ASSERT(object_path.path.back() == object->name);
|
||||
|
||||
auto parent_path = object_path;
|
||||
parent_path.path.pop_back();
|
||||
|
||||
auto parent_object = find_object(parsing_scope, parent_path);
|
||||
if (!parent_object)
|
||||
{
|
||||
AML_ERROR("Parent object not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parent_object->is_scope())
|
||||
{
|
||||
AML_ERROR("Parent object is not a scope");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* parent_scope = static_cast<Scope*>(parent_object.ptr());
|
||||
if (parent_scope->objects.contains(object->name))
|
||||
{
|
||||
AML_ERROR("Object already exists");
|
||||
return false;
|
||||
}
|
||||
|
||||
MUST(parent_scope->objects.insert(object->name, object));
|
||||
return true;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Namespace> AML::Namespace::parse(BAN::ConstByteSpan aml_data)
|
||||
{
|
||||
auto result = MUST(BAN::RefPtr<Namespace>::create());
|
||||
|
||||
AML::ParseContext context;
|
||||
context.aml_data = aml_data;
|
||||
context.root_namespace = result.ptr();
|
||||
|
||||
while (context.aml_data.size() > 0)
|
||||
{
|
||||
auto result = AML::parse_object(context);
|
||||
if (!result.success())
|
||||
{
|
||||
AML_ERROR("Failed to parse object");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
102
kernel/kernel/ACPI/AML/Node.cpp
Normal file
102
kernel/kernel/ACPI/AML/Node.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <kernel/ACPI/AML/Buffer.h>
|
||||
#include <kernel/ACPI/AML/Bytes.h>
|
||||
#include <kernel/ACPI/AML/Device.h>
|
||||
#include <kernel/ACPI/AML/Field.h>
|
||||
#include <kernel/ACPI/AML/Integer.h>
|
||||
#include <kernel/ACPI/AML/Method.h>
|
||||
#include <kernel/ACPI/AML/Mutex.h>
|
||||
#include <kernel/ACPI/AML/Names.h>
|
||||
#include <kernel/ACPI/AML/Node.h>
|
||||
#include <kernel/ACPI/AML/Package.h>
|
||||
#include <kernel/ACPI/AML/ParseContext.h>
|
||||
#include <kernel/ACPI/AML/Processor.h>
|
||||
#include <kernel/ACPI/AML/Region.h>
|
||||
#include <kernel/ACPI/AML/String.h>
|
||||
#include <kernel/ACPI/AML/Utils.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
AML::ParseResult AML::ParseResult::Failure = AML::ParseResult(AML::ParseResult::Result::Failure);
|
||||
AML::ParseResult AML::ParseResult::Success = AML::ParseResult(AML::ParseResult::Result::Success);
|
||||
|
||||
AML::ParseResult AML::parse_object(AML::ParseContext& context)
|
||||
{
|
||||
if (context.aml_data.size() < 1)
|
||||
return ParseResult::Failure;
|
||||
|
||||
if (static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix)
|
||||
{
|
||||
if (context.aml_data.size() < 2)
|
||||
return ParseResult::Failure;
|
||||
|
||||
switch (static_cast<AML::ExtOp>(context.aml_data[1]))
|
||||
{
|
||||
case AML::ExtOp::FieldOp:
|
||||
return AML::Field::parse(context);
|
||||
case AML::ExtOp::IndexFieldOp:
|
||||
return AML::IndexField::parse(context);
|
||||
case AML::ExtOp::OpRegionOp:
|
||||
return AML::OpRegion::parse(context);
|
||||
case AML::ExtOp::DeviceOp:
|
||||
return AML::Device::parse(context);
|
||||
case AML::ExtOp::MutexOp:
|
||||
return AML::Mutex::parse(context);
|
||||
case AML::ExtOp::ProcessorOp:
|
||||
return AML::Processor::parse(context);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
AML_TODO("{2H} {2H}", context.aml_data[0], context.aml_data[1]);
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
switch (static_cast<AML::Byte>(context.aml_data[0]))
|
||||
{
|
||||
case AML::Byte::ZeroOp:
|
||||
case AML::Byte::OneOp:
|
||||
case AML::Byte::OnesOp:
|
||||
case AML::Byte::BytePrefix:
|
||||
case AML::Byte::WordPrefix:
|
||||
case AML::Byte::DWordPrefix:
|
||||
case AML::Byte::QWordPrefix:
|
||||
return AML::Integer::parse(context.aml_data);
|
||||
case AML::Byte::StringPrefix:
|
||||
return AML::String::parse(context);
|
||||
case AML::Byte::NameOp:
|
||||
return AML::Name::parse(context);
|
||||
case AML::Byte::PackageOp:
|
||||
return AML::Package::parse(context);
|
||||
case AML::Byte::MethodOp:
|
||||
return AML::Method::parse(context);
|
||||
case AML::Byte::BufferOp:
|
||||
return AML::Buffer::parse(context);
|
||||
case AML::Byte::ScopeOp:
|
||||
return AML::Scope::parse(context);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::RootChar
|
||||
|| static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ParentPrefixChar
|
||||
|| static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::NullName
|
||||
|| is_lead_name_char(context.aml_data[0]))
|
||||
{
|
||||
auto name_string = AML::NameString::parse(context.aml_data);
|
||||
if (!name_string.has_value())
|
||||
return ParseResult::Failure;
|
||||
auto aml_object = context.root_namespace->find_object(context.scope.span(), name_string.value());
|
||||
if (!aml_object)
|
||||
{
|
||||
AML_TODO("NameString not found in namespace");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
return ParseResult(aml_object);
|
||||
}
|
||||
|
||||
AML_TODO("{2H}", context.aml_data[0]);
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
}
|
||||
77
kernel/kernel/ACPI/AML/Scope.cpp
Normal file
77
kernel/kernel/ACPI/AML/Scope.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include <kernel/ACPI/AML/Device.h>
|
||||
#include <kernel/ACPI/AML/ParseContext.h>
|
||||
#include <kernel/ACPI/AML/Pkg.h>
|
||||
#include <kernel/ACPI/AML/Scope.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
AML::ParseResult AML::Scope::parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ScopeOp);
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
|
||||
auto scope_pkg = AML::parse_pkg(context.aml_data);
|
||||
if (!scope_pkg.has_value())
|
||||
return ParseResult::Failure;
|
||||
|
||||
auto name_string = AML::NameString::parse(scope_pkg.value());
|
||||
if (!name_string.has_value())
|
||||
return ParseResult::Failure;
|
||||
|
||||
BAN::RefPtr<Scope> scope;
|
||||
if (auto named_object = context.root_namespace->find_object(context.scope.span(), name_string.value()))
|
||||
{
|
||||
if (!named_object->is_scope())
|
||||
{
|
||||
AML_ERROR("Scope name already exists and is not a scope");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
scope = static_cast<Scope*>(named_object.ptr());
|
||||
}
|
||||
else
|
||||
{
|
||||
scope = MUST(BAN::RefPtr<Scope>::create(name_string->path.back()));
|
||||
if (!context.root_namespace->add_named_object(context.scope.span(), name_string.value(), scope))
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
return scope->enter_context_and_parse_term_list(context, name_string.value(), scope_pkg.value());
|
||||
}
|
||||
|
||||
AML::ParseResult AML::Scope::enter_context_and_parse_term_list(ParseContext& outer_context, const AML::NameString& name_string, BAN::ConstByteSpan aml_data)
|
||||
{
|
||||
auto scope = outer_context.root_namespace->resolve_path(outer_context.scope.span(), name_string);
|
||||
if (!scope.has_value())
|
||||
return ParseResult::Failure;
|
||||
|
||||
ParseContext scope_context = outer_context;
|
||||
scope_context.scope = scope.release_value();
|
||||
scope_context.aml_data = aml_data;
|
||||
while (scope_context.aml_data.size() > 0)
|
||||
{
|
||||
auto object_result = AML::parse_object(scope_context);
|
||||
if (!object_result.success())
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
return ParseResult::Success;
|
||||
}
|
||||
|
||||
void AML::Scope::debug_print(int indent) const
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("Scope ");
|
||||
name.debug_print();
|
||||
AML_DEBUG_PRINTLN(" {");
|
||||
for (const auto& [name, object] : objects)
|
||||
{
|
||||
object->debug_print(indent + 1);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
}
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("}");
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user