#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->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(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); } }; }