From ec4cfdee23238cb6cdbc4eb5dee3394f45b9eac6 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 13 Aug 2024 22:14:14 +0300 Subject: [PATCH] Kernel: Fix and cleanup a lot of AML code Node now have APIs to convert them to buffer, integer and string. This allows possibility to handle methods that need explicitly use one of the overloads instead of integer. This patch also adds handling of DebugOp. This is used quite heavily in uACPIs test suite. --- kernel/CMakeLists.txt | 2 + kernel/include/kernel/ACPI/AML/Buffer.h | 67 ++++++++++++++++---- kernel/include/kernel/ACPI/AML/Expression.h | 62 +++++++++--------- kernel/include/kernel/ACPI/AML/Field.h | 8 ++- kernel/include/kernel/ACPI/AML/IfElse.h | 6 +- kernel/include/kernel/ACPI/AML/Index.h | 18 +++--- kernel/include/kernel/ACPI/AML/Integer.h | 27 +++++++- kernel/include/kernel/ACPI/AML/Method.h | 5 +- kernel/include/kernel/ACPI/AML/NamedObject.h | 4 ++ kernel/include/kernel/ACPI/AML/Namespace.h | 1 + kernel/include/kernel/ACPI/AML/Node.h | 11 +++- kernel/include/kernel/ACPI/AML/Notify.h | 6 +- kernel/include/kernel/ACPI/AML/Package.h | 57 +++++++++++++---- kernel/include/kernel/ACPI/AML/Reference.h | 19 +++++- kernel/include/kernel/ACPI/AML/Region.h | 9 +-- kernel/include/kernel/ACPI/AML/Register.h | 7 ++ kernel/include/kernel/ACPI/AML/Sleep.h | 8 +-- kernel/include/kernel/ACPI/AML/Store.h | 2 +- kernel/include/kernel/ACPI/AML/String.h | 32 ++-------- kernel/include/kernel/ACPI/AML/ThermalZone.h | 2 +- kernel/include/kernel/ACPI/AML/While.h | 6 +- kernel/kernel/ACPI/ACPI.cpp | 10 +-- kernel/kernel/ACPI/AML/Field.cpp | 22 +++---- kernel/kernel/ACPI/AML/NamedObject.cpp | 23 ++++++- kernel/kernel/ACPI/AML/Namespace.cpp | 23 ++++++- kernel/kernel/ACPI/AML/Node.cpp | 25 +++++--- kernel/kernel/ACPI/AML/Register.cpp | 30 +++++++++ kernel/kernel/ACPI/AML/Scope.cpp | 14 ++-- kernel/kernel/ACPI/AML/String.cpp | 58 +++++++++++++++++ 29 files changed, 415 insertions(+), 149 deletions(-) create mode 100644 kernel/kernel/ACPI/AML/Register.cpp create mode 100644 kernel/kernel/ACPI/AML/String.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 3e10f980d3..cc86017b13 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -7,7 +7,9 @@ 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 kernel/BootInfo.cpp kernel/CPUID.cpp diff --git a/kernel/include/kernel/ACPI/AML/Buffer.h b/kernel/include/kernel/ACPI/AML/Buffer.h index 253dbc4f92..8b428d623e 100644 --- a/kernel/include/kernel/ACPI/AML/Buffer.h +++ b/kernel/include/kernel/ACPI/AML/Buffer.h @@ -18,6 +18,30 @@ namespace Kernel::ACPI::AML : AML::Node(Node::Type::Buffer) {} + BAN::Optional logical_compare(BAN::RefPtr node, AML::Byte binaryop) + { + auto rhs = node ? node->as_buffer() : BAN::RefPtr(); + if (!rhs) + { + AML_ERROR("Buffer logical compare RHS is not buffer"); + return {}; + } + + (void)binaryop; + AML_TODO("Logical compare buffer"); + return {}; + } + + BAN::RefPtr as_buffer() override { return this; } + + BAN::RefPtr as_integer() override + { + uint64_t value = 0; + for (size_t i = 0; i < BAN::Math::min(buffer.size(), 8); i++) + value |= buffer[i] << (8 * i); + return MUST(BAN::RefPtr::create(value)); + } + BAN::RefPtr evaluate() override { return this; @@ -41,10 +65,10 @@ namespace Kernel::ACPI::AML return ParseResult::Failure; auto buffer_size = buffer_size_object.node()->as_integer(); - if (!buffer_size.has_value()) + if (!buffer_size) return ParseResult::Failure; - uint32_t actual_buffer_size = BAN::Math::max(buffer_size.value(), buffer_context.aml_data.size()); + uint32_t actual_buffer_size = BAN::Math::max(buffer_size->value, buffer_context.aml_data.size()); auto buffer = MUST(BAN::RefPtr::create()); MUST(buffer->buffer.resize(actual_buffer_size, 0)); @@ -80,6 +104,27 @@ namespace Kernel::ACPI::AML , field_bit_size(field_bit_size) {} + BAN::RefPtr as_integer() 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++) + { + const size_t bit = field_bit_offset + i; + value |= ((buffer[bit / 8] >> (bit % 8)) & 1) << i; + } + + return MUST(BAN::RefPtr::create(value)); + } + BAN::RefPtr evaluate() override { ASSERT(buffer); @@ -111,7 +156,7 @@ namespace Kernel::ACPI::AML ASSERT(field_bit_offset + field_bit_size <= buffer.size() * 8); auto value = node->as_integer(); - if (!value.has_value()) + if (!value) return false; // TODO: optimize for whole byte accesses @@ -119,7 +164,7 @@ namespace Kernel::ACPI::AML { 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->value >> i) & 1) << (bit % 8); } return true; @@ -159,7 +204,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()->evaluate() : nullptr; + auto buffer_node = buffer_result.node() ? buffer_result.node()->as_buffer() : BAN::RefPtr(); if (!buffer_node || buffer_node->type != Node::Type::Buffer) { AML_ERROR("Buffer source does not evaluate to a Buffer"); @@ -170,13 +215,13 @@ 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::Optional(); - if (!index.has_value()) + auto index = index_result.node() ? index_result.node()->as_integer() : BAN::RefPtr(); + if (!index) { AML_ERROR("Failed to parse index for BufferField"); return ParseResult::Failure; } - size_t field_bit_offset = index.value(); + size_t field_bit_offset = index->value; if (field_bit_size != 1) field_bit_offset *= 8; @@ -185,13 +230,13 @@ namespace Kernel::ACPI::AML auto bit_count_result = AML::parse_object(context); if (!index_result.success()) return ParseResult::Failure; - auto bit_count = bit_count_result.node() ? bit_count_result.node()->as_integer() : BAN::Optional(); - if (!bit_count.has_value()) + auto bit_count = bit_count_result.node() ? bit_count_result.node()->as_integer() : BAN::RefPtr(); + if (!bit_count) { AML_ERROR("Failed to parse bit count for BufferField"); return ParseResult::Failure; } - field_bit_size = bit_count.value(); + field_bit_size = bit_count->value; } auto field_name = AML::NameString::parse(context.aml_data); diff --git a/kernel/include/kernel/ACPI/AML/Expression.h b/kernel/include/kernel/ACPI/AML/Expression.h index e9d99122bc..80f3dc0448 100644 --- a/kernel/include/kernel/ACPI/AML/Expression.h +++ b/kernel/include/kernel/ACPI/AML/Expression.h @@ -25,22 +25,21 @@ 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()->evaluate() : BAN::RefPtr(); - if (!source_node || source_node->type != AML::Node::Type::Integer) + auto source_node = source_result.node() ? source_result.node()->as_integer(): BAN::RefPtr(); + if (!source_node) { AML_ERROR("UnaryOp source not integer"); return ParseResult::Failure; } - auto source_integer = static_cast(source_node.ptr()); - if (source_integer->constant) + if (source_node->constant) { AML_ERROR("UnaryOp source is constant"); return ParseResult::Failure; } - source_integer->value += (opcode == AML::Byte::AddOp) ? 1 : -1; - return ParseResult(source_integer); + source_node->value += (opcode == AML::Byte::AddOp) ? 1 : -1; + return ParseResult(source_node); } case AML::Byte::NotOp: AML_TODO("NotOp", context.aml_data[0]); @@ -53,14 +52,14 @@ namespace Kernel::ACPI::AML if (!node_result.success()) return ParseResult::Failure; - auto value = node_result.node() ? node_result.node()->as_integer() : BAN::Optional(); - if (!value.has_value()) + auto value = node_result.node() ? node_result.node()->as_integer() : BAN::RefPtr(); + if (!value) { AML_ERROR("Logical NotOp source is not integer"); return ParseResult::Failure; } - auto result = value.value() ? Integer::Constants::Zero : Integer::Constants::Ones; + auto result = value->value ? Integer::Constants::Zero : Integer::Constants::Ones; return ParseResult(result); } case AML::Byte::AddOp: @@ -98,8 +97,8 @@ 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::Optional(); - if (!lhs_value.has_value()) + auto lhs_value = lhs_result.node() ? lhs_result.node()->as_integer() : BAN::RefPtr(); + if (!lhs_value) { AML_ERROR("BinaryOP {2H} LHS not an integer", static_cast(opcode)); if (lhs_result.node()) @@ -111,8 +110,8 @@ namespace Kernel::ACPI::AML auto rhs_result = AML::parse_object(context); if (!rhs_result.success()) return ParseResult::Failure; - auto rhs_value = lhs_result.node() ? rhs_result.node()->as_integer() : BAN::Optional(); - if (!rhs_value.has_value()) + auto rhs_value = rhs_result.node() ? rhs_result.node()->as_integer() : BAN::RefPtr(); + if (!rhs_value) { AML_ERROR("BinaryOP {2H} RHS not an integer", static_cast(opcode)); if (rhs_result.node()) @@ -160,7 +159,7 @@ namespace Kernel::ACPI::AML ASSERT_NOT_REACHED(); } - uint64_t result = func(lhs_value.value(), rhs_value.value()); + uint64_t result = func(lhs_value->value, rhs_value->value); auto result_node = MUST(BAN::RefPtr::create(result)); if (target_node && !target_node->store(result_node)) @@ -180,36 +179,37 @@ 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::Optional(); - if (!lhs_value.has_value()) + auto lhs_node = lhs_result.node() ? lhs_result.node()->evaluate() : BAN::RefPtr(); + if (!lhs_node) { - AML_TODO("Logical BinaryOP {2H} LHS not integer", static_cast(opcode)); + AML_TODO("Logical BinaryOP {2H} LHS evaluated to nothing", static_cast(opcode)); return ParseResult::Failure; } 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::Optional(); - if (!rhs_value.has_value()) - { - AML_TODO("Logical BinaryOP {2H} RHS not integer", static_cast(opcode)); - return ParseResult::Failure; - } - BAN::RefPtr (*func)(uint64_t, uint64_t) = nullptr; - switch (opcode) + BAN::Optional result = false; + switch (lhs_node->type) { - case AML::Byte::LAndOp: func = [](uint64_t a, uint64_t b) { return a && b ? Integer::Constants::Ones : Integer::Constants::Zero; }; break; - case AML::Byte::LEqualOp: func = [](uint64_t a, uint64_t b) { return a == b ? Integer::Constants::Ones : Integer::Constants::Zero; }; break; - case AML::Byte::LGreaterOp: func = [](uint64_t a, uint64_t b) { return a > b ? Integer::Constants::Ones : Integer::Constants::Zero; }; break; - case AML::Byte::LLessOp: func = [](uint64_t a, uint64_t b) { return a < b ? Integer::Constants::Ones : Integer::Constants::Zero; }; break; - case AML::Byte::LOrOp: func = [](uint64_t a, uint64_t b) { return a || b ? Integer::Constants::Ones : Integer::Constants::Zero; }; break; + case AML::Node::Type::Integer: + result = static_cast(lhs_node.ptr())->logical_compare(rhs_result.node(), opcode); + break; + case AML::Node::Type::Buffer: + result = static_cast(lhs_node.ptr())->logical_compare(rhs_result.node(), opcode); + break; + case AML::Node::Type::String: + result = static_cast(lhs_node.ptr())->logical_compare(rhs_result.node(), opcode); + break; default: ASSERT_NOT_REACHED(); } - return ParseResult(func(lhs_value.value(), rhs_value.value())); + if (!result.has_value()) + return ParseResult::Failure; + + return ParseResult(result.value() ? AML::Integer::Constants::Ones : AML::Integer::Constants::Zero); } }; diff --git a/kernel/include/kernel/ACPI/AML/Field.h b/kernel/include/kernel/ACPI/AML/Field.h index c645a00fb3..b3b57b20ef 100644 --- a/kernel/include/kernel/ACPI/AML/Field.h +++ b/kernel/include/kernel/ACPI/AML/Field.h @@ -63,7 +63,9 @@ namespace Kernel::ACPI::AML , access_rules(access_rules) {} - BAN::RefPtr evaluate() override; + BAN::RefPtr as_integer() override; + + BAN::RefPtr evaluate() override { return as_integer(); } bool store(BAN::RefPtr source) override; void debug_print(int indent) const override; @@ -98,7 +100,9 @@ namespace Kernel::ACPI::AML , access_rules(access_rules) {} - BAN::RefPtr evaluate() override; + BAN::RefPtr as_integer() override; + + BAN::RefPtr evaluate() override { return as_integer(); } bool store(BAN::RefPtr source) override; void debug_print(int indent) const override; diff --git a/kernel/include/kernel/ACPI/AML/IfElse.h b/kernel/include/kernel/ACPI/AML/IfElse.h index dbde91e87f..bded25d03b 100644 --- a/kernel/include/kernel/ACPI/AML/IfElse.h +++ b/kernel/include/kernel/ACPI/AML/IfElse.h @@ -26,8 +26,8 @@ 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::Optional(); - if (!predicate.has_value()) + auto predicate = predicate_result.node() ? predicate_result.node()->as_integer() : BAN::RefPtr(); + if (!predicate) { AML_ERROR("If predicate is not an integer"); return ParseResult::Failure; @@ -43,7 +43,7 @@ namespace Kernel::ACPI::AML return ParseResult::Failure; else_pkg = else_pkg_result.value(); } - if (!predicate.value()) + 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 2212a692c9..2549a482d7 100644 --- a/kernel/include/kernel/ACPI/AML/Index.h +++ b/kernel/include/kernel/ACPI/AML/Index.h @@ -30,8 +30,8 @@ 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::Optional(); - if (!index.has_value()) + auto index = index_result.node() ? index_result.node()->as_integer() : BAN::RefPtr(); + if (!index) { AML_ERROR("IndexOp index is not an integer"); return ParseResult::Failure; @@ -43,36 +43,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->value >= 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->value * 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->value >= 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->value]; 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->value >= 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->value * 8, 8)); result = MUST(BAN::RefPtr::create(buffer_field)); break; } @@ -82,7 +82,7 @@ namespace Kernel::ACPI::AML } #if AML_DEBUG_LEVEL >= 2 - AML_DEBUG_PRINT("Index {}, ", index.value()); + AML_DEBUG_PRINT("Index {}, ", index->value); 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 280e17d3e6..c9457724b1 100644 --- a/kernel/include/kernel/ACPI/AML/Integer.h +++ b/kernel/include/kernel/ACPI/AML/Integer.h @@ -30,6 +30,29 @@ namespace Kernel::ACPI::AML , constant(constant) {} + BAN::Optional logical_compare(BAN::RefPtr node, AML::Byte binaryop) + { + auto rhs = node ? node->as_integer() : BAN::RefPtr(); + if (!rhs) + { + AML_ERROR("Integer logical compare RHS is not integer"); + return {}; + } + + 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; + default: + ASSERT_NOT_REACHED(); + } + } + + BAN::RefPtr as_integer() override { return this; } + BAN::RefPtr copy() override { return MUST(BAN::RefPtr::create(value)); } BAN::RefPtr evaluate() override @@ -45,12 +68,12 @@ namespace Kernel::ACPI::AML return false; } auto store_value = store_node->as_integer(); - if (!store_value.has_value()) + if (!store_value) { AML_ERROR("Cannot store non-integer to integer"); return false; } - value = store_value.value(); + value = store_value->value; return true; } diff --git a/kernel/include/kernel/ACPI/AML/Method.h b/kernel/include/kernel/ACPI/AML/Method.h index 258ab9c204..84b0699391 100644 --- a/kernel/include/kernel/ACPI/AML/Method.h +++ b/kernel/include/kernel/ACPI/AML/Method.h @@ -53,7 +53,7 @@ namespace Kernel::ACPI::AML method_flags >> 4 )); if (!Namespace::root_namespace()->add_named_object(context, name_string.value(), method)) - return ParseResult::Failure; + return ParseResult::Success; method->term_list = method_pkg.value(); #if AML_DEBUG_LEVEL >= 2 @@ -142,6 +142,9 @@ namespace Kernel::ACPI::AML } } + if (return_value.has_value() && return_value.value()) + return_value = return_value.value()->evaluate(); + while (!context.created_objects.empty()) { Namespace::root_namespace()->remove_named_object(context.created_objects.back()); diff --git a/kernel/include/kernel/ACPI/AML/NamedObject.h b/kernel/include/kernel/ACPI/AML/NamedObject.h index cc943f7201..28c2abe2ec 100644 --- a/kernel/include/kernel/ACPI/AML/NamedObject.h +++ b/kernel/include/kernel/ACPI/AML/NamedObject.h @@ -22,6 +22,10 @@ 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 evaluate() override { ASSERT(object); diff --git a/kernel/include/kernel/ACPI/AML/Namespace.h b/kernel/include/kernel/ACPI/AML/Namespace.h index 7809795cab..bd937bb017 100644 --- a/kernel/include/kernel/ACPI/AML/Namespace.h +++ b/kernel/include/kernel/ACPI/AML/Namespace.h @@ -11,6 +11,7 @@ namespace Kernel::ACPI::AML struct Namespace : public AML::Scope { static BAN::RefPtr root_namespace(); + static BAN::RefPtr debug_node; template static void for_each_child(const AML::NameString& scope, const F& callback) diff --git a/kernel/include/kernel/ACPI/AML/Node.h b/kernel/include/kernel/ACPI/AML/Node.h index 8f0b379594..2e82f6eda0 100644 --- a/kernel/include/kernel/ACPI/AML/Node.h +++ b/kernel/include/kernel/ACPI/AML/Node.h @@ -9,12 +9,17 @@ namespace Kernel::ACPI::AML { + struct Buffer; + struct Integer; + struct String; + struct Node : public BAN::RefCounted { static uint64_t total_node_count; enum class Type { + Debug, BankFieldElement, Buffer, BufferField, @@ -45,7 +50,10 @@ namespace Kernel::ACPI::AML virtual BAN::RefPtr copy() { return this; } - [[nodiscard]] BAN::Optional as_integer(); + [[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; } @@ -84,7 +92,6 @@ namespace Kernel::ACPI::AML BAN::RefPtr node() { - ASSERT(m_node); return m_node; } diff --git a/kernel/include/kernel/ACPI/AML/Notify.h b/kernel/include/kernel/ACPI/AML/Notify.h index 1a0c3a6525..e5871f652a 100644 --- a/kernel/include/kernel/ACPI/AML/Notify.h +++ b/kernel/include/kernel/ACPI/AML/Notify.h @@ -29,8 +29,8 @@ 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::Optional(); - if (!value.has_value()) + auto value = value_result.node() ? value_result.node()->as_integer() : BAN::RefPtr(); + if (!value) { AML_ERROR("Notify value is not an integer"); return ParseResult::Failure; @@ -58,7 +58,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->value); return ParseResult::Success; } }; diff --git a/kernel/include/kernel/ACPI/AML/Package.h b/kernel/include/kernel/ACPI/AML/Package.h index fa2d591bee..270dd81af3 100644 --- a/kernel/include/kernel/ACPI/AML/Package.h +++ b/kernel/include/kernel/ACPI/AML/Package.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -65,6 +66,49 @@ namespace Kernel::ACPI::AML initialized = false; } + bool resolve() + { + ASSERT(!resolved); + + auto object = Namespace::root_namespace()->find_object(parent->scope, unresolved_name, Namespace::FindMode::Normal); + if (!object) + { + AML_ERROR("Failed to resolve reference {} in package {}", unresolved_name, parent->scope); + return false; + } + element = object; + resolved = true; + + return true; + } + + bool store(BAN::RefPtr node) override + { + if (!initialized) + { + AML_ERROR("Trying to store into uninitialized PackageElement"); + return {}; + } + if (!resolved && !resolve()) + return {}; + 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) @@ -72,17 +116,8 @@ namespace Kernel::ACPI::AML AML_ERROR("Trying to evaluate uninitialized PackageElement"); return {}; } - if (!resolved) - { - auto object = Namespace::root_namespace()->find_object(parent->scope, unresolved_name, Namespace::FindMode::Normal); - if (!object) - { - AML_ERROR("Failed to resolve reference {} in package {}", unresolved_name, parent->scope); - return {}; - } - element = object; - resolved = true; - } + if (!resolved && !resolve()) + return {}; return element->evaluate(); } diff --git a/kernel/include/kernel/ACPI/AML/Reference.h b/kernel/include/kernel/ACPI/AML/Reference.h index 38f34c6b6a..74aaec03b5 100644 --- a/kernel/include/kernel/ACPI/AML/Reference.h +++ b/kernel/include/kernel/ACPI/AML/Reference.h @@ -21,11 +21,28 @@ 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 + { + if (!node) + { + AML_ERROR("Storing to null reference"); + return false; + } + return node->store(value); + } + static ParseResult parse(ParseContext& context) { ASSERT(context.aml_data.size() >= 1); @@ -127,7 +144,7 @@ namespace Kernel::ACPI::AML auto parse_result = AML::parse_object(context); if (!parse_result.success()) return ParseResult::Failure; - auto object = parse_result.node(); + auto object = parse_result.node() ? parse_result.node()->evaluate() : BAN::RefPtr(); if (!object || object->type != AML::Node::Type::Reference) { AML_TODO("DerefOf source is not a Reference, but a {}", object ? static_cast(object->type) : 999); diff --git a/kernel/include/kernel/ACPI/AML/Region.h b/kernel/include/kernel/ACPI/AML/Region.h index 1d19d07a23..805734476f 100644 --- a/kernel/include/kernel/ACPI/AML/Region.h +++ b/kernel/include/kernel/ACPI/AML/Region.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -43,7 +44,7 @@ namespace Kernel::ACPI::AML if (!offset_result.success()) return ParseResult::Failure; auto offset = offset_result.node()->as_integer(); - if (!offset.has_value()) + if (!offset) { AML_ERROR("OpRegion offset must be an integer"); return ParseResult::Failure; @@ -53,7 +54,7 @@ namespace Kernel::ACPI::AML if (!length_result.success()) return ParseResult::Failure; auto length = length_result.node()->as_integer(); - if (!length.has_value()) + if (!length) { AML_ERROR("OpRegion length must be an integer"); return ParseResult::Failure; @@ -62,8 +63,8 @@ namespace Kernel::ACPI::AML auto op_region = MUST(BAN::RefPtr::create( name->path.back(), region_space, - offset.value(), - length.value() + offset->value, + length->value )); 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 589eccb63b..8ca942e814 100644 --- a/kernel/include/kernel/ACPI/AML/Register.h +++ b/kernel/include/kernel/ACPI/AML/Register.h @@ -17,6 +17,10 @@ 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 { if (value) @@ -26,6 +30,9 @@ namespace Kernel::ACPI::AML bool store(BAN::RefPtr source) override { + if (value && value->type == AML::Node::Type::Reference) + return value->store(source); + auto evaluated = source->evaluate(); if (!evaluated) { diff --git a/kernel/include/kernel/ACPI/AML/Sleep.h b/kernel/include/kernel/ACPI/AML/Sleep.h index fe23293d95..2bdeac10e5 100644 --- a/kernel/include/kernel/ACPI/AML/Sleep.h +++ b/kernel/include/kernel/ACPI/AML/Sleep.h @@ -19,18 +19,18 @@ 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::Optional(); - if (!sleep_time.has_value()) + auto sleep_time = sleep_time_result.node() ? sleep_time_result.node()->as_integer() : BAN::RefPtr(); + if (!sleep_time) { AML_ERROR("Sleep time cannot be evaluated to an integer"); return ParseResult::Failure; } #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 59a6d45b73..ab8df72662 100644 --- a/kernel/include/kernel/ACPI/AML/Store.h +++ b/kernel/include/kernel/ACPI/AML/Store.h @@ -46,7 +46,7 @@ namespace Kernel::ACPI::AML if (!destination->store(source)) return ParseResult::Failure; - return ParseResult::Success; + return ParseResult(destination); } }; diff --git a/kernel/include/kernel/ACPI/AML/String.h b/kernel/include/kernel/ACPI/AML/String.h index 5ca48c88b0..2d0806b0f1 100644 --- a/kernel/include/kernel/ACPI/AML/String.h +++ b/kernel/include/kernel/ACPI/AML/String.h @@ -20,6 +20,10 @@ namespace Kernel::ACPI::AML this->string[i] = string[i]; } + BAN::Optional logical_compare(BAN::RefPtr node, AML::Byte binaryop); + + BAN::RefPtr as_buffer() override; + BAN::RefPtr evaluate() override { return this; @@ -30,33 +34,7 @@ namespace Kernel::ACPI::AML return BAN::StringView(reinterpret_cast(string.data()), string.size()); } - static ParseResult parse(ParseContext& context) - { - ASSERT(context.aml_data.size() >= 1); - ASSERT(static_cast(context.aml_data[0]) == AML::Byte::StringPrefix); - context.aml_data = context.aml_data.slice(1); - - BAN::Vector string; - - while (context.aml_data.size() > 0) - { - if (context.aml_data[0] == 0x00) - break; - MUST(string.push_back(context.aml_data[0])); - context.aml_data = context.aml_data.slice(1); - } - - if (context.aml_data.size() == 0) - return ParseResult::Failure; - if (context.aml_data[0] != 0x00) - return ParseResult::Failure; - context.aml_data = context.aml_data.slice(1); - - auto string_node = MUST(BAN::RefPtr::create()); - string_node->string = BAN::move(string); - - return ParseResult(string_node); - } + static ParseResult parse(ParseContext& context); virtual void debug_print(int indent) const override { diff --git a/kernel/include/kernel/ACPI/AML/ThermalZone.h b/kernel/include/kernel/ACPI/AML/ThermalZone.h index 44f0def85d..69e379eb9a 100644 --- a/kernel/include/kernel/ACPI/AML/ThermalZone.h +++ b/kernel/include/kernel/ACPI/AML/ThermalZone.h @@ -19,7 +19,7 @@ namespace Kernel::ACPI::AML { ASSERT(context.aml_data.size() >= 2); ASSERT(static_cast(context.aml_data[0]) == AML::Byte::ExtOpPrefix); - ASSERT(static_cast(context.aml_data[1]) == AML::ExtOp::PowerResOp); + ASSERT(static_cast(context.aml_data[1]) == AML::ExtOp::ThermalZoneOp); context.aml_data = context.aml_data.slice(2); auto opt_thermal_zone_pkg = AML::parse_pkg(context.aml_data); diff --git a/kernel/include/kernel/ACPI/AML/While.h b/kernel/include/kernel/ACPI/AML/While.h index 19c0bf3b49..02fc4f36ba 100644 --- a/kernel/include/kernel/ACPI/AML/While.h +++ b/kernel/include/kernel/ACPI/AML/While.h @@ -29,14 +29,14 @@ 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::Optional(); - if (!predicate.has_value()) + auto predicate = predicate_result.node() ? predicate_result.node()->as_integer() : BAN::RefPtr(); + if (!predicate) { AML_ERROR("While predicate is not an integer"); return ParseResult::Failure; } - if (!predicate.value()) + if (!predicate->value) break; while (context.aml_data.size() > 0) diff --git a/kernel/kernel/ACPI/ACPI.cpp b/kernel/kernel/ACPI/ACPI.cpp index 716f8c9e97..720c156a7f 100644 --- a/kernel/kernel/ACPI/ACPI.cpp +++ b/kernel/kernel/ACPI/ACPI.cpp @@ -145,9 +145,9 @@ acpi_release_global_lock: field_element->op_region = op_region; auto result = field_element->as_integer(); - if (!result.has_value()) + if (!result) return {}; - return result.value(); + return result->value; } bool GAS::write(uint64_t value) @@ -514,7 +514,7 @@ acpi_release_global_lock: auto slp_typa = s5_package->elements[0]->as_integer(); auto slp_typb = s5_package->elements[1]->as_integer(); - if (!slp_typa.has_value() || !slp_typb.has_value()) + if (!slp_typa || !slp_typb) { dwarnln("Failed to get SLP_TYPx values"); return; @@ -527,7 +527,7 @@ acpi_release_global_lock: 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 +535,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 b416555aee..314d8cc721 100644 --- a/kernel/kernel/ACPI/AML/Field.cpp +++ b/kernel/kernel/ACPI/AML/Field.cpp @@ -479,7 +479,7 @@ namespace Kernel::ACPI return perform_write_general(op_region->region_offset, bit_count, bit_offset, access_size.value(), value, access_rules.update_rule, read_func, write_func); } - BAN::RefPtr AML::FieldElement::evaluate() + BAN::RefPtr AML::FieldElement::as_integer() { op_region->mutex.lock(); BAN::ScopeGuard unlock_guard([&] { @@ -495,7 +495,7 @@ namespace Kernel::ACPI bool AML::FieldElement::store(BAN::RefPtr source) { auto source_integer = source->as_integer(); - if (!source_integer.has_value()) + if (!source_integer) { AML_TODO("FieldElement store with non-integer source, type {}", static_cast(source->type)); return false; @@ -510,7 +510,7 @@ namespace Kernel::ACPI ACPI::release_global_lock(); }); - return store_internal(source_integer.value()); + return store_internal(source_integer->value); } void AML::FieldElement::debug_print(int indent) const @@ -590,7 +590,7 @@ namespace Kernel::ACPI return AML::ParseResult::Success; } - BAN::RefPtr AML::IndexFieldElement::evaluate() + BAN::RefPtr AML::IndexFieldElement::as_integer() { if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal) { @@ -634,7 +634,7 @@ namespace Kernel::ACPI return {}; } auto source_integer = source->as_integer(); - if (!source_integer.has_value()) + if (!source_integer) { AML_TODO("IndexFieldElement store with non-integer source, type {}", static_cast(source->type)); return false; @@ -670,7 +670,7 @@ 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)) + 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; @@ -734,8 +734,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::Optional(); - if (!bank_value.has_value()) + auto bank_value = bank_value_result.node() ? bank_value_result.node()->as_integer() : BAN::RefPtr(); + if (!bank_value) { AML_ERROR("BankField BankValue is not an integer"); return ParseResult::Failure; @@ -760,7 +760,7 @@ namespace Kernel::ACPI { 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->value; NameString element_name; MUST(element_name.path.push_back(element->name)); @@ -821,7 +821,7 @@ namespace Kernel::ACPI } auto source_integer = source->as_integer(); - if (!source_integer.has_value()) + if (!source_integer) { AML_TODO("BankFieldElement store with non-integer source, type {}", static_cast(source->type)); return false; @@ -852,7 +852,7 @@ 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); + 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); } 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 ef8ad39e86..44cf224c7f 100644 --- a/kernel/kernel/ACPI/AML/NamedObject.cpp +++ b/kernel/kernel/ACPI/AML/NamedObject.cpp @@ -1,9 +1,30 @@ +#include +#include #include #include +#include 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); @@ -20,7 +41,7 @@ namespace Kernel::ACPI auto name = MUST(BAN::RefPtr::create(name_string.value().path.back(), object.node())); if (!Namespace::root_namespace()->add_named_object(context, name_string.value(), name)) - return ParseResult::Failure; + return ParseResult::Success; #if AML_DEBUG_LEVEL >= 2 name->debug_print(0); diff --git a/kernel/kernel/ACPI/AML/Namespace.cpp b/kernel/kernel/ACPI/AML/Namespace.cpp index bed77d510d..5f855df9a5 100644 --- a/kernel/kernel/ACPI/AML/Namespace.cpp +++ b/kernel/kernel/ACPI/AML/Namespace.cpp @@ -17,6 +17,24 @@ namespace Kernel::ACPI BAN::RefPtr AML::Integer::Constants::One; BAN::RefPtr AML::Integer::Constants::Ones; + struct DebugNode : AML::Node + { + DebugNode() : AML::Node(AML::Node::Type::Debug) {} + bool store(BAN::RefPtr node) + { + node->debug_print(0); + AML_DEBUG_PRINTLN(""); + return true; + } + void debug_print(int indent) const override + { + AML_DEBUG_PRINT_INDENT(indent); + AML_DEBUG_PRINT("DEBUG"); + } + }; + + BAN::RefPtr AML::Namespace::debug_node; + BAN::RefPtr AML::Namespace::root_namespace() { ASSERT(s_root_namespace); @@ -147,7 +165,7 @@ namespace Kernel::ACPI if (m_objects.contains(canonical_path.value())) { - AML_ERROR("Object '{}' already exists", canonical_path.value()); + AML_PRINT("Object '{}' already exists", canonical_path.value()); return false; } @@ -194,6 +212,9 @@ namespace Kernel::ACPI s_root_namespace = MUST(BAN::RefPtr::create(NameSeg("\\"_sv))); s_root_namespace->scope = AML::NameString("\\"_sv); + ASSERT(!Namespace::debug_node); + Namespace::debug_node = MUST(BAN::RefPtr::create()); + Integer::Constants::Zero = MUST(BAN::RefPtr::create(0, true)); Integer::Constants::One = MUST(BAN::RefPtr::create(1, true)); Integer::Constants::Ones = MUST(BAN::RefPtr::create(0xFFFFFFFFFFFFFFFF, true)); diff --git a/kernel/kernel/ACPI/AML/Node.cpp b/kernel/kernel/ACPI/AML/Node.cpp index 610cbe3dbe..288dd764f5 100644 --- a/kernel/kernel/ACPI/AML/Node.cpp +++ b/kernel/kernel/ACPI/AML/Node.cpp @@ -33,15 +33,21 @@ namespace Kernel::ACPI uint64_t AML::Node::total_node_count = 0; - BAN::Optional AML::Node::as_integer() + BAN::RefPtr AML::Node::as_buffer() { - if (type == Type::Integer) - return static_cast(this)->value; - auto evaluated = evaluate(); - if (!evaluated) - return {}; - if (evaluated->type == Type::Integer) - return static_cast(evaluated.ptr())->value; + 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 {}; } @@ -83,6 +89,9 @@ namespace Kernel::ACPI 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; } diff --git a/kernel/kernel/ACPI/AML/Register.cpp b/kernel/kernel/ACPI/AML/Register.cpp new file mode 100644 index 0000000000..6ec5ad327e --- /dev/null +++ b/kernel/kernel/ACPI/AML/Register.cpp @@ -0,0 +1,30 @@ +#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 ef1725c666..483f72a978 100644 --- a/kernel/kernel/ACPI/AML/Scope.cpp +++ b/kernel/kernel/ACPI/AML/Scope.cpp @@ -25,8 +25,8 @@ namespace Kernel::ACPI auto named_object = Namespace::root_namespace()->find_object(context.scope, name_string.value(), Namespace::FindMode::Normal); if (!named_object) { - AML_ERROR("Scope '{}' not found in namespace", name_string.value()); - return ParseResult::Failure; + AML_DEBUG_PRINT("Scope '{}' not found in namespace", name_string.value()); + return ParseResult::Success; } if (!named_object->is_scope()) { @@ -66,7 +66,7 @@ namespace Kernel::ACPI return ParseResult::Success; } - static BAN::Optional evaluate_or_invoke(BAN::RefPtr object) + static BAN::RefPtr evaluate_or_invoke(BAN::RefPtr object) { if (object->type != AML::Node::Type::Method) return object->as_integer(); @@ -85,7 +85,7 @@ namespace Kernel::ACPI return {}; } - return result.value() ? result.value()->as_integer() : BAN::Optional(); + return result.value() ? result.value()->as_integer() : BAN::RefPtr(); } bool AML::initialize_scope(BAN::RefPtr scope) @@ -138,14 +138,14 @@ namespace Kernel::ACPI if (auto sta = Namespace::root_namespace()->find_object(scope->scope, AML::NameString("_STA"_sv), Namespace::FindMode::ForceAbsolute)) { auto result = evaluate_or_invoke(sta); - if (!result.has_value()) + if (!result) { AML_ERROR("Failed to evaluate {}._STA, return value could not be resolved to integer", scope->scope); return false; } - run_ini = (result.value() & 0x01); - init_children = run_ini || (result.value() & 0x02); + run_ini = (result->value & 0x01); + init_children = run_ini || (result->value & 0x02); } if (run_ini) diff --git a/kernel/kernel/ACPI/AML/String.cpp b/kernel/kernel/ACPI/AML/String.cpp new file mode 100644 index 0000000000..93bca18ff6 --- /dev/null +++ b/kernel/kernel/ACPI/AML/String.cpp @@ -0,0 +1,58 @@ +#include +#include + +namespace Kernel::ACPI::AML +{ + + BAN::Optional String::logical_compare(BAN::RefPtr node, AML::Byte binaryop) + { + auto rhs = node ? node->as_string() : BAN::RefPtr(); + if (!rhs) + { + AML_ERROR("String logical compare RHS is not string"); + return {}; + } + + (void)binaryop; + AML_TODO("Logical compare string"); + return {}; + } + + BAN::RefPtr String::as_buffer() + { + auto buffer = MUST(BAN::RefPtr::create()); + MUST(buffer->buffer.resize(string.size())); + for (size_t i = 0; i < string.size(); i++) + buffer->buffer[i] = string[i]; + return buffer; + } + + ParseResult String::parse(ParseContext& context) + { + ASSERT(context.aml_data.size() >= 1); + ASSERT(static_cast(context.aml_data[0]) == AML::Byte::StringPrefix); + context.aml_data = context.aml_data.slice(1); + + BAN::Vector string; + + while (context.aml_data.size() > 0) + { + if (context.aml_data[0] == 0x00) + break; + MUST(string.push_back(context.aml_data[0])); + context.aml_data = context.aml_data.slice(1); + } + + if (context.aml_data.size() == 0) + return ParseResult::Failure; + if (context.aml_data[0] != 0x00) + return ParseResult::Failure; + context.aml_data = context.aml_data.slice(1); + + auto string_node = MUST(BAN::RefPtr::create()); + string_node->string = BAN::move(string); + + return ParseResult(string_node); + } + +}