diff --git a/kernel/include/kernel/ACPI/AML/Buffer.h b/kernel/include/kernel/ACPI/AML/Buffer.h index e4a270be..c5610a72 100644 --- a/kernel/include/kernel/ACPI/AML/Buffer.h +++ b/kernel/include/kernel/ACPI/AML/Buffer.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace Kernel::ACPI::AML { @@ -67,11 +68,12 @@ namespace Kernel::ACPI::AML struct BufferField : AML::NamedObject { - BAN::RefPtr buffer; + BAN::RefPtr buffer; size_t field_bit_offset; size_t field_bit_size; - BufferField(AML::NameSeg name, BAN::RefPtr buffer, size_t field_bit_offset, size_t field_bit_size) + template requires BAN::is_same_v || BAN::is_same_v + BufferField(AML::NameSeg name, BAN::RefPtr buffer, size_t field_bit_offset, size_t field_bit_size) : AML::NamedObject(Node::Type::BufferField, name) , buffer(buffer) , field_bit_offset(field_bit_offset) @@ -81,7 +83,11 @@ namespace Kernel::ACPI::AML BAN::RefPtr evaluate() override { ASSERT(buffer); - ASSERT(field_bit_offset + field_bit_size <= buffer->buffer.size() * 8); + 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; @@ -89,13 +95,13 @@ namespace Kernel::ACPI::AML const size_t bit_offset = field_bit_offset % 8; if (field_bit_size == 1) { - value = (buffer->buffer[byte_offset] >> bit_offset) & 1; + value = (buffer[byte_offset] >> bit_offset) & 1; } else { ASSERT(bit_offset == 0); for (size_t byte = 0; byte < field_bit_size / 8; byte++) - value |= buffer->buffer[byte_offset + byte] << byte; + value |= buffer[byte_offset + byte] << byte; } return MUST(BAN::RefPtr::create(value)); @@ -104,7 +110,11 @@ namespace Kernel::ACPI::AML bool store(BAN::RefPtr node) override { ASSERT(buffer); - ASSERT(field_bit_offset + field_bit_size <= buffer->buffer.size() * 8); + ASSERT(buffer->type == AML::Node::Type::Buffer || buffer->type == AML::Node::Type::String); + 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); auto value = node->as_integer(); if (!value.has_value()) @@ -114,14 +124,14 @@ namespace Kernel::ACPI::AML const size_t bit_offset = field_bit_offset % 8; if (field_bit_size == 1) { - buffer->buffer[byte_offset] &= ~(1 << bit_offset); - buffer->buffer[byte_offset] |= (value.value() & 1) << bit_offset; + buffer[byte_offset] &= ~(1 << bit_offset); + buffer[byte_offset] |= (value.value() & 1) << bit_offset; } else { ASSERT(bit_offset == 0); for (size_t byte = 0; byte < field_bit_size / 8; byte++) - buffer->buffer[byte_offset + byte] = (value.value() >> (byte * 8)) & 0xFF; + buffer[byte_offset + byte] = (value.value() >> (byte * 8)) & 0xFF; } return true; @@ -163,7 +173,7 @@ namespace Kernel::ACPI::AML AML_ERROR("Buffer source does not evaluate to a Buffer"); return ParseResult::Failure; } - auto buffer = static_cast(buffer_node.ptr()); + auto buffer = BAN::RefPtr(static_cast(buffer_node.ptr())); auto index_result = AML::parse_object(context); if (!index_result.success()) diff --git a/kernel/include/kernel/ACPI/AML/Index.h b/kernel/include/kernel/ACPI/AML/Index.h index 3928b092..2212a692 100644 --- a/kernel/include/kernel/ACPI/AML/Index.h +++ b/kernel/include/kernel/ACPI/AML/Index.h @@ -42,7 +42,7 @@ namespace Kernel::ACPI::AML { case AML::Node::Type::Buffer: { - auto buffer = static_cast(source.ptr()); + auto buffer = BAN::RefPtr(static_cast(source.ptr())); if (index.value() >= buffer->buffer.size()) { AML_ERROR("IndexOp index is out of buffer bounds"); @@ -65,8 +65,17 @@ namespace Kernel::ACPI::AML break; } case AML::Node::Type::String: - AML_TODO("IndexOp source String"); - return ParseResult::Failure; + { + auto string = BAN::RefPtr(static_cast(source.ptr())); + 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)); + result = MUST(BAN::RefPtr::create(buffer_field)); + break; + } default: AML_ERROR("IndexOp source is not a Buffer, Package, or String"); return ParseResult::Failure; diff --git a/kernel/include/kernel/ACPI/AML/String.h b/kernel/include/kernel/ACPI/AML/String.h index 027a3707..5ca48c88 100644 --- a/kernel/include/kernel/ACPI/AML/String.h +++ b/kernel/include/kernel/ACPI/AML/String.h @@ -9,28 +9,40 @@ namespace Kernel::ACPI::AML struct String : public AML::Node { - BAN::String string; + BAN::Vector string; String() : Node(Node::Type::String) {} + String(BAN::StringView string) + : Node(Node::Type::String) + { + MUST(this->string.resize(string.size())); + for (size_t i = 0; i < string.size(); i++) + this->string[i] = string[i]; + } BAN::RefPtr evaluate() override { return this; } + BAN::StringView string_view() const + { + 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::String string; + BAN::Vector string; while (context.aml_data.size() > 0) { if (context.aml_data[0] == 0x00) break; - MUST(string.push_back(static_cast(context.aml_data[0]))); + MUST(string.push_back(context.aml_data[0])); context.aml_data = context.aml_data.slice(1); } @@ -49,7 +61,7 @@ namespace Kernel::ACPI::AML virtual void debug_print(int indent) const override { AML_DEBUG_PRINT_INDENT(indent); - AML_DEBUG_PRINT("String \"{}\"", string); + AML_DEBUG_PRINT("String \"{}\"", string_view()); } }; diff --git a/kernel/kernel/ACPI/AML/Namespace.cpp b/kernel/kernel/ACPI/AML/Namespace.cpp index 031f47df..b679b0ac 100644 --- a/kernel/kernel/ACPI/AML/Namespace.cpp +++ b/kernel/kernel/ACPI/AML/Namespace.cpp @@ -222,7 +222,7 @@ namespace Kernel::ACPI return {}; } auto string = static_cast(arg.ptr()); - return string->string == "Linux" ? AML::Integer::Constants::Ones : AML::Integer::Constants::Zero; + return string->string_view() == "Linux"_sv ? AML::Integer::Constants::Ones : AML::Integer::Constants::Zero; }; ASSERT(s_root_namespace->add_named_object(context, AML::NameString("\\_OSI"), osi));