266 lines
8.1 KiB
C++
266 lines
8.1 KiB
C++
#include <kernel/ACPI/AML/Buffer.h>
|
|
#include <kernel/ACPI/AML/Bytes.h>
|
|
#include <kernel/ACPI/AML/Device.h>
|
|
#include <kernel/ACPI/AML/Expression.h>
|
|
#include <kernel/ACPI/AML/Field.h>
|
|
#include <kernel/ACPI/AML/IfElse.h>
|
|
#include <kernel/ACPI/AML/Index.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/Notify.h>
|
|
#include <kernel/ACPI/AML/Package.h>
|
|
#include <kernel/ACPI/AML/ParseContext.h>
|
|
#include <kernel/ACPI/AML/PowerResource.h>
|
|
#include <kernel/ACPI/AML/Processor.h>
|
|
#include <kernel/ACPI/AML/Reference.h>
|
|
#include <kernel/ACPI/AML/Region.h>
|
|
#include <kernel/ACPI/AML/SizeOf.h>
|
|
#include <kernel/ACPI/AML/Sleep.h>
|
|
#include <kernel/ACPI/AML/Store.h>
|
|
#include <kernel/ACPI/AML/String.h>
|
|
#include <kernel/ACPI/AML/ThermalZone.h>
|
|
#include <kernel/ACPI/AML/Utils.h>
|
|
#include <kernel/ACPI/AML/While.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);
|
|
|
|
uint64_t AML::Node::total_node_count = 0;
|
|
|
|
BAN::RefPtr<AML::Buffer> AML::Node::as_buffer()
|
|
{
|
|
AML_TODO("Node type {} to buffer", static_cast<uint32_t>(type));
|
|
return {};
|
|
}
|
|
|
|
BAN::RefPtr<AML::Integer> AML::Node::as_integer()
|
|
{
|
|
AML_TODO("Node type {} to integer", static_cast<uint32_t>(type));
|
|
return {};
|
|
}
|
|
|
|
BAN::RefPtr<AML::String> AML::Node::as_string()
|
|
{
|
|
AML_TODO("Node type {} to string", static_cast<uint32_t>(type));
|
|
return {};
|
|
}
|
|
|
|
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::BankFieldOp:
|
|
return AML::BankField::parse(context);
|
|
case AML::ExtOp::CreateFieldOp:
|
|
return AML::BufferField::parse(context);
|
|
case AML::ExtOp::OpRegionOp:
|
|
return AML::OpRegion::parse(context);
|
|
case AML::ExtOp::DeviceOp:
|
|
return AML::Device::parse(context);
|
|
case AML::ExtOp::MutexOp:
|
|
case AML::ExtOp::AcquireOp:
|
|
case AML::ExtOp::ReleaseOp:
|
|
return AML::Mutex::parse(context);
|
|
case AML::ExtOp::ProcessorOp:
|
|
return AML::Processor::parse(context);
|
|
case AML::ExtOp::PowerResOp:
|
|
return AML::PowerResource::parse(context);
|
|
case AML::ExtOp::ThermalZoneOp:
|
|
return AML::ThermalZone::parse(context);
|
|
case AML::ExtOp::CondRefOfOp:
|
|
return AML::Reference::parse(context);
|
|
case AML::ExtOp::SleepOp:
|
|
return AML::Sleep::parse(context);
|
|
case AML::ExtOp::DebugOp:
|
|
context.aml_data = context.aml_data.slice(2);
|
|
return ParseResult(AML::Namespace::debug_node);
|
|
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::Arg0:
|
|
case AML::Byte::Arg1:
|
|
case AML::Byte::Arg2:
|
|
case AML::Byte::Arg3:
|
|
case AML::Byte::Arg4:
|
|
case AML::Byte::Arg5:
|
|
case AML::Byte::Arg6:
|
|
{
|
|
uint8_t index = context.aml_data[0] - static_cast<uint8_t>(AML::Byte::Arg0);
|
|
context.aml_data = context.aml_data.slice(1);
|
|
return ParseResult(context.method_args[index]);
|
|
}
|
|
case AML::Byte::Local0:
|
|
case AML::Byte::Local1:
|
|
case AML::Byte::Local2:
|
|
case AML::Byte::Local3:
|
|
case AML::Byte::Local4:
|
|
case AML::Byte::Local5:
|
|
case AML::Byte::Local6:
|
|
case AML::Byte::Local7:
|
|
{
|
|
uint8_t index = context.aml_data[0] - static_cast<uint8_t>(AML::Byte::Local0);
|
|
context.aml_data = context.aml_data.slice(1);
|
|
return ParseResult(context.method_locals[index]);
|
|
}
|
|
case AML::Byte::AddOp:
|
|
case AML::Byte::AndOp:
|
|
case AML::Byte::DecrementOp:
|
|
case AML::Byte::DivideOp:
|
|
case AML::Byte::IncrementOp:
|
|
case AML::Byte::LAndOp:
|
|
case AML::Byte::LEqualOp:
|
|
case AML::Byte::LGreaterOp:
|
|
case AML::Byte::LLessOp:
|
|
case AML::Byte::LNotOp:
|
|
case AML::Byte::LOrOp:
|
|
case AML::Byte::ModOp:
|
|
case AML::Byte::MultiplyOp:
|
|
case AML::Byte::NandOp:
|
|
case AML::Byte::NorOp:
|
|
case AML::Byte::NotOp:
|
|
case AML::Byte::OrOp:
|
|
case AML::Byte::ShiftLeftOp:
|
|
case AML::Byte::ShiftRightOp:
|
|
case AML::Byte::SubtractOp:
|
|
case AML::Byte::XorOp:
|
|
return AML::Expression::parse(context);
|
|
case AML::Byte::CreateBitFieldOp:
|
|
case AML::Byte::CreateByteFieldOp:
|
|
case AML::Byte::CreateWordFieldOp:
|
|
case AML::Byte::CreateDWordFieldOp:
|
|
case AML::Byte::CreateQWordFieldOp:
|
|
return AML::BufferField::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);
|
|
case AML::Byte::IfOp:
|
|
return AML::IfElse::parse(context);
|
|
case AML::Byte::WhileOp:
|
|
return AML::While::parse(context);
|
|
case AML::Byte::StoreOp:
|
|
return AML::Store::parse(context);
|
|
case AML::Byte::DerefOfOp:
|
|
case AML::Byte::RefOfOp:
|
|
return AML::Reference::parse(context);
|
|
case AML::Byte::IndexOp:
|
|
return AML::Index::parse(context);
|
|
case AML::Byte::NotifyOp:
|
|
return AML::Notify::parse(context);
|
|
case AML::Byte::SizeOfOp:
|
|
return AML::SizeOf::parse(context);
|
|
case AML::Byte::NoopOp:
|
|
context.aml_data = context.aml_data.slice(1);
|
|
return ParseResult::Success;
|
|
case AML::Byte::ReturnOp:
|
|
{
|
|
context.aml_data = context.aml_data.slice(1);
|
|
auto result = AML::parse_object(context);
|
|
if (result.success())
|
|
return ParseResult(ParseResult::Result::Returned, result.node());
|
|
AML_ERROR("Failed to parse return value for method {}", context.scope);
|
|
return ParseResult::Failure;
|
|
}
|
|
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 = Namespace::root_namespace()->find_object(context.scope, name_string.value(), Namespace::FindMode::Normal);
|
|
if (!aml_object)
|
|
{
|
|
AML_ERROR("NameString {} not found in namespace", name_string.value());
|
|
return ParseResult::Failure;
|
|
}
|
|
if (aml_object->type == AML::Node::Type::Method)
|
|
{
|
|
auto* method = static_cast<AML::Method*>(aml_object.ptr());
|
|
|
|
BAN::Array<BAN::RefPtr<AML::Node>, 7> args;
|
|
for (uint8_t i = 0; i < method->arg_count; i++)
|
|
{
|
|
auto arg = AML::parse_object(context);
|
|
if (!arg.success())
|
|
{
|
|
AML_ERROR("Failed to parse argument {} for method {}", i, name_string.value());
|
|
return ParseResult::Failure;
|
|
}
|
|
args[i] = MUST(BAN::RefPtr<AML::Register>::create(arg.node()));
|
|
}
|
|
|
|
auto result = method->invoke_with_sync_stack(
|
|
context.sync_stack,
|
|
args[0],
|
|
args[1],
|
|
args[2],
|
|
args[3],
|
|
args[4],
|
|
args[5],
|
|
args[6]
|
|
);
|
|
if (!result.has_value())
|
|
{
|
|
AML_ERROR("Failed to evaluate {}", name_string.value());
|
|
return ParseResult::Failure;
|
|
}
|
|
if (!result.value())
|
|
return ParseResult::Success;
|
|
return ParseResult(result.value());
|
|
}
|
|
return ParseResult(aml_object);
|
|
}
|
|
|
|
AML_TODO("{2H}", context.aml_data[0]);
|
|
return ParseResult::Failure;
|
|
}
|
|
|
|
}
|