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); + } + +}