forked from Bananymous/banan-os
Kernel: Implement barebones AML parser
This implements only parsing for AML in qemu. InvokeMethods are not parsed since number of arguments to Methods is not yet known. Parsing AML uses multiple kilobytes of stack space, so I increased boot stack size by a lot :D I am not sure where my own AML is going, but this is good start if I decide to implement full ACPI on my own. This code is very much just ugly macro expansion. Qemu has 2 DefPackage elements that I am not able to parse. Package data ends while there should be still multiple elements.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <BAN/StringView.h>
|
||||
#include <kernel/ACPI/ACPI.h>
|
||||
#include <kernel/ACPI/AML.h>
|
||||
#include <kernel/BootInfo.h>
|
||||
#include <kernel/Memory/PageTable.h>
|
||||
|
||||
@@ -31,6 +32,11 @@ namespace Kernel::ACPI
|
||||
if (s_instance == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
TRY(s_instance->initialize_impl());
|
||||
|
||||
auto dsdt = s_instance->get_header("DSDT", 0);
|
||||
ASSERT(dsdt);
|
||||
AMLParser::parse_table(*dsdt);
|
||||
|
||||
#if ARCH(x86_64)
|
||||
lai_create_namespace();
|
||||
#endif
|
||||
|
||||
35
kernel/kernel/ACPI/AML.cpp
Normal file
35
kernel/kernel/ACPI/AML.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <BAN/ByteSpan.h>
|
||||
#include <BAN/Variant.h>
|
||||
#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)
|
||||
{
|
||||
dprintln("Parsing {}, {} bytes of AML", header, header.length - sizeof(header));
|
||||
|
||||
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 term_list = AML::TermList::parse(aml_raw);
|
||||
if (!term_list.has_value())
|
||||
dwarnln("Failed to parse AML term_list");
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
281
kernel/kernel/ACPI/AML/DataObject.cpp
Normal file
281
kernel/kernel/ACPI/AML/DataObject.cpp
Normal file
@@ -0,0 +1,281 @@
|
||||
#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);
|
||||
|
||||
if (buffer_span.size() < buffer_size->value)
|
||||
{
|
||||
AML_DEBUG_ERROR("Buffer size {} bytes and span only {} bytes", buffer_size->value, buffer_span.size());
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::Vector<uint8_t> data;
|
||||
MUST(data.resize(buffer_size->value));
|
||||
for (size_t i = 0; i < buffer_size->value; 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; 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 {}; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
99
kernel/kernel/ACPI/AML/MiscObject.cpp
Normal file
99
kernel/kernel/ACPI/AML/MiscObject.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#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 {};
|
||||
}
|
||||
|
||||
}
|
||||
162
kernel/kernel/ACPI/AML/NameObject.cpp
Normal file
162
kernel/kernel/ACPI/AML/NameObject.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#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())) };
|
||||
}
|
||||
|
||||
}
|
||||
1031
kernel/kernel/ACPI/AML/TermObject.cpp
Normal file
1031
kernel/kernel/ACPI/AML/TermObject.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user