diff --git a/kernel/include/kernel/ACPI/AML/Conversion.h b/kernel/include/kernel/ACPI/AML/Conversion.h new file mode 100644 index 00000000..b755b16c --- /dev/null +++ b/kernel/include/kernel/ACPI/AML/Conversion.h @@ -0,0 +1,92 @@ +#pragma once + +#include +#include +#include +#include + +namespace Kernel::ACPI::AML +{ + + struct Conversion + { + static ParseResult parse(AML::ParseContext& context) + { + const auto opcode = static_cast(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(opcode)); + return ParseResult::Failure; + } + + if (context.aml_data.size() < 1) + { + AML_ERROR("Conversion {2H} missing target", static_cast(opcode)); + return ParseResult::Failure; + } + + BAN::RefPtr 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(opcode)); + return ParseResult::Failure; + } + } + + BAN::RefPtr converted; + switch (opcode) + { + case AML::Byte::ToBufferOp: + converted = data_node->as_buffer(); + break; + case AML::Byte::ToIntegerOp: + converted = data_node->as_integer(); + break; + case AML::Byte::ToStringOp: + converted = data_node->as_string(); + break; + default: + ASSERT_NOT_REACHED(); + } + + if (!converted) + { + AML_ERROR("Conversion {2H} could not convert from node type {}", static_cast(opcode), static_cast(data_node->type)); + return ParseResult::Failure; + } + + if (target_node && !target_node->store(converted)) + { + AML_ERROR("Conversion {2H} failed to store converted value", static_cast(opcode)); + return ParseResult::Failure; + } + + return ParseResult(converted); + } + }; + +} diff --git a/kernel/kernel/ACPI/AML/Node.cpp b/kernel/kernel/ACPI/AML/Node.cpp index 729fd62f..c686ee33 100644 --- a/kernel/kernel/ACPI/AML/Node.cpp +++ b/kernel/kernel/ACPI/AML/Node.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -166,6 +167,10 @@ namespace Kernel::ACPI case AML::Byte::SubtractOp: case AML::Byte::XorOp: return AML::Expression::parse(context); + case AML::Byte::ToBufferOp: + case AML::Byte::ToIntegerOp: + case AML::Byte::ToStringOp: + return AML::Conversion::parse(context); case AML::Byte::CreateBitFieldOp: case AML::Byte::CreateByteFieldOp: case AML::Byte::CreateWordFieldOp: