From 3f5ee6f414a7af4fb3b2ae276b1f49d9a7fe9726 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Thu, 15 Aug 2024 02:13:41 +0300 Subject: [PATCH] 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 --- kernel/CMakeLists.txt | 1 - kernel/include/kernel/ACPI/AML/Alias.h | 11 +- kernel/include/kernel/ACPI/AML/Buffer.h | 164 ++++++++++-------- kernel/include/kernel/ACPI/AML/Conversion.h | 6 +- kernel/include/kernel/ACPI/AML/Device.h | 4 +- kernel/include/kernel/ACPI/AML/Event.h | 19 +- kernel/include/kernel/ACPI/AML/Expression.h | 65 +++++-- kernel/include/kernel/ACPI/AML/Field.h | 76 ++++++-- kernel/include/kernel/ACPI/AML/IfElse.h | 7 +- kernel/include/kernel/ACPI/AML/Index.h | 32 ++-- kernel/include/kernel/ACPI/AML/Integer.h | 65 ++++--- kernel/include/kernel/ACPI/AML/Method.h | 22 +-- kernel/include/kernel/ACPI/AML/Mutex.h | 4 +- kernel/include/kernel/ACPI/AML/NamedObject.h | 20 +-- kernel/include/kernel/ACPI/AML/Namespace.h | 6 +- kernel/include/kernel/ACPI/AML/Node.h | 23 ++- kernel/include/kernel/ACPI/AML/Notify.h | 7 +- kernel/include/kernel/ACPI/AML/Package.h | 49 ++---- .../include/kernel/ACPI/AML/PowerResource.h | 4 +- kernel/include/kernel/ACPI/AML/Processor.h | 4 +- kernel/include/kernel/ACPI/AML/Reference.h | 71 +++++--- kernel/include/kernel/ACPI/AML/Region.h | 23 ++- kernel/include/kernel/ACPI/AML/Register.h | 30 ++-- kernel/include/kernel/ACPI/AML/SizeOf.h | 24 +-- kernel/include/kernel/ACPI/AML/Sleep.h | 12 +- kernel/include/kernel/ACPI/AML/Store.h | 4 +- kernel/include/kernel/ACPI/AML/String.h | 12 +- kernel/include/kernel/ACPI/AML/ThermalZone.h | 4 +- kernel/include/kernel/ACPI/AML/While.h | 8 +- kernel/kernel/ACPI/ACPI.cpp | 40 ++++- kernel/kernel/ACPI/AML/Field.cpp | 56 +++--- kernel/kernel/ACPI/AML/NamedObject.cpp | 18 -- kernel/kernel/ACPI/AML/Namespace.cpp | 7 +- kernel/kernel/ACPI/AML/Node.cpp | 22 +-- kernel/kernel/ACPI/AML/Register.cpp | 30 ---- kernel/kernel/ACPI/AML/Scope.cpp | 14 +- kernel/kernel/ACPI/AML/String.cpp | 16 +- 37 files changed, 564 insertions(+), 416 deletions(-) delete mode 100644 kernel/kernel/ACPI/AML/Register.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index cc86017b..3b99aba1 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -7,7 +7,6 @@ set(KERNEL_SOURCES kernel/ACPI/AML/Namespace.cpp kernel/ACPI/AML/Node.cpp kernel/ACPI/AML/Package.cpp - kernel/ACPI/AML/Register.cpp kernel/ACPI/AML/Scope.cpp kernel/ACPI/AML/String.cpp kernel/APIC.cpp diff --git a/kernel/include/kernel/ACPI/AML/Alias.h b/kernel/include/kernel/ACPI/AML/Alias.h index 315cb041..9e32ce79 100644 --- a/kernel/include/kernel/ACPI/AML/Alias.h +++ b/kernel/include/kernel/ACPI/AML/Alias.h @@ -7,7 +7,7 @@ namespace Kernel::ACPI::AML { - struct Alias : public AML::NamedObject + struct Alias final : public AML::NamedObject { BAN::RefPtr target; @@ -18,14 +18,11 @@ namespace Kernel::ACPI::AML bool is_scope() const override { return target->is_scope(); } + BAN::RefPtr convert(uint8_t) override { return {}; } + BAN::RefPtr copy() override { return target->copy(); } - BAN::RefPtr as_buffer() override { return target->as_buffer(); } - BAN::RefPtr as_integer() override { return target->as_integer(); } - BAN::RefPtr as_string() override { return target->as_string(); } - - BAN::RefPtr evaluate() override { return target->evaluate(); } - bool store(BAN::RefPtr node) override { return target->store(node); } + BAN::RefPtr store(BAN::RefPtr node) override { ASSERT(target); return target->store(node); } static ParseResult parse(ParseContext& context) { diff --git a/kernel/include/kernel/ACPI/AML/Buffer.h b/kernel/include/kernel/ACPI/AML/Buffer.h index 49d244b5..efed7471 100644 --- a/kernel/include/kernel/ACPI/AML/Buffer.h +++ b/kernel/include/kernel/ACPI/AML/Buffer.h @@ -10,7 +10,7 @@ namespace Kernel::ACPI::AML { - struct Buffer : public AML::Node + struct Buffer final : public AML::Node { BAN::Vector buffer; @@ -20,10 +20,10 @@ namespace Kernel::ACPI::AML BAN::Optional logical_compare(BAN::RefPtr node, AML::Byte binaryop) { - auto rhs = node ? node->as_buffer() : BAN::RefPtr(); - if (!rhs) + auto rhs_node = node ? node->convert(AML::Node::ConvBuffer) : BAN::RefPtr(); + if (!rhs_node) { - AML_ERROR("Buffer logical compare RHS is not buffer"); + AML_ERROR("Buffer logical compare RHS cannot be converted to buffer"); return {}; } @@ -32,19 +32,18 @@ namespace Kernel::ACPI::AML return {}; } - BAN::RefPtr as_buffer() override { return this; } - - BAN::RefPtr as_integer() override + BAN::RefPtr convert(uint8_t mask) override { - uint64_t value = 0; - for (size_t i = 0; i < BAN::Math::min(buffer.size(), 8); i++) - value |= static_cast(buffer[i]) << (8 * i); - return MUST(BAN::RefPtr::create(value)); - } - - BAN::RefPtr evaluate() override - { - return this; + if (mask & AML::Node::ConvBuffer) + return this; + if (mask & AML::Node::ConvInteger) + return as_integer(); + if (mask & AML::Node::ConvString) + { + AML_TODO("Convert BufferField to String"); + return {}; + } + return {}; } static ParseResult parse(AML::ParseContext& context) @@ -60,15 +59,21 @@ namespace Kernel::ACPI::AML auto buffer_context = context; buffer_context.aml_data = buffer_pkg.value(); - auto buffer_size_object = AML::parse_object(buffer_context); - if (!buffer_size_object.success()) + auto buffer_size_result = AML::parse_object(buffer_context); + if (!buffer_size_result.success()) return ParseResult::Failure; - auto buffer_size = buffer_size_object.node()->as_integer(); - if (!buffer_size) + auto buffer_size_node = buffer_size_result.node() ? buffer_size_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!buffer_size_node) + { + AML_ERROR("Buffer size is not an integer"); return ParseResult::Failure; + } - uint32_t actual_buffer_size = BAN::Math::max(buffer_size->value, buffer_context.aml_data.size()); + const uint32_t actual_buffer_size = BAN::Math::max( + static_cast(buffer_size_node.ptr())->value, + buffer_context.aml_data.size() + ); auto buffer = MUST(BAN::RefPtr::create()); MUST(buffer->buffer.resize(actual_buffer_size, 0)); @@ -88,9 +93,18 @@ namespace Kernel::ACPI::AML AML_DEBUG_PRINT_INDENT(indent); AML_DEBUG_PRINT("Buffer ({} bytes)", buffer.size()); } + + private: + BAN::RefPtr as_integer() + { + uint64_t value = 0; + for (size_t i = 0; i < BAN::Math::min(buffer.size(), 8); i++) + value |= static_cast(buffer[i]) << (8 * i); + return MUST(BAN::RefPtr::create(value)); + } }; - struct BufferField : AML::NamedObject + struct BufferField final : AML::NamedObject { BAN::RefPtr buffer; size_t field_bit_offset; @@ -104,49 +118,26 @@ namespace Kernel::ACPI::AML , field_bit_size(field_bit_size) {} - BAN::RefPtr as_integer() override + BAN::RefPtr convert(uint8_t mask) override { - ASSERT(buffer); - ASSERT(buffer->type == AML::Node::Type::Buffer || buffer->type == AML::Node::Type::String); - - const auto& buffer = (this->buffer->type == AML::Node::Type::Buffer) - ? static_cast(this->buffer.ptr())->buffer - : static_cast(this->buffer.ptr())->string; - - uint64_t value = 0; - - // TODO: optimize for whole byte accesses - for (size_t i = 0; i < BAN::Math::min(field_bit_size, 64); i++) + if (mask & AML::Node::ConvBufferField) + return this; + if (mask & AML::Node::ConvInteger) + return as_integer(); + if (mask & AML::Node::ConvBuffer) { - const size_t bit = field_bit_offset + i; - value |= static_cast((buffer[bit / 8] >> (bit % 8)) & 1) << i; + AML_TODO("Convert BufferField to Buffer"); + return {}; } - - return MUST(BAN::RefPtr::create(value)); + if (mask & AML::Node::ConvString) + { + AML_TODO("Convert BufferField to String"); + return {}; + } + return {}; } - BAN::RefPtr evaluate() override - { - ASSERT(buffer); - ASSERT(buffer->type == AML::Node::Type::Buffer || buffer->type == AML::Node::Type::String); - const auto& buffer = (this->buffer->type == AML::Node::Type::Buffer) - ? static_cast(this->buffer.ptr())->buffer - : static_cast(this->buffer.ptr())->string; - ASSERT(field_bit_offset + field_bit_size <= buffer.size() * 8); - - uint64_t value = 0; - - // TODO: optimize for whole byte accesses - for (size_t i = 0; i < field_bit_size; i++) - { - const size_t bit = field_bit_offset + i; - value |= static_cast((buffer[bit / 8] >> (bit % 8)) & 1) << i; - } - - return MUST(BAN::RefPtr::create(value)); - } - - bool store(BAN::RefPtr node) override + BAN::RefPtr store(BAN::RefPtr node) override { ASSERT(buffer); ASSERT(buffer->type == AML::Node::Type::Buffer || buffer->type == AML::Node::Type::String); @@ -155,19 +146,20 @@ namespace Kernel::ACPI::AML : static_cast(this->buffer.ptr())->string; ASSERT(field_bit_offset + field_bit_size <= buffer.size() * 8); - auto value = node->as_integer(); - if (!value) - return false; + auto value_node = node ? node->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!value_node) + return {}; + const auto value = static_cast(value_node.ptr())->value; // TODO: optimize for whole byte accesses for (size_t i = 0; i < field_bit_size; i++) { const size_t bit = field_bit_offset + 1; buffer[bit / 8] &= ~(1 << (bit % 8)); - buffer[bit / 8] |= ((value->value >> i) & 1) << (bit % 8); + buffer[bit / 8] |= ((value >> i) & 1) << (bit % 8); } - return true; + return value_node; } static ParseResult parse(AML::ParseContext& context) @@ -204,7 +196,7 @@ namespace Kernel::ACPI::AML auto buffer_result = AML::parse_object(context); if (!buffer_result.success()) return ParseResult::Failure; - auto buffer_node = buffer_result.node() ? buffer_result.node()->as_buffer() : BAN::RefPtr(); + auto buffer_node = buffer_result.node() ? buffer_result.node()->convert(AML::Node::ConvBuffer) : BAN::RefPtr(); if (!buffer_node || buffer_node->type != Node::Type::Buffer) { AML_ERROR("Buffer source does not evaluate to a Buffer"); @@ -215,28 +207,25 @@ namespace Kernel::ACPI::AML auto index_result = AML::parse_object(context); if (!index_result.success()) return ParseResult::Failure; - auto index = index_result.node() ? index_result.node()->as_integer() : BAN::RefPtr(); - if (!index) + auto index_node = index_result.node() ? index_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!index_node) { AML_ERROR("Failed to parse index for BufferField"); return ParseResult::Failure; } - size_t field_bit_offset = index->value; - if (field_bit_size != 1) - field_bit_offset *= 8; if (field_bit_size == 0) { auto bit_count_result = AML::parse_object(context); - if (!index_result.success()) + if (!bit_count_result.success()) return ParseResult::Failure; - auto bit_count = bit_count_result.node() ? bit_count_result.node()->as_integer() : BAN::RefPtr(); - if (!bit_count) + auto bit_count_node = bit_count_result.node() ? bit_count_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!bit_count_node) { AML_ERROR("Failed to parse bit count for BufferField"); return ParseResult::Failure; } - field_bit_size = bit_count->value; + field_bit_size = static_cast(bit_count_node.ptr())->value; } auto field_name = AML::NameString::parse(context.aml_data); @@ -248,6 +237,10 @@ namespace Kernel::ACPI::AML return ParseResult::Failure; } + size_t field_bit_offset = static_cast(index_node.ptr())->value; + if (field_bit_size != 1) + field_bit_offset *= 8; + auto field = MUST(BAN::RefPtr::create(field_name->path.back(), buffer, field_bit_offset, field_bit_size)); if (!Namespace::root_namespace()->add_named_object(context, field_name.value(), field)) return ParseResult::Success; @@ -268,6 +261,27 @@ namespace Kernel::ACPI::AML AML_DEBUG_PRINT(" }"); } + private: + BAN::RefPtr as_integer() + { + ASSERT(buffer); + ASSERT(buffer->type == AML::Node::Type::Buffer || buffer->type == AML::Node::Type::String); + + const auto& buffer = (this->buffer->type == AML::Node::Type::Buffer) + ? static_cast(this->buffer.ptr())->buffer + : static_cast(this->buffer.ptr())->string; + + uint64_t value = 0; + + // TODO: optimize for whole byte accesses + for (size_t i = 0; i < BAN::Math::min(field_bit_size, 64); i++) + { + const size_t bit = field_bit_offset + i; + value |= static_cast((buffer[bit / 8] >> (bit % 8)) & 1) << i; + } + + return MUST(BAN::RefPtr::create(value)); + } }; } diff --git a/kernel/include/kernel/ACPI/AML/Conversion.h b/kernel/include/kernel/ACPI/AML/Conversion.h index b755b16c..e89d9393 100644 --- a/kernel/include/kernel/ACPI/AML/Conversion.h +++ b/kernel/include/kernel/ACPI/AML/Conversion.h @@ -61,13 +61,13 @@ namespace Kernel::ACPI::AML switch (opcode) { case AML::Byte::ToBufferOp: - converted = data_node->as_buffer(); + converted = data_node->convert(AML::Node::ConvBuffer); break; case AML::Byte::ToIntegerOp: - converted = data_node->as_integer(); + converted = data_node->convert(AML::Node::ConvInteger); break; case AML::Byte::ToStringOp: - converted = data_node->as_string(); + converted = data_node->convert(AML::Node::ConvString); break; default: ASSERT_NOT_REACHED(); diff --git a/kernel/include/kernel/ACPI/AML/Device.h b/kernel/include/kernel/ACPI/AML/Device.h index 0349290b..cb6fd674 100644 --- a/kernel/include/kernel/ACPI/AML/Device.h +++ b/kernel/include/kernel/ACPI/AML/Device.h @@ -8,12 +8,14 @@ namespace Kernel::ACPI::AML { - struct Device : public AML::Scope + struct Device final : public AML::Scope { Device(NameSeg name) : Scope(Node::Type::Device, name) {} + BAN::RefPtr convert(uint8_t) override { return {}; } + static ParseResult parse(ParseContext& context) { ASSERT(context.aml_data.size() >= 2); diff --git a/kernel/include/kernel/ACPI/AML/Event.h b/kernel/include/kernel/ACPI/AML/Event.h index d5411d09..1a58171c 100644 --- a/kernel/include/kernel/ACPI/AML/Event.h +++ b/kernel/include/kernel/ACPI/AML/Event.h @@ -10,7 +10,7 @@ namespace Kernel::ACPI::AML { - struct Event : public AML::NamedObject + struct Event final : public AML::NamedObject { BAN::Atomic signal_count { 0 }; ThreadBlocker thread_blocker; @@ -19,6 +19,8 @@ namespace Kernel::ACPI::AML : NamedObject(Node::Type::Event, name) {} + BAN::RefPtr convert(uint8_t) override { return {}; } + static ParseResult parse(ParseContext& context) { ASSERT(context.aml_data.size() >= 2); @@ -43,7 +45,7 @@ namespace Kernel::ACPI::AML if (!event_result.success()) return ParseResult::Failure; - auto general_node = event_result.node() ? event_result.node()->evaluate() : BAN::RefPtr(); + auto general_node = event_result.node(); if (!general_node || general_node->type != Node::Type::Event) { AML_ERROR("Release, Wait or Signal does not name an event"); @@ -58,12 +60,15 @@ namespace Kernel::ACPI::AML if (!timeout_result.success()) return ParseResult::Failure; - auto timeout = timeout_result.node() ? timeout_result.node()->as_integer() : BAN::RefPtr(); - if (!timeout) + auto timeout_node = timeout_result.node() + ? timeout_result.node()->convert(AML::Node::ConvInteger) + : BAN::RefPtr(); + if (!timeout_node) { AML_ERROR("Wait timeout does not evaluate to integer"); return ParseResult::Failure; } + const auto timeout_value = static_cast(timeout_node.ptr())->value; const uint64_t start_ms = SystemTimer::get().ms_since_boot(); while (true) @@ -77,14 +82,14 @@ namespace Kernel::ACPI::AML return ParseResult(Integer::Constants::Zero); } - if (timeout->value >= 0xFFFF) + if (timeout_value >= 0xFFFF) event_node->thread_blocker.block_indefinite(); else { const uint64_t current_ms = SystemTimer::get().ms_since_boot(); - if (current_ms >= start_ms + timeout->value) + if (current_ms >= start_ms + timeout_value) return ParseResult(Integer::Constants::Ones); - event_node->thread_blocker.block_with_timeout_ms(start_ms + timeout->value - current_ms); + event_node->thread_blocker.block_with_timeout_ms(start_ms + timeout_value - current_ms); } } diff --git a/kernel/include/kernel/ACPI/AML/Expression.h b/kernel/include/kernel/ACPI/AML/Expression.h index 80f3dc04..1dff2aa0 100644 --- a/kernel/include/kernel/ACPI/AML/Expression.h +++ b/kernel/include/kernel/ACPI/AML/Expression.h @@ -1,9 +1,10 @@ #pragma once +#include #include #include -#include #include +#include namespace Kernel::ACPI::AML { @@ -25,13 +26,14 @@ namespace Kernel::ACPI::AML auto source_result = AML::parse_object(context); if (!source_result.success()) return ParseResult::Failure; - auto source_node = source_result.node() ? source_result.node()->as_integer(): BAN::RefPtr(); - if (!source_node) + auto conv_node = source_result.node() ? source_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!conv_node) { - AML_ERROR("UnaryOp source not integer"); + AML_ERROR("UnaryOp source not integer, type {}", static_cast(source_result.node()->type)); return ParseResult::Failure; } + auto source_node = static_cast(conv_node.ptr()); if (source_node->constant) { AML_ERROR("UnaryOp source is constant"); @@ -48,18 +50,23 @@ namespace Kernel::ACPI::AML { context.aml_data = context.aml_data.slice(1); - auto node_result = AML::parse_object(context); - if (!node_result.success()) + auto source_result = AML::parse_object(context); + if (!source_result.success()) return ParseResult::Failure; - - auto value = node_result.node() ? node_result.node()->as_integer() : BAN::RefPtr(); - if (!value) + auto conv_node = source_result.node() ? source_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!conv_node) + { + AML_ERROR("UnaryOp source not integer, type {}", static_cast(source_result.node()->type)); + return ParseResult::Failure; + } + auto source_node = static_cast(conv_node.ptr()); + if (!source_node) { AML_ERROR("Logical NotOp source is not integer"); return ParseResult::Failure; } - auto result = value->value ? Integer::Constants::Zero : Integer::Constants::Ones; + auto result = source_node->value ? Integer::Constants::Zero : Integer::Constants::Ones; return ParseResult(result); } case AML::Byte::AddOp: @@ -97,21 +104,25 @@ namespace Kernel::ACPI::AML auto lhs_result = AML::parse_object(context); if (!lhs_result.success()) return ParseResult::Failure; - auto lhs_value = lhs_result.node() ? lhs_result.node()->as_integer() : BAN::RefPtr(); - if (!lhs_value) + auto lhs_conv = lhs_result.node() ? lhs_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!lhs_conv) { - AML_ERROR("BinaryOP {2H} LHS not an integer", static_cast(opcode)); + AML_ERROR("BinaryOP {2H} LHS not an integer, type {}", + static_cast(opcode), + static_cast(lhs_result.node()->type) + ); if (lhs_result.node()) lhs_result.node()->debug_print(1); AML_DEBUG_PRINTLN(""); return ParseResult::Failure; } + const auto lhs_value = static_cast(lhs_conv.ptr())->value; auto rhs_result = AML::parse_object(context); if (!rhs_result.success()) return ParseResult::Failure; - auto rhs_value = rhs_result.node() ? rhs_result.node()->as_integer() : BAN::RefPtr(); - if (!rhs_value) + auto rhs_conv = rhs_result.node() ? rhs_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!rhs_conv) { AML_ERROR("BinaryOP {2H} RHS not an integer", static_cast(opcode)); if (rhs_result.node()) @@ -119,12 +130,14 @@ namespace Kernel::ACPI::AML AML_DEBUG_PRINTLN(""); return ParseResult::Failure; } + const auto rhs_value = static_cast(rhs_conv.ptr())->value; if (context.aml_data.size() < 1) { AML_ERROR("BinaryOP {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); @@ -159,9 +172,7 @@ namespace Kernel::ACPI::AML ASSERT_NOT_REACHED(); } - uint64_t result = func(lhs_value->value, rhs_value->value); - auto result_node = MUST(BAN::RefPtr::create(result)); - + auto result_node = MUST(BAN::RefPtr::create(func(lhs_value, rhs_value))); if (target_node && !target_node->store(result_node)) { AML_ERROR("BinaryOp {2H} failed to store result", static_cast(opcode)); @@ -176,10 +187,26 @@ namespace Kernel::ACPI::AML auto opcode = static_cast(context.aml_data[0]); context.aml_data = context.aml_data.slice(1); + uint8_t mask; + switch (opcode) + { + case AML::Byte::LAndOp: + case AML::Byte::LOrOp: + mask = AML::Node::ConvInteger; + break; + case AML::Byte::LEqualOp: + case AML::Byte::LGreaterOp: + case AML::Byte::LLessOp: + mask = AML::Node::ConvInteger | AML::Node::ConvString | AML::Node::ConvBuffer; + break; + default: + ASSERT_NOT_REACHED(); + } + auto lhs_result = AML::parse_object(context); if (!lhs_result.success()) return ParseResult::Failure; - auto lhs_node = lhs_result.node() ? lhs_result.node()->evaluate() : BAN::RefPtr(); + auto lhs_node = lhs_result.node() ? lhs_result.node()->convert(mask) : BAN::RefPtr(); if (!lhs_node) { AML_TODO("Logical BinaryOP {2H} LHS evaluated to nothing", static_cast(opcode)); diff --git a/kernel/include/kernel/ACPI/AML/Field.h b/kernel/include/kernel/ACPI/AML/Field.h index b3b57b20..04d577f1 100644 --- a/kernel/include/kernel/ACPI/AML/Field.h +++ b/kernel/include/kernel/ACPI/AML/Field.h @@ -47,7 +47,7 @@ namespace Kernel::ACPI::AML uint8_t access_length = 0; }; - struct FieldElement : public NamedObject + struct FieldElement final : public AML::NamedObject { uint64_t bit_offset; uint64_t bit_count; @@ -63,14 +63,30 @@ namespace Kernel::ACPI::AML , access_rules(access_rules) {} - BAN::RefPtr as_integer() override; + BAN::RefPtr convert(uint8_t mask) override + { + if (mask & AML::Node::ConvInteger) + return as_integer(); + if (mask & AML::Node::ConvBuffer) + { + AML_TODO("Convert BankFieldElement to Buffer"); + return {}; + } + if (mask & AML::Node::ConvString) + { + AML_TODO("Convert BankFieldElement to String"); + return {}; + } + return {}; + } - BAN::RefPtr evaluate() override { return as_integer(); } - bool store(BAN::RefPtr source) override; + BAN::RefPtr store(BAN::RefPtr source) override; void debug_print(int indent) const override; private: + BAN::RefPtr as_integer(); + BAN::Optional evaluate_internal(); bool store_internal(uint64_t value); @@ -83,7 +99,7 @@ namespace Kernel::ACPI::AML static ParseResult parse(ParseContext& context); }; - struct IndexFieldElement : public NamedObject + struct IndexFieldElement final : public AML::NamedObject { uint64_t bit_offset; uint64_t bit_count; @@ -100,12 +116,30 @@ namespace Kernel::ACPI::AML , access_rules(access_rules) {} - BAN::RefPtr as_integer() override; + BAN::RefPtr convert(uint8_t mask) override + { + if (mask & AML::Node::ConvInteger) + if (auto node = as_integer()) + return node; + if (mask & AML::Node::ConvBuffer) + { + AML_TODO("convert BankFieldElement to Buffer"); + return {}; + } + if (mask & AML::Node::ConvString) + { + AML_TODO("convert BankFieldElement to String"); + return {}; + } + return {}; + } - BAN::RefPtr evaluate() override { return as_integer(); } - bool store(BAN::RefPtr source) override; + BAN::RefPtr store(BAN::RefPtr source) override; void debug_print(int indent) const override; + + private: + BAN::RefPtr as_integer(); }; struct IndexField @@ -113,7 +147,7 @@ namespace Kernel::ACPI::AML static ParseResult parse(ParseContext& context); }; - struct BankFieldElement : public NamedObject + struct BankFieldElement final : public AML::NamedObject { uint64_t bit_offset; uint64_t bit_count; @@ -131,10 +165,30 @@ namespace Kernel::ACPI::AML , access_rules(access_rules) {} - BAN::RefPtr evaluate() override; - bool store(BAN::RefPtr source) override; + BAN::RefPtr convert(uint8_t mask) override + { + if (mask & AML::Node::ConvInteger) + if (auto node = as_integer()) + return node; + if (mask & AML::Node::ConvBuffer) + { + AML_TODO("convert BankFieldElement to Buffer"); + return {}; + } + if (mask & AML::Node::ConvString) + { + AML_TODO("convert BankFieldElement to String"); + return {}; + } + return {}; + } + + BAN::RefPtr store(BAN::RefPtr source) override; void debug_print(int indent) const override; + + private: + BAN::RefPtr as_integer(); }; struct BankField diff --git a/kernel/include/kernel/ACPI/AML/IfElse.h b/kernel/include/kernel/ACPI/AML/IfElse.h index bded25d0..37a09de5 100644 --- a/kernel/include/kernel/ACPI/AML/IfElse.h +++ b/kernel/include/kernel/ACPI/AML/IfElse.h @@ -26,12 +26,13 @@ namespace Kernel::ACPI::AML auto predicate_result = AML::parse_object(context); if (!predicate_result.success()) return ParseResult::Failure; - auto predicate = predicate_result.node() ? predicate_result.node()->as_integer() : BAN::RefPtr(); - if (!predicate) + auto predicate_node = predicate_result.node() ? predicate_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!predicate_node) { AML_ERROR("If predicate is not an integer"); return ParseResult::Failure; } + const auto predicate_value = static_cast(predicate_node.ptr())->value; // Else BAN::ConstByteSpan else_pkg; @@ -43,7 +44,7 @@ namespace Kernel::ACPI::AML return ParseResult::Failure; else_pkg = else_pkg_result.value(); } - if (predicate->value == 0) + if (predicate_value == 0) context.aml_data = else_pkg; while (context.aml_data.size() > 0) diff --git a/kernel/include/kernel/ACPI/AML/Index.h b/kernel/include/kernel/ACPI/AML/Index.h index 2549a482..d92a90ca 100644 --- a/kernel/include/kernel/ACPI/AML/Index.h +++ b/kernel/include/kernel/ACPI/AML/Index.h @@ -20,22 +20,32 @@ namespace Kernel::ACPI::AML auto source_result = AML::parse_object(context); if (!source_result.success()) return ParseResult::Failure; - auto source = source_result.node() ? source_result.node()->evaluate() : BAN::RefPtr(); + auto source = source_result.node() + ? source_result.node()->convert(AML::Node::ConvBuffer | AML::Node::ConvInteger | AML::Node::ConvString) + : BAN::RefPtr(); if (!source) { - AML_ERROR("IndexOp source is null"); + AML_ERROR("IndexOp source could not be converted"); + if (source) + { + source->debug_print(0); + AML_DEBUG_PRINTLN(""); + } return ParseResult::Failure; } auto index_result = AML::parse_object(context); if (!index_result.success()) return ParseResult::Failure; - auto index = index_result.node() ? index_result.node()->as_integer() : BAN::RefPtr(); - if (!index) + auto index_node = source_result.node() + ? source_result.node()->convert(AML::Node::ConvInteger) + : BAN::RefPtr(); + if (!index_node) { AML_ERROR("IndexOp index is not an integer"); return ParseResult::Failure; } + const auto index = static_cast(index_node.ptr())->value; BAN::RefPtr result; switch (source->type) @@ -43,36 +53,36 @@ namespace Kernel::ACPI::AML case AML::Node::Type::Buffer: { auto buffer = BAN::RefPtr(static_cast(source.ptr())); - if (index->value >= buffer->buffer.size()) + if (index >= buffer->buffer.size()) { AML_ERROR("IndexOp index is out of buffer bounds"); return ParseResult::Failure; } - auto buffer_field = MUST(BAN::RefPtr::create(NameSeg(""_sv), buffer, index->value * 8, 8)); + auto buffer_field = MUST(BAN::RefPtr::create(NameSeg(""_sv), buffer, index * 8, 8)); result = MUST(BAN::RefPtr::create(buffer_field)); break; } case AML::Node::Type::Package: { auto package = static_cast(source.ptr()); - if (index->value >= package->elements.size()) + if (index >= package->elements.size()) { AML_ERROR("IndexOp index is out of package bounds"); return ParseResult::Failure; } - auto package_element = package->elements[index->value]; + auto package_element = package->elements[index]; result = MUST(BAN::RefPtr::create(package_element)); break; } case AML::Node::Type::String: { auto string = BAN::RefPtr(static_cast(source.ptr())); - if (index->value >= string->string.size()) + if (index >= string->string.size()) { AML_ERROR("IndexOp index is out of string bounds"); return ParseResult::Failure; } - auto buffer_field = MUST(BAN::RefPtr::create(NameSeg(""_sv), string, index->value * 8, 8)); + auto buffer_field = MUST(BAN::RefPtr::create(NameSeg(""_sv), string, index * 8, 8)); result = MUST(BAN::RefPtr::create(buffer_field)); break; } @@ -82,7 +92,7 @@ namespace Kernel::ACPI::AML } #if AML_DEBUG_LEVEL >= 2 - AML_DEBUG_PRINT("Index {}, ", index->value); + AML_DEBUG_PRINT("Index {}, ", index); source->debug_print(0); AML_DEBUG_PRINTLN(""); #endif diff --git a/kernel/include/kernel/ACPI/AML/Integer.h b/kernel/include/kernel/ACPI/AML/Integer.h index baa223a1..6e3c3252 100644 --- a/kernel/include/kernel/ACPI/AML/Integer.h +++ b/kernel/include/kernel/ACPI/AML/Integer.h @@ -10,7 +10,7 @@ namespace Kernel::ACPI::AML { - struct Integer : public Node + struct Integer final : public AML::Node { struct Constants { @@ -31,49 +31,70 @@ namespace Kernel::ACPI::AML BAN::Optional logical_compare(BAN::RefPtr node, AML::Byte binaryop) { - auto rhs = node ? node->as_integer() : BAN::RefPtr(); - if (!rhs) + auto rhs_node = node ? node->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!rhs_node) { - AML_ERROR("Integer logical compare RHS is not integer"); + AML_ERROR("Integer logical compare RHS cannot be converted to"); return {}; } + const auto rhs_value = static_cast(rhs_node.ptr())->value; switch (binaryop) { - case AML::Byte::LAndOp: return value && rhs->value; - case AML::Byte::LEqualOp: return value == rhs->value; - case AML::Byte::LGreaterOp: return value > rhs->value; - case AML::Byte::LLessOp: return value < rhs->value; - case AML::Byte::LOrOp: return value || rhs->value; + case AML::Byte::LAndOp: return value && rhs_value; + case AML::Byte::LEqualOp: return value == rhs_value; + case AML::Byte::LGreaterOp: return value > rhs_value; + case AML::Byte::LLessOp: return value < rhs_value; + case AML::Byte::LOrOp: return value || rhs_value; default: ASSERT_NOT_REACHED(); } } - BAN::RefPtr as_integer() override { return this; } + BAN::RefPtr convert(uint8_t mask) override + { + if (mask & AML::Node::ConvInteger) + return this; + if (mask & AML::Node::ConvBuffer) + { + AML_TODO("Convert Integer to Buffer"); + return {}; + } + if (mask & AML::Node::ConvBufferField) + { + AML_TODO("Convert Integer to BufferField"); + return {}; + } + if (mask & AML::Node::ConvFieldUnit) + { + AML_TODO("Convert Integer to FieldUnit"); + return {}; + } + if (mask & AML::Node::ConvString) + { + AML_TODO("Convert Integer to String"); + return {}; + } + return {}; + } BAN::RefPtr copy() override { return MUST(BAN::RefPtr::create(value)); } - BAN::RefPtr evaluate() override - { - return this; - } - - bool store(BAN::RefPtr store_node) override + BAN::RefPtr store(BAN::RefPtr store_node) override { if (constant) { AML_ERROR("Cannot store to constant integer"); - return false; + return {}; } - auto store_value = store_node->as_integer(); - if (!store_value) + auto conv_node = store_node ? store_node->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!conv_node) { AML_ERROR("Cannot store non-integer to integer"); - return false; + return {}; } - value = store_value->value; - return true; + value = static_cast(conv_node.ptr())->value; + return MUST(BAN::RefPtr::create(value)); } static ParseResult parse(BAN::ConstByteSpan& aml_data) diff --git a/kernel/include/kernel/ACPI/AML/Method.h b/kernel/include/kernel/ACPI/AML/Method.h index 84b06993..c7e1740c 100644 --- a/kernel/include/kernel/ACPI/AML/Method.h +++ b/kernel/include/kernel/ACPI/AML/Method.h @@ -10,7 +10,7 @@ namespace Kernel::ACPI::AML { - struct Method : public AML::Scope + struct Method final : public AML::Scope { Kernel::Mutex mutex; uint8_t arg_count; @@ -27,6 +27,8 @@ namespace Kernel::ACPI::AML , sync_level(sync_level) {} + BAN::RefPtr convert(uint8_t) override { return {}; } + static ParseResult parse(AML::ParseContext& context) { ASSERT(context.aml_data.size() >= 1); @@ -98,13 +100,13 @@ namespace Kernel::ACPI::AML ParseContext context; context.aml_data = term_list; context.scope = scope; - context.method_args[0] = MUST(BAN::RefPtr::create(arg0)); - context.method_args[1] = MUST(BAN::RefPtr::create(arg1)); - context.method_args[2] = MUST(BAN::RefPtr::create(arg2)); - context.method_args[3] = MUST(BAN::RefPtr::create(arg3)); - context.method_args[4] = MUST(BAN::RefPtr::create(arg4)); - context.method_args[5] = MUST(BAN::RefPtr::create(arg5)); - context.method_args[6] = MUST(BAN::RefPtr::create(arg6)); + context.method_args[0] = MUST(BAN::RefPtr::create(arg0 && arg0->type == AML::Node::Type::Register ? static_cast(arg0.ptr())->value : arg0)); + context.method_args[1] = MUST(BAN::RefPtr::create(arg1 && arg1->type == AML::Node::Type::Register ? static_cast(arg1.ptr())->value : arg1)); + context.method_args[2] = MUST(BAN::RefPtr::create(arg2 && arg2->type == AML::Node::Type::Register ? static_cast(arg2.ptr())->value : arg2)); + context.method_args[3] = MUST(BAN::RefPtr::create(arg3 && arg3->type == AML::Node::Type::Register ? static_cast(arg3.ptr())->value : arg3)); + context.method_args[4] = MUST(BAN::RefPtr::create(arg4 && arg4->type == AML::Node::Type::Register ? static_cast(arg4.ptr())->value : arg4)); + context.method_args[5] = MUST(BAN::RefPtr::create(arg5 && arg5->type == AML::Node::Type::Register ? static_cast(arg5.ptr())->value : arg5)); + context.method_args[6] = MUST(BAN::RefPtr::create(arg6 && arg6->type == AML::Node::Type::Register ? static_cast(arg6.ptr())->value : arg6)); context.sync_stack = BAN::move(current_sync_stack); for (auto& local : context.method_locals) local = MUST(BAN::RefPtr::create()); @@ -142,8 +144,8 @@ namespace Kernel::ACPI::AML } } - if (return_value.has_value() && return_value.value()) - return_value = return_value.value()->evaluate(); + if (return_value.has_value() && return_value.value() && return_value.value()->type == AML::Node::Type::Register) + return_value.value() = static_cast(return_value.value().ptr())->value; while (!context.created_objects.empty()) { diff --git a/kernel/include/kernel/ACPI/AML/Mutex.h b/kernel/include/kernel/ACPI/AML/Mutex.h index 7aa23327..d10cdf7a 100644 --- a/kernel/include/kernel/ACPI/AML/Mutex.h +++ b/kernel/include/kernel/ACPI/AML/Mutex.h @@ -10,7 +10,7 @@ namespace Kernel::ACPI::AML { - struct Mutex : public AML::NamedObject + struct Mutex final : public AML::NamedObject { Kernel::Mutex mutex; uint8_t sync_level; @@ -20,6 +20,8 @@ namespace Kernel::ACPI::AML , sync_level(sync_level) {} + BAN::RefPtr convert(uint8_t) override { return {}; } + static ParseResult parse(ParseContext& context) { ASSERT(context.aml_data.size() >= 2); diff --git a/kernel/include/kernel/ACPI/AML/NamedObject.h b/kernel/include/kernel/ACPI/AML/NamedObject.h index 28c2abe2..fe9e2469 100644 --- a/kernel/include/kernel/ACPI/AML/NamedObject.h +++ b/kernel/include/kernel/ACPI/AML/NamedObject.h @@ -6,7 +6,7 @@ namespace Kernel::ACPI::AML { - struct NamedObject : public Node + struct NamedObject : public AML::Node { BAN::RefPtr parent; NameSeg name; @@ -14,7 +14,7 @@ namespace Kernel::ACPI::AML NamedObject(Node::Type type, NameSeg name) : Node(type), name(name) {} }; - struct Name : public NamedObject + struct Name final : public AML::NamedObject { BAN::RefPtr object; @@ -22,21 +22,15 @@ namespace Kernel::ACPI::AML : NamedObject(Node::Type::Name, name), object(BAN::move(object)) {} - BAN::RefPtr as_buffer() override; - BAN::RefPtr as_integer() override; - BAN::RefPtr as_string() override; + BAN::RefPtr convert(uint8_t) override { return {}; } - BAN::RefPtr evaluate() override - { - ASSERT(object); - return object->evaluate(); - } - - bool store(BAN::RefPtr node) override + BAN::RefPtr store(BAN::RefPtr node) override { ASSERT(object); + if (object->type == AML::Node::Type::Reference) + return object->store(node); object = node; - return true; + return node; } static ParseResult parse(ParseContext& context); diff --git a/kernel/include/kernel/ACPI/AML/Namespace.h b/kernel/include/kernel/ACPI/AML/Namespace.h index bd937bb0..85030167 100644 --- a/kernel/include/kernel/ACPI/AML/Namespace.h +++ b/kernel/include/kernel/ACPI/AML/Namespace.h @@ -8,8 +8,9 @@ namespace Kernel::ACPI::AML { - struct Namespace : public AML::Scope + struct Namespace final : public AML::Scope { + static BAN::RefPtr create_root_namespace(); static BAN::RefPtr root_namespace(); static BAN::RefPtr debug_node; @@ -35,7 +36,8 @@ namespace Kernel::ACPI::AML Namespace(NameSeg name) : AML::Scope(Node::Type::Namespace, name) {} - static BAN::RefPtr create_root_namespace(); + BAN::RefPtr convert(uint8_t) override { return {}; } + bool parse(const SDTHeader& header); void debug_print(int indent) const override; diff --git a/kernel/include/kernel/ACPI/AML/Node.h b/kernel/include/kernel/ACPI/AML/Node.h index c568a623..eb965805 100644 --- a/kernel/include/kernel/ACPI/AML/Node.h +++ b/kernel/include/kernel/ACPI/AML/Node.h @@ -17,8 +17,18 @@ namespace Kernel::ACPI::AML { static uint64_t total_node_count; - enum class Type + enum Conversion : uint8_t { + ConvBuffer = 1 << 0, + ConvBufferField = 1 << 1, + ConvFieldUnit = 1 << 2, + ConvInteger = 1 << 3, + ConvString = 1 << 4, + }; + + enum class Type : uint8_t + { + None, Alias, BankFieldElement, Buffer, @@ -50,14 +60,9 @@ namespace Kernel::ACPI::AML virtual bool is_scope() const { return false; } - virtual BAN::RefPtr copy() { return this; } - - [[nodiscard]] virtual BAN::RefPtr as_buffer(); - [[nodiscard]] virtual BAN::RefPtr as_integer(); - [[nodiscard]] virtual BAN::RefPtr as_string(); - - [[nodiscard]] virtual BAN::RefPtr evaluate() { AML_TODO("evaluate, type {}", static_cast(type)); return nullptr; } - [[nodiscard]] virtual bool store(BAN::RefPtr) { AML_TODO("store, type {}", static_cast(type)); return false; } + [[nodiscard]] virtual BAN::RefPtr convert(uint8_t mask) = 0; + [[nodiscard]] virtual BAN::RefPtr copy() { return this; } + [[nodiscard]] virtual BAN::RefPtr store(BAN::RefPtr) { AML_TODO("store, type {}", static_cast(type)); return {}; } virtual void debug_print(int indent) const = 0; }; diff --git a/kernel/include/kernel/ACPI/AML/Notify.h b/kernel/include/kernel/ACPI/AML/Notify.h index e5871f65..f75879e2 100644 --- a/kernel/include/kernel/ACPI/AML/Notify.h +++ b/kernel/include/kernel/ACPI/AML/Notify.h @@ -29,12 +29,13 @@ namespace Kernel::ACPI::AML auto value_result = AML::parse_object(context); if (!value_result.success()) return ParseResult::Failure; - auto value = value_result.node() ? value_result.node()->as_integer() : BAN::RefPtr(); - if (!value) + auto value_node = value_result.node() ? value_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!value_node) { AML_ERROR("Notify value is not an integer"); return ParseResult::Failure; } + const auto value = static_cast(value_node.ptr())->value; BAN::StringView object_type_sv; BAN::StringView object_name_sv; @@ -58,7 +59,7 @@ namespace Kernel::ACPI::AML break; } - AML_TODO("Notify: {} {}: {2H}", object_type_sv, object_name_sv, value->value); + AML_TODO("Notify: {} {}: {2H}", object_type_sv, object_name_sv, value); return ParseResult::Success; } }; diff --git a/kernel/include/kernel/ACPI/AML/Package.h b/kernel/include/kernel/ACPI/AML/Package.h index 270dd81a..9991d778 100644 --- a/kernel/include/kernel/ACPI/AML/Package.h +++ b/kernel/include/kernel/ACPI/AML/Package.h @@ -11,7 +11,7 @@ namespace Kernel::ACPI::AML struct PackageElement; - struct Package : public AML::Node + struct Package final : public AML::Node { BAN::Vector> elements; AML::NameString scope; @@ -22,16 +22,13 @@ namespace Kernel::ACPI::AML , scope(scope) {} - BAN::RefPtr evaluate() override - { - return this; - } + BAN::RefPtr convert(uint8_t) override { return {}; } static ParseResult parse(AML::ParseContext& context); virtual void debug_print(int indent) const override; }; - struct PackageElement : public AML::Node + struct PackageElement final : public AML::Node { BAN::RefPtr parent; BAN::RefPtr element; @@ -82,7 +79,19 @@ namespace Kernel::ACPI::AML return true; } - bool store(BAN::RefPtr node) override + BAN::RefPtr convert(uint8_t mask) override + { + if (!initialized) + { + AML_ERROR("Trying to store into uninitialized PackageElement"); + return {}; + } + if (!resolved && !resolve()) + return {}; + return element->convert(mask); + } + + BAN::RefPtr store(BAN::RefPtr node) override { if (!initialized) { @@ -94,31 +103,7 @@ namespace Kernel::ACPI::AML if (element->type == AML::Node::Type::Reference) return element->store(node); element = node->copy(); - return true; - } - - BAN::RefPtr as_integer() override - { - if (!initialized) - { - AML_ERROR("Trying to evaluate uninitialized PackageElement"); - return {}; - } - if (!resolved && !resolve()) - return {}; - return element->as_integer(); - } - - BAN::RefPtr evaluate() override - { - if (!initialized) - { - AML_ERROR("Trying to evaluate uninitialized PackageElement"); - return {}; - } - if (!resolved && !resolve()) - return {}; - return element->evaluate(); + return element; } static ParseResult parse(AML::ParseContext& context, BAN::RefPtr package) diff --git a/kernel/include/kernel/ACPI/AML/PowerResource.h b/kernel/include/kernel/ACPI/AML/PowerResource.h index a96892fb..f7b27702 100644 --- a/kernel/include/kernel/ACPI/AML/PowerResource.h +++ b/kernel/include/kernel/ACPI/AML/PowerResource.h @@ -9,7 +9,7 @@ namespace Kernel::ACPI::AML { - struct PowerResource : public AML::Scope + struct PowerResource final : public AML::Scope { uint8_t system_level; uint16_t resource_order; @@ -20,6 +20,8 @@ namespace Kernel::ACPI::AML , resource_order(resource_order) {} + BAN::RefPtr convert(uint8_t) override { return {}; } + static ParseResult parse(ParseContext& context) { ASSERT(context.aml_data.size() >= 2); diff --git a/kernel/include/kernel/ACPI/AML/Processor.h b/kernel/include/kernel/ACPI/AML/Processor.h index 3402e345..d4a55c66 100644 --- a/kernel/include/kernel/ACPI/AML/Processor.h +++ b/kernel/include/kernel/ACPI/AML/Processor.h @@ -9,7 +9,7 @@ namespace Kernel::ACPI::AML { - struct Processor : public AML::Scope + struct Processor final : public AML::Scope { uint8_t id; uint32_t pblk_addr; @@ -22,6 +22,8 @@ namespace Kernel::ACPI::AML , pblk_len(pblk_len) {} + BAN::RefPtr convert(uint8_t) override { return {}; } + static ParseResult parse(ParseContext& context) { ASSERT(context.aml_data.size() >= 2); diff --git a/kernel/include/kernel/ACPI/AML/Reference.h b/kernel/include/kernel/ACPI/AML/Reference.h index 74aaec03..fade7dfa 100644 --- a/kernel/include/kernel/ACPI/AML/Reference.h +++ b/kernel/include/kernel/ACPI/AML/Reference.h @@ -10,7 +10,7 @@ namespace Kernel::ACPI::AML { - struct Reference : public AML::Node + struct Reference final : public AML::Node { BAN::RefPtr node; @@ -21,24 +21,22 @@ namespace Kernel::ACPI::AML ASSERT(node); } - BAN::RefPtr as_integer() override - { - if (node) - return node->as_integer(); - return {}; - } - - BAN::RefPtr evaluate() override - { - return this; - } - - bool store(BAN::RefPtr value) override + BAN::RefPtr convert(uint8_t mask) override { if (!node) { - AML_ERROR("Storing to null reference"); - return false; + AML_ERROR("Trying to convert null Reference"); + return {}; + } + return node->convert(mask); + } + + BAN::RefPtr store(BAN::RefPtr value) override + { + if (!node) + { + AML_ERROR("Storing to null Reference"); + return {}; } return node->store(value); } @@ -79,6 +77,8 @@ namespace Kernel::ACPI::AML if (!parse_result.success()) return ParseResult::Failure; object = parse_result.node(); + if (object && object->type == AML::Node::Type::Register) + object = static_cast(object.ptr())->value; } if (!conditional) @@ -96,18 +96,26 @@ namespace Kernel::ACPI::AML return ParseResult(reference); } - if (context.aml_data.size() >= 1 && context.aml_data[0] != 0x00) + if (context.aml_data.size() < 1) + { + AML_ERROR("CondRefOf missing target"); + 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; - auto target_node = target_result.node(); + target_node = target_result.node(); if (!target_node) { AML_ERROR("CondRefOf failed to resolve target"); return ParseResult::Failure; } - target_node->store(MUST(BAN::RefPtr::create(object))); } #if AML_DEBUG_LEVEL >= 2 @@ -119,8 +127,16 @@ namespace Kernel::ACPI::AML AML_DEBUG_PRINTLN(""); #endif - auto return_value = object ? Integer::Constants::Ones : Integer::Constants::Zero; - return AML::ParseResult(return_value); + if (!object) + return AML::ParseResult(Integer::Constants::Zero); + + if (target_node && !target_node->store(object)) + { + AML_ERROR("CondRefOf failed to store into target"); + return ParseResult::Failure; + } + + return AML::ParseResult(Integer::Constants::Ones); } static ParseResult parse_dereference(ParseContext& context) @@ -144,18 +160,20 @@ namespace Kernel::ACPI::AML auto parse_result = AML::parse_object(context); if (!parse_result.success()) return ParseResult::Failure; - auto object = parse_result.node() ? parse_result.node()->evaluate() : BAN::RefPtr(); - if (!object || object->type != AML::Node::Type::Reference) + auto node = parse_result.node(); + if (node && node->type == AML::Node::Type::Register) + node = static_cast(node.ptr())->value; + if (!node || node->type != AML::Node::Type::Reference) { - AML_TODO("DerefOf source is not a Reference, but a {}", object ? static_cast(object->type) : 999); + AML_TODO("DerefOf source is not a Reference, but a {}", node ? static_cast(node->type) : 999); return ParseResult::Failure; } #if AML_DEBUG_LEVEL >= 2 AML_DEBUG_PRINT("DerefOf "); - object->debug_print(0); + node->debug_print(0); AML_DEBUG_PRINTLN(""); #endif - return ParseResult(static_cast(object.ptr())->node); + return ParseResult(static_cast(node.ptr())->node); } } @@ -164,6 +182,7 @@ namespace Kernel::ACPI::AML AML_DEBUG_PRINT_INDENT(indent); AML_DEBUG_PRINTLN("Reference {"); node->debug_print(indent + 1); + AML_DEBUG_PRINTLN(""); AML_DEBUG_PRINT_INDENT(indent); AML_DEBUG_PRINT("}"); } diff --git a/kernel/include/kernel/ACPI/AML/Region.h b/kernel/include/kernel/ACPI/AML/Region.h index ad599b8c..5080d51a 100644 --- a/kernel/include/kernel/ACPI/AML/Region.h +++ b/kernel/include/kernel/ACPI/AML/Region.h @@ -8,7 +8,7 @@ namespace Kernel::ACPI::AML { - struct OpRegion : public NamedObject + struct OpRegion final : public AML::NamedObject { using RegionSpace = GAS::AddressSpaceID; RegionSpace region_space; @@ -24,6 +24,8 @@ namespace Kernel::ACPI::AML , region_length(region_length) {} + BAN::RefPtr convert(uint8_t) override { return {}; } + static ParseResult parse(AML::ParseContext& context) { ASSERT(context.aml_data.size() > 2); @@ -43,8 +45,10 @@ namespace Kernel::ACPI::AML auto offset_result = AML::parse_object(context); if (!offset_result.success()) return ParseResult::Failure; - auto offset = offset_result.node()->as_integer(); - if (!offset) + auto offset_node = offset_result.node() + ? offset_result.node()->convert(AML::Node::ConvInteger) + : BAN::RefPtr(); + if (!offset_node) { AML_ERROR("OpRegion offset must be an integer"); return ParseResult::Failure; @@ -53,18 +57,23 @@ namespace Kernel::ACPI::AML auto length_result = AML::parse_object(context); if (!length_result.success()) return ParseResult::Failure; - auto length = length_result.node()->as_integer(); - if (!length) + auto length_node = length_result.node() + ? length_result.node()->convert(AML::Node::ConvInteger) + : BAN::RefPtr(); + if (!length_node) { AML_ERROR("OpRegion length must be an integer"); return ParseResult::Failure; } + const auto offset = static_cast(offset_node.ptr())->value; + const auto length = static_cast(length_node.ptr())->value; + auto op_region = MUST(BAN::RefPtr::create( name->path.back(), region_space, - offset->value, - length->value + offset, + length )); if (!Namespace::root_namespace()->add_named_object(context, name.value(), op_region)) diff --git a/kernel/include/kernel/ACPI/AML/Register.h b/kernel/include/kernel/ACPI/AML/Register.h index 8ca942e8..c2123947 100644 --- a/kernel/include/kernel/ACPI/AML/Register.h +++ b/kernel/include/kernel/ACPI/AML/Register.h @@ -5,7 +5,7 @@ namespace Kernel::ACPI::AML { - struct Register : public AML::Node + struct Register final : public AML::Node { BAN::RefPtr value; @@ -17,30 +17,22 @@ namespace Kernel::ACPI::AML , value(value) {} - BAN::RefPtr as_buffer() override; - BAN::RefPtr as_integer() override; - BAN::RefPtr as_string() override; - - BAN::RefPtr evaluate() override + BAN::RefPtr convert(uint8_t mask) override { - if (value) - return value->evaluate(); - return {}; + if (!value) + { + AML_ERROR("Trying to convert null Register"); + return {}; + } + return value->convert(mask); } - bool store(BAN::RefPtr source) override + BAN::RefPtr store(BAN::RefPtr source) override { if (value && value->type == AML::Node::Type::Reference) return value->store(source); - - auto evaluated = source->evaluate(); - if (!evaluated) - { - AML_ERROR("Failed to evaluate source for store"); - return false; - } - value = evaluated->copy(); - return true; + value = source->copy(); + return value; } void debug_print(int indent) const override diff --git a/kernel/include/kernel/ACPI/AML/SizeOf.h b/kernel/include/kernel/ACPI/AML/SizeOf.h index 1187b980..828fad96 100644 --- a/kernel/include/kernel/ACPI/AML/SizeOf.h +++ b/kernel/include/kernel/ACPI/AML/SizeOf.h @@ -21,30 +21,34 @@ namespace Kernel::ACPI::AML auto object_result = AML::parse_object(context); if (!object_result.success()) return ParseResult::Failure; - auto object = object_result.node()->evaluate(); - if (object && object->type == AML::Node::Type::Reference) - object = static_cast(object.ptr())->node->evaluate(); - if (!object) + auto object_node = object_result.node(); + if (!object_node) { AML_ERROR("SizeOf object is null"); return ParseResult::Failure; } + if (object_node->type != AML::Node::Type::Package) + object_node = object_node->convert(AML::Node::ConvBuffer | AML::Node::ConvString); + if (!object_node) + { + AML_ERROR("SizeOf object is not Buffer, String or Package"); + return ParseResult::Failure; + } uint64_t size = 0; - switch (object->type) + switch (object_node->type) { case AML::Node::Type::Buffer: - size = static_cast(object.ptr())->buffer.size(); + size = static_cast(object_node.ptr())->buffer.size(); break; case AML::Node::Type::String: - size = static_cast(object.ptr())->string.size(); + size = static_cast(object_node.ptr())->string.size(); break; case AML::Node::Type::Package: - size = static_cast(object.ptr())->elements.size(); + size = static_cast(object_node.ptr())->elements.size(); break; default: - AML_ERROR("SizeOf object is not a buffer, string or package ({})", static_cast(object->type)); - return ParseResult::Failure; + ASSERT_NOT_REACHED(); } return ParseResult(MUST(BAN::RefPtr::create(size))); diff --git a/kernel/include/kernel/ACPI/AML/Sleep.h b/kernel/include/kernel/ACPI/AML/Sleep.h index 2bdeac10..bcbf08e0 100644 --- a/kernel/include/kernel/ACPI/AML/Sleep.h +++ b/kernel/include/kernel/ACPI/AML/Sleep.h @@ -19,18 +19,22 @@ namespace Kernel::ACPI::AML auto sleep_time_result = AML::parse_object(context); if (!sleep_time_result.success()) return ParseResult::Failure; - auto sleep_time = sleep_time_result.node() ? sleep_time_result.node()->as_integer() : BAN::RefPtr(); - if (!sleep_time) + auto sleep_time_node = sleep_time_result.node() + ? sleep_time_result.node()->convert(AML::Node::ConvInteger) + : BAN::RefPtr(); + if (!sleep_time_node) { AML_ERROR("Sleep time cannot be evaluated to an integer"); return ParseResult::Failure; } + const auto sleep_time_value = static_cast(sleep_time_node.ptr())->value; + #if AML_DEBUG_LEVEL >= 2 - AML_DEBUG_PRINTLN("Sleeping for {} ms", sleep_time->value); + AML_DEBUG_PRINTLN("Sleeping for {} ms", sleep_time_value); #endif - SystemTimer::get().sleep_ms(sleep_time->value); + SystemTimer::get().sleep_ms(sleep_time_value); return ParseResult::Success; } }; diff --git a/kernel/include/kernel/ACPI/AML/Store.h b/kernel/include/kernel/ACPI/AML/Store.h index ab8df726..62fa30ac 100644 --- a/kernel/include/kernel/ACPI/AML/Store.h +++ b/kernel/include/kernel/ACPI/AML/Store.h @@ -17,10 +17,10 @@ namespace Kernel::ACPI::AML auto source_result = AML::parse_object(context); if (!source_result.success()) return ParseResult::Failure; - auto source = source_result.node() ? source_result.node()->evaluate() : BAN::RefPtr(); + auto source = source_result.node(); if (!source) { - AML_ERROR("Store source cannot be evaluated"); + AML_ERROR("Store source is null"); return ParseResult::Failure; } diff --git a/kernel/include/kernel/ACPI/AML/String.h b/kernel/include/kernel/ACPI/AML/String.h index 2d0806b0..908f674c 100644 --- a/kernel/include/kernel/ACPI/AML/String.h +++ b/kernel/include/kernel/ACPI/AML/String.h @@ -7,7 +7,7 @@ namespace Kernel::ACPI::AML { - struct String : public AML::Node + struct String final : public AML::Node { BAN::Vector string; @@ -22,12 +22,7 @@ namespace Kernel::ACPI::AML BAN::Optional logical_compare(BAN::RefPtr node, AML::Byte binaryop); - BAN::RefPtr as_buffer() override; - - BAN::RefPtr evaluate() override - { - return this; - } + BAN::RefPtr convert(uint8_t mask) override; BAN::StringView string_view() const { @@ -41,6 +36,9 @@ namespace Kernel::ACPI::AML AML_DEBUG_PRINT_INDENT(indent); AML_DEBUG_PRINT("String \"{}\"", string_view()); } + + private: + BAN::RefPtr as_buffer(); }; } diff --git a/kernel/include/kernel/ACPI/AML/ThermalZone.h b/kernel/include/kernel/ACPI/AML/ThermalZone.h index 675c3552..3328042a 100644 --- a/kernel/include/kernel/ACPI/AML/ThermalZone.h +++ b/kernel/include/kernel/ACPI/AML/ThermalZone.h @@ -9,12 +9,14 @@ namespace Kernel::ACPI::AML { - struct ThermalZone : public AML::Scope + struct ThermalZone final : public AML::Scope { ThermalZone(NameSeg name) : Scope(Node::Type::ThermalZone, name) {} + BAN::RefPtr convert(uint8_t) override { return {}; } + static ParseResult parse(ParseContext& context) { ASSERT(context.aml_data.size() >= 2); diff --git a/kernel/include/kernel/ACPI/AML/While.h b/kernel/include/kernel/ACPI/AML/While.h index 02fc4f36..2dbfd15a 100644 --- a/kernel/include/kernel/ACPI/AML/While.h +++ b/kernel/include/kernel/ACPI/AML/While.h @@ -29,14 +29,16 @@ namespace Kernel::ACPI::AML auto predicate_result = AML::parse_object(context); if (!predicate_result.success()) return ParseResult::Failure; - auto predicate = predicate_result.node() ? predicate_result.node()->as_integer() : BAN::RefPtr(); - if (!predicate) + auto predicate_node = predicate_result.node() + ? predicate_result.node()->convert(AML::Node::ConvInteger) + : BAN::RefPtr(); + if (!predicate_node) { AML_ERROR("While predicate is not an integer"); return ParseResult::Failure; } - if (!predicate->value) + if (!static_cast(predicate_node.ptr())->value) break; while (context.aml_data.size() > 0) diff --git a/kernel/kernel/ACPI/ACPI.cpp b/kernel/kernel/ACPI/ACPI.cpp index 720c156a..b494a0fb 100644 --- a/kernel/kernel/ACPI/ACPI.cpp +++ b/kernel/kernel/ACPI/ACPI.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -144,10 +145,10 @@ acpi_release_global_lock: auto field_element = MUST(BAN::RefPtr::create(""_sv, register_bit_offset, register_bit_width, field_rules)); field_element->op_region = op_region; - auto result = field_element->as_integer(); + auto result = field_element->convert(AML::Node::ConvInteger); if (!result) return {}; - return result->value; + return static_cast(result.ptr())->value; } bool GAS::write(uint64_t value) @@ -168,7 +169,7 @@ acpi_release_global_lock: auto field_element = MUST(BAN::RefPtr::create(""_sv, register_bit_offset, register_bit_width, field_rules)); field_element->op_region = op_region; - return field_element->store(MUST(BAN::RefPtr::create(value))); + return !!field_element->store(MUST(BAN::RefPtr::create(value))); } enum PM1Event : uint16_t @@ -494,7 +495,25 @@ acpi_release_global_lock: dwarnln("\\_S5 not found"); return; } - auto s5_evaluated = s5_object->evaluate(); + BAN::RefPtr s5_evaluated = s5_object; + while (true) + { + bool done = false; + switch (s5_evaluated->type) + { + case AML::Node::Type::Alias: + s5_evaluated = static_cast(s5_evaluated.ptr())->target; + break; + case AML::Node::Type::Name: + s5_evaluated = static_cast(s5_evaluated.ptr())->object; + break; + default: + done = true; + break; + } + if (done) + break; + } if (!s5_evaluated) { dwarnln("Failed to evaluate \\_S5"); @@ -512,9 +531,9 @@ acpi_release_global_lock: return; } - auto slp_typa = s5_package->elements[0]->as_integer(); - auto slp_typb = s5_package->elements[1]->as_integer(); - if (!slp_typa || !slp_typb) + auto slp_typa_node = s5_package->elements[0]->convert(AML::Node::ConvInteger); + auto slp_typb_node = s5_package->elements[1]->convert(AML::Node::ConvInteger); + if (!slp_typa_node || !slp_typb_node) { dwarnln("Failed to get SLP_TYPx values"); return; @@ -525,9 +544,12 @@ acpi_release_global_lock: dprintln("Entering sleep state S5"); + const auto slp_typa_value = static_cast(slp_typa_node.ptr())->value; + const auto slp_typb_value = static_cast(slp_typb_node.ptr())->value; + uint16_t pm1a_data = IO::inw(fadt().pm1a_cnt_blk); pm1a_data &= ~(PM1_CNT_SLP_TYP_MASK << PM1_CNT_SLP_TYP_SHIFT); - pm1a_data |= (slp_typa->value & PM1_CNT_SLP_TYP_MASK) << PM1_CNT_SLP_TYP_SHIFT; + pm1a_data |= (slp_typa_value & PM1_CNT_SLP_TYP_MASK) << PM1_CNT_SLP_TYP_SHIFT; pm1a_data |= PM1_CNT_SLP_EN; IO::outw(fadt().pm1a_cnt_blk, pm1a_data); @@ -535,7 +557,7 @@ acpi_release_global_lock: { uint16_t pm1b_data = IO::inw(fadt().pm1b_cnt_blk); pm1b_data &= ~(PM1_CNT_SLP_TYP_MASK << PM1_CNT_SLP_TYP_SHIFT); - pm1b_data |= (slp_typb->value & PM1_CNT_SLP_TYP_MASK) << PM1_CNT_SLP_TYP_SHIFT; + pm1b_data |= (slp_typb_value & PM1_CNT_SLP_TYP_MASK) << PM1_CNT_SLP_TYP_SHIFT; pm1b_data |= PM1_CNT_SLP_EN; IO::outw(fadt().pm1b_cnt_blk, pm1b_data); } diff --git a/kernel/kernel/ACPI/AML/Field.cpp b/kernel/kernel/ACPI/AML/Field.cpp index 314d8cc7..d2b2d66a 100644 --- a/kernel/kernel/ACPI/AML/Field.cpp +++ b/kernel/kernel/ACPI/AML/Field.cpp @@ -492,13 +492,14 @@ namespace Kernel::ACPI return MUST(BAN::RefPtr::create(result.value())); } - bool AML::FieldElement::store(BAN::RefPtr source) + BAN::RefPtr AML::FieldElement::store(BAN::RefPtr source) { - auto source_integer = source->as_integer(); + ASSERT(source); + auto source_integer = source->convert(AML::Node::ConvInteger); if (!source_integer) { AML_TODO("FieldElement store with non-integer source, type {}", static_cast(source->type)); - return false; + return {}; } op_region->mutex.lock(); @@ -510,7 +511,9 @@ namespace Kernel::ACPI ACPI::release_global_lock(); }); - return store_internal(source_integer->value); + if (!store_internal(static_cast(source_integer.ptr())->value)) + return {}; + return source_integer; } void AML::FieldElement::debug_print(int indent) const @@ -626,28 +629,30 @@ namespace Kernel::ACPI return MUST(BAN::RefPtr::create(result.value())); } - bool AML::IndexFieldElement::store(BAN::RefPtr source) + BAN::RefPtr AML::IndexFieldElement::store(BAN::RefPtr source) { if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal) { AML_TODO("FieldElement with access attribute {}", static_cast(access_rules.access_attrib)); return {}; } - auto source_integer = source->as_integer(); + + ASSERT(source); + auto source_integer = source->convert(AML::Node::ConvInteger); if (!source_integer) { AML_TODO("IndexFieldElement store with non-integer source, type {}", static_cast(source->type)); - return false; + return {}; } auto access_size = determine_access_size(access_rules.access_type); if (!access_size.has_value()) - return false; + return {}; if (access_size.value() > data_element->bit_count) { AML_ERROR("IndexFieldElement write_field with access size {} > data element bit count {}", access_size.value(), data_element->bit_count); - return false; + return {}; } auto read_func = [&](uint64_t byte_offset) -> BAN::Optional { @@ -657,7 +662,7 @@ namespace Kernel::ACPI }; auto write_func = [&](uint64_t byte_offset, uint64_t value) -> bool { if (!index_element->store_internal(byte_offset)) - return false; + return {}; return data_element->store_internal(value); }; @@ -670,10 +675,10 @@ namespace Kernel::ACPI ACPI::release_global_lock(); }); - if (!perform_write_general(0, bit_count, bit_offset, access_size.value(), source_integer->value, access_rules.update_rule, read_func, write_func)) - return false; - - return true; + const auto source_value = static_cast(source_integer.ptr())->value; + if (!perform_write_general(0, bit_count, bit_offset, access_size.value(), source_value, access_rules.update_rule, read_func, write_func)) + return {}; + return source_integer; } void AML::IndexFieldElement::debug_print(int indent) const @@ -734,8 +739,8 @@ namespace Kernel::ACPI context.aml_data = temp_aml_data; if (!bank_value_result.success()) return ParseResult::Failure; - auto bank_value = bank_value_result.node() ? bank_value_result.node()->as_integer() : BAN::RefPtr(); - if (!bank_value) + auto bank_value_node = bank_value_result.node() ? bank_value_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!bank_value_node) { AML_ERROR("BankField BankValue is not an integer"); return ParseResult::Failure; @@ -756,11 +761,12 @@ namespace Kernel::ACPI if (!parse_field_element(field_context)) return ParseResult::Failure; + const auto bank_value = static_cast(bank_value_node.ptr())->value; for (auto& [_, element] : field_context.elements) { element->op_region = static_cast(op_region.ptr()); element->bank_selector = static_cast(bank_selector.ptr()); - element->bank_value = bank_value->value; + element->bank_value = bank_value; NameString element_name; MUST(element_name.path.push_back(element->name)); @@ -776,7 +782,7 @@ namespace Kernel::ACPI return ParseResult::Success; } - BAN::RefPtr AML::BankFieldElement::evaluate() + BAN::RefPtr AML::BankFieldElement::as_integer() { if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal) { @@ -812,7 +818,7 @@ namespace Kernel::ACPI return MUST(BAN::RefPtr::create(result.value())); } - bool AML::BankFieldElement::store(BAN::RefPtr source) + BAN::RefPtr AML::BankFieldElement::store(BAN::RefPtr source) { if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal) { @@ -820,16 +826,17 @@ namespace Kernel::ACPI return {}; } - auto source_integer = source->as_integer(); + ASSERT(source); + auto source_integer = source->convert(AML::Node::ConvInteger); if (!source_integer) { AML_TODO("BankFieldElement store with non-integer source, type {}", static_cast(source->type)); - return false; + return {}; } auto access_size = determine_access_size(access_rules.access_type); if (!access_size.has_value()) - return false; + return {}; auto read_func = [&](uint64_t byte_offset) -> BAN::Optional { return perform_read(op_region->region_space, byte_offset, access_size.value()); }; @@ -852,7 +859,10 @@ namespace Kernel::ACPI return {}; } - return perform_write_general(op_region->region_offset, bit_count, bit_offset, access_size.value(), source_integer->value, access_rules.update_rule, read_func, write_func); + const auto source_value = static_cast(source_integer.ptr())->value; + if (!perform_write_general(op_region->region_offset, bit_count, bit_offset, access_size.value(), source_value, access_rules.update_rule, read_func, write_func)) + return {}; + return source_integer; } void AML::BankFieldElement::debug_print(int indent) const diff --git a/kernel/kernel/ACPI/AML/NamedObject.cpp b/kernel/kernel/ACPI/AML/NamedObject.cpp index 44cf224c..ff132d1d 100644 --- a/kernel/kernel/ACPI/AML/NamedObject.cpp +++ b/kernel/kernel/ACPI/AML/NamedObject.cpp @@ -7,24 +7,6 @@ namespace Kernel::ACPI { - BAN::RefPtr AML::Name::as_buffer() - { - ASSERT(object); - return object->as_buffer(); - } - - BAN::RefPtr AML::Name::as_integer() - { - ASSERT(object); - return object->as_integer(); - } - - BAN::RefPtr AML::Name::as_string() - { - ASSERT(object); - return object->as_string(); - } - AML::ParseResult AML::Name::parse(ParseContext& context) { ASSERT(context.aml_data.size() >= 1); diff --git a/kernel/kernel/ACPI/AML/Namespace.cpp b/kernel/kernel/ACPI/AML/Namespace.cpp index 5f855df9..66bcfb4e 100644 --- a/kernel/kernel/ACPI/AML/Namespace.cpp +++ b/kernel/kernel/ACPI/AML/Namespace.cpp @@ -20,11 +20,12 @@ namespace Kernel::ACPI struct DebugNode : AML::Node { DebugNode() : AML::Node(AML::Node::Type::Debug) {} - bool store(BAN::RefPtr node) + BAN::RefPtr convert(uint8_t) override { return {}; } + BAN::RefPtr store(BAN::RefPtr node) { node->debug_print(0); AML_DEBUG_PRINTLN(""); - return true; + return node; } void debug_print(int indent) const override { @@ -236,7 +237,7 @@ namespace Kernel::ACPI auto osi = MUST(BAN::RefPtr::create(NameSeg("_OSI"_sv), 1, false, 0)); osi->override_function = [](AML::ParseContext& context) -> BAN::RefPtr { ASSERT(context.method_args[0]); - auto arg = context.method_args[0]->evaluate(); + auto arg = context.method_args[0]->convert(AML::Node::ConvString); if (!arg || arg->type != AML::Node::Type::String) { AML_ERROR("Invalid _OSI argument"); diff --git a/kernel/kernel/ACPI/AML/Node.cpp b/kernel/kernel/ACPI/AML/Node.cpp index c686ee33..739b31c9 100644 --- a/kernel/kernel/ACPI/AML/Node.cpp +++ b/kernel/kernel/ACPI/AML/Node.cpp @@ -36,24 +36,6 @@ namespace Kernel::ACPI uint64_t AML::Node::total_node_count = 0; - BAN::RefPtr AML::Node::as_buffer() - { - AML_TODO("Node type {} to buffer", static_cast(type)); - return {}; - } - - BAN::RefPtr AML::Node::as_integer() - { - AML_TODO("Node type {} to integer", static_cast(type)); - return {}; - } - - BAN::RefPtr AML::Node::as_string() - { - AML_TODO("Node type {} to string", static_cast(type)); - return {}; - } - AML::ParseResult AML::parse_object(AML::ParseContext& context) { if (context.aml_data.size() < 1) @@ -204,6 +186,7 @@ namespace Kernel::ACPI return AML::Notify::parse(context); case AML::Byte::SizeOfOp: return AML::SizeOf::parse(context); + case AML::Byte::BreakPointOp: // TODO: support breakpoints? case AML::Byte::NoopOp: context.aml_data = context.aml_data.slice(1); return ParseResult::Success; @@ -269,6 +252,9 @@ namespace Kernel::ACPI return ParseResult::Success; return ParseResult(result.value()); } + + if (aml_object->type == AML::Node::Type::Name) + return ParseResult(static_cast(aml_object.ptr())->object); return ParseResult(aml_object); } diff --git a/kernel/kernel/ACPI/AML/Register.cpp b/kernel/kernel/ACPI/AML/Register.cpp deleted file mode 100644 index 6ec5ad32..00000000 --- a/kernel/kernel/ACPI/AML/Register.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include - -namespace Kernel::ACPI::AML -{ - - BAN::RefPtr Register::as_buffer() - { - if (value) - return value->as_buffer(); - return {}; - } - - BAN::RefPtr Register::as_integer() - { - if (value) - return value->as_integer(); - return {}; - } - - BAN::RefPtr Register::as_string() - { - if (value) - return value->as_string(); - return {}; - } - -} diff --git a/kernel/kernel/ACPI/AML/Scope.cpp b/kernel/kernel/ACPI/AML/Scope.cpp index 483f72a9..0239ec6c 100644 --- a/kernel/kernel/ACPI/AML/Scope.cpp +++ b/kernel/kernel/ACPI/AML/Scope.cpp @@ -25,7 +25,7 @@ namespace Kernel::ACPI auto named_object = Namespace::root_namespace()->find_object(context.scope, name_string.value(), Namespace::FindMode::Normal); if (!named_object) { - AML_DEBUG_PRINT("Scope '{}' not found in namespace", name_string.value()); + AML_PRINT("Scope '{}' not found in namespace", name_string.value()); return ParseResult::Success; } if (!named_object->is_scope()) @@ -69,7 +69,12 @@ namespace Kernel::ACPI static BAN::RefPtr evaluate_or_invoke(BAN::RefPtr object) { if (object->type != AML::Node::Type::Method) - return object->as_integer(); + { + auto converted = object->convert(AML::Node::ConvInteger); + if (!converted) + return {}; + return static_cast(converted.ptr()); + } auto* method = static_cast(object.ptr()); if (method->arg_count != 0) @@ -85,7 +90,10 @@ namespace Kernel::ACPI return {}; } - return result.value() ? result.value()->as_integer() : BAN::RefPtr(); + auto result_integer = result.value() + ? result.value()->convert(AML::Node::ConvInteger) + : BAN::RefPtr(); + return static_cast(result_integer.ptr()); } bool AML::initialize_scope(BAN::RefPtr scope) diff --git a/kernel/kernel/ACPI/AML/String.cpp b/kernel/kernel/ACPI/AML/String.cpp index 93bca18f..9def9208 100644 --- a/kernel/kernel/ACPI/AML/String.cpp +++ b/kernel/kernel/ACPI/AML/String.cpp @@ -6,7 +6,7 @@ namespace Kernel::ACPI::AML BAN::Optional String::logical_compare(BAN::RefPtr node, AML::Byte binaryop) { - auto rhs = node ? node->as_string() : BAN::RefPtr(); + auto rhs = node ? node->convert(AML::Node::ConvString) : BAN::RefPtr(); if (!rhs) { AML_ERROR("String logical compare RHS is not string"); @@ -27,6 +27,20 @@ namespace Kernel::ACPI::AML return buffer; } + BAN::RefPtr String::convert(uint8_t mask) + { + if (mask & AML::Node::ConvString) + return this; + if (mask & AML::Node::ConvInteger) + { + AML_TODO("Convert String to Integer"); + return {}; + } + if (mask & AML::Node::ConvBuffer) + return as_buffer(); + return {}; + } + ParseResult String::parse(ParseContext& context) { ASSERT(context.aml_data.size() >= 1);