Files
banan-os/kernel/include/kernel/ACPI/AML/Conversion.h
Bananymous 3f5ee6f414 Kernel: Rewrite the AML conversion API
This doesn't currently make the interpreter any better, but it will make
further implementation easier to be spec (or hardware...) compliant
2024-08-15 02:25:45 +03:00

93 lines
2.3 KiB
C++

#pragma once
#include <kernel/ACPI/AML/Buffer.h>
#include <kernel/ACPI/AML/Integer.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/String.h>
namespace Kernel::ACPI::AML
{
struct Conversion
{
static ParseResult parse(AML::ParseContext& context)
{
const auto opcode = static_cast<AML::Byte>(context.aml_data[0]);
context.aml_data = context.aml_data.slice(1);
switch (opcode)
{
case AML::Byte::ToIntegerOp:
case AML::Byte::ToBufferOp:
case AML::Byte::ToStringOp:
break;
default:
ASSERT_NOT_REACHED();
}
auto data_result = AML::parse_object(context);
if (!data_result.success())
return ParseResult::Failure;
auto data_node = data_result.node();
if (!data_node)
{
AML_ERROR("Conversion {2H} data could not be evaluated", static_cast<uint8_t>(opcode));
return ParseResult::Failure;
}
if (context.aml_data.size() < 1)
{
AML_ERROR("Conversion {2H} missing target", static_cast<uint8_t>(opcode));
return ParseResult::Failure;
}
BAN::RefPtr<AML::Node> target_node;
if (context.aml_data[0] == 0x00)
context.aml_data = context.aml_data.slice(1);
else
{
auto target_result = AML::parse_object(context);
if (!target_result.success())
return ParseResult::Failure;
target_node = target_result.node();
if (!target_node)
{
AML_ERROR("Conversion {2H} target invalid", static_cast<uint8_t>(opcode));
return ParseResult::Failure;
}
}
BAN::RefPtr<AML::Node> converted;
switch (opcode)
{
case AML::Byte::ToBufferOp:
converted = data_node->convert(AML::Node::ConvBuffer);
break;
case AML::Byte::ToIntegerOp:
converted = data_node->convert(AML::Node::ConvInteger);
break;
case AML::Byte::ToStringOp:
converted = data_node->convert(AML::Node::ConvString);
break;
default:
ASSERT_NOT_REACHED();
}
if (!converted)
{
AML_ERROR("Conversion {2H} could not convert from node type {}", static_cast<uint8_t>(opcode), static_cast<uint8_t>(data_node->type));
return ParseResult::Failure;
}
if (target_node && !target_node->store(converted))
{
AML_ERROR("Conversion {2H} failed to store converted value", static_cast<uint8_t>(opcode));
return ParseResult::Failure;
}
return ParseResult(converted);
}
};
}