diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 3b99aba1..350045ec 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -3,10 +3,12 @@ set(KERNEL_SOURCES kernel/ACPI/ACPI.cpp kernel/ACPI/AML.cpp kernel/ACPI/AML/Field.cpp + kernel/ACPI/AML/Integer.cpp kernel/ACPI/AML/NamedObject.cpp 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/Integer.h b/kernel/include/kernel/ACPI/AML/Integer.h index 6e3c3252..b2942b24 100644 --- a/kernel/include/kernel/ACPI/AML/Integer.h +++ b/kernel/include/kernel/ACPI/AML/Integer.h @@ -23,162 +23,17 @@ namespace Kernel::ACPI::AML uint64_t value; const bool constant; - Integer(uint64_t value, bool constant = false) - : Node(Node::Type::Integer) - , value(value) - , constant(constant) - {} + Integer(uint64_t value, bool constant = false); - BAN::Optional logical_compare(BAN::RefPtr node, AML::Byte binaryop) - { - auto rhs_node = node ? node->convert(AML::Node::ConvInteger) : BAN::RefPtr(); - if (!rhs_node) - { - AML_ERROR("Integer logical compare RHS cannot be converted to"); - return {}; - } - const auto rhs_value = static_cast(rhs_node.ptr())->value; + BAN::Optional logical_compare(BAN::RefPtr node, AML::Byte binaryop); - 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 convert(uint8_t mask) override; + BAN::RefPtr copy() override; + BAN::RefPtr store(BAN::RefPtr store_node) override; - 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 {}; - } + static ParseResult parse(BAN::ConstByteSpan& aml_data); - BAN::RefPtr copy() override { return MUST(BAN::RefPtr::create(value)); } - - BAN::RefPtr store(BAN::RefPtr store_node) override - { - if (constant) - { - AML_ERROR("Cannot store to constant integer"); - return {}; - } - 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 {}; - } - value = static_cast(conv_node.ptr())->value; - return MUST(BAN::RefPtr::create(value)); - } - - static ParseResult parse(BAN::ConstByteSpan& aml_data) - { - switch (static_cast(aml_data[0])) - { - case AML::Byte::ZeroOp: - aml_data = aml_data.slice(1); - return ParseResult(Constants::Zero); - case AML::Byte::OneOp: - aml_data = aml_data.slice(1); - return ParseResult(Constants::One); - case AML::Byte::OnesOp: - aml_data = aml_data.slice(1); - return ParseResult(Constants::Ones); - case AML::Byte::BytePrefix: - { - if (aml_data.size() < 2) - return ParseResult::Failure; - const uint8_t value = aml_data[1]; - aml_data = aml_data.slice(2); - return ParseResult(MUST(BAN::RefPtr::create(value))); - } - case AML::Byte::WordPrefix: - { - if (aml_data.size() < 3) - return ParseResult::Failure; - uint16_t value = 0; - value |= aml_data[1] << 0; - value |= aml_data[2] << 8; - aml_data = aml_data.slice(3); - return ParseResult(MUST(BAN::RefPtr::create(value))); - } - case AML::Byte::DWordPrefix: - { - if (aml_data.size() < 5) - return ParseResult::Failure; - uint32_t value = 0; - value |= static_cast(aml_data[1]) << 0; - value |= static_cast(aml_data[2]) << 8; - value |= static_cast(aml_data[3]) << 16; - value |= static_cast(aml_data[4]) << 24; - aml_data = aml_data.slice(5); - return ParseResult(MUST(BAN::RefPtr::create(value))); - } - case AML::Byte::QWordPrefix: - { - if (aml_data.size() < 9) - return ParseResult::Failure; - uint64_t value = 0; - value |= static_cast(aml_data[1]) << 0; - value |= static_cast(aml_data[2]) << 8; - value |= static_cast(aml_data[3]) << 16; - value |= static_cast(aml_data[4]) << 24; - value |= static_cast(aml_data[5]) << 32; - value |= static_cast(aml_data[6]) << 40; - value |= static_cast(aml_data[7]) << 48; - value |= static_cast(aml_data[8]) << 56; - aml_data = aml_data.slice(9); - return ParseResult(MUST(BAN::RefPtr::create(value))); - } - default: - ASSERT_NOT_REACHED(); - } - } - - void debug_print(int indent) const override - { - AML_DEBUG_PRINT_INDENT(indent); - if (!constant) - AML_DEBUG_PRINT("0x{H}", value); - else - { - AML_DEBUG_PRINT("Const "); - if (value == Constants::Zero->value) - AML_DEBUG_PRINT("Zero"); - else if (value == Constants::One->value) - AML_DEBUG_PRINT("One"); - else if (value == Constants::Ones->value) - AML_DEBUG_PRINT("Ones"); - else - ASSERT_NOT_REACHED(); - } - } + void debug_print(int indent) const override; }; } diff --git a/kernel/include/kernel/ACPI/AML/Register.h b/kernel/include/kernel/ACPI/AML/Register.h index c2123947..7ff0b0b6 100644 --- a/kernel/include/kernel/ACPI/AML/Register.h +++ b/kernel/include/kernel/ACPI/AML/Register.h @@ -9,46 +9,13 @@ namespace Kernel::ACPI::AML { BAN::RefPtr value; - Register() - : Node(Node::Type::Register) - {} - Register(BAN::RefPtr value) - : Node(Node::Type::Register) - , value(value) - {} + Register(); + Register(BAN::RefPtr node); - BAN::RefPtr convert(uint8_t mask) override - { - if (!value) - { - AML_ERROR("Trying to convert null Register"); - return {}; - } - return value->convert(mask); - } + BAN::RefPtr convert(uint8_t mask) override; + BAN::RefPtr store(BAN::RefPtr source) override; - BAN::RefPtr store(BAN::RefPtr source) override - { - if (value && value->type == AML::Node::Type::Reference) - return value->store(source); - value = source->copy(); - return value; - } - - void debug_print(int indent) const override - { - AML_DEBUG_PRINT_INDENT(indent); - if (!value) - AML_DEBUG_PRINT("Register { No value }"); - else - { - AML_DEBUG_PRINTLN("Register { "); - value->debug_print(indent + 1); - AML_DEBUG_PRINTLN(""); - AML_DEBUG_PRINT_INDENT(indent); - AML_DEBUG_PRINT(" }"); - } - } + void debug_print(int indent) const override; }; } diff --git a/kernel/include/kernel/ACPI/AML/String.h b/kernel/include/kernel/ACPI/AML/String.h index 908f674c..e5a40dbf 100644 --- a/kernel/include/kernel/ACPI/AML/String.h +++ b/kernel/include/kernel/ACPI/AML/String.h @@ -24,6 +24,31 @@ namespace Kernel::ACPI::AML BAN::RefPtr convert(uint8_t mask) override; + BAN::RefPtr copy() override + { + auto new_string = MUST(BAN::RefPtr::create()); + MUST(new_string->string.resize(this->string.size())); + for (size_t i = 0; i < this->string.size(); i++) + new_string->string[i] = this->string[i]; + return new_string; + } + + BAN::RefPtr store(BAN::RefPtr node) override + { + ASSERT(node); + auto conv_node = node->convert(AML::Node::ConvString); + if (!conv_node) + { + AML_ERROR("Could not convert to String"); + return {}; + } + auto* string_node = static_cast(conv_node.ptr()); + MUST(string.resize(string_node->string.size())); + for (size_t i = 0; i < string.size(); i++) + string[i] = string_node->string[i]; + return string_node->copy(); + } + BAN::StringView string_view() const { return BAN::StringView(reinterpret_cast(string.data()), string.size()); diff --git a/kernel/kernel/ACPI/AML/Integer.cpp b/kernel/kernel/ACPI/AML/Integer.cpp new file mode 100644 index 00000000..83f0d673 --- /dev/null +++ b/kernel/kernel/ACPI/AML/Integer.cpp @@ -0,0 +1,180 @@ +#include +#include +#include + +namespace Kernel::ACPI +{ + + AML::Integer::Integer(uint64_t value, bool constant) + : Node(Node::Type::Integer) + , value(value) + , constant(constant) + {} + + BAN::Optional AML::Integer::logical_compare(BAN::RefPtr node, AML::Byte binaryop) + { + auto rhs_node = node ? node->convert(AML::Node::ConvInteger) : BAN::RefPtr(); + if (!rhs_node) + { + 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; + default: + ASSERT_NOT_REACHED(); + } + } + + BAN::RefPtr AML::Integer::convert(uint8_t mask) + { + if (mask & AML::Node::ConvInteger) + return this; + if (mask & AML::Node::ConvBuffer) + { + auto buffer = MUST(BAN::RefPtr::create()); + MUST(buffer->buffer.resize(8)); + for (size_t i = 0; i < 8; i++) + buffer->buffer[i] = (value >> (56 - i * 8)) & 0xFF; + return buffer; + } + 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) + { + constexpr auto get_hex_char = + [](uint8_t nibble) + { + return (nibble < 10 ? '0' : 'A' - 10) + nibble; + }; + + auto string = MUST(BAN::RefPtr::create()); + MUST(string->string.resize(16)); + for (size_t i = 0; i < 16; i++) + string->string[i] = get_hex_char((value >> (60 - i * 4)) & 0xF); + return string; + } + return {}; + } + + BAN::RefPtr AML::Integer::copy() + { + return MUST(BAN::RefPtr::create(value)); + } + + BAN::RefPtr AML::Integer::store(BAN::RefPtr store_node) + { + if (constant) + { + AML_ERROR("Cannot store to constant integer"); + return {}; + } + 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 {}; + } + value = static_cast(conv_node.ptr())->value; + return MUST(BAN::RefPtr::create(value)); + } + + AML::ParseResult AML::Integer::parse(BAN::ConstByteSpan& aml_data) + { + switch (static_cast(aml_data[0])) + { + case AML::Byte::ZeroOp: + aml_data = aml_data.slice(1); + return ParseResult(Constants::Zero); + case AML::Byte::OneOp: + aml_data = aml_data.slice(1); + return ParseResult(Constants::One); + case AML::Byte::OnesOp: + aml_data = aml_data.slice(1); + return ParseResult(Constants::Ones); + case AML::Byte::BytePrefix: + { + if (aml_data.size() < 2) + return ParseResult::Failure; + const uint8_t value = aml_data[1]; + aml_data = aml_data.slice(2); + return ParseResult(MUST(BAN::RefPtr::create(value))); + } + case AML::Byte::WordPrefix: + { + if (aml_data.size() < 3) + return ParseResult::Failure; + uint16_t value = 0; + value |= aml_data[1] << 0; + value |= aml_data[2] << 8; + aml_data = aml_data.slice(3); + return ParseResult(MUST(BAN::RefPtr::create(value))); + } + case AML::Byte::DWordPrefix: + { + if (aml_data.size() < 5) + return ParseResult::Failure; + uint32_t value = 0; + value |= static_cast(aml_data[1]) << 0; + value |= static_cast(aml_data[2]) << 8; + value |= static_cast(aml_data[3]) << 16; + value |= static_cast(aml_data[4]) << 24; + aml_data = aml_data.slice(5); + return ParseResult(MUST(BAN::RefPtr::create(value))); + } + case AML::Byte::QWordPrefix: + { + if (aml_data.size() < 9) + return ParseResult::Failure; + uint64_t value = 0; + value |= static_cast(aml_data[1]) << 0; + value |= static_cast(aml_data[2]) << 8; + value |= static_cast(aml_data[3]) << 16; + value |= static_cast(aml_data[4]) << 24; + value |= static_cast(aml_data[5]) << 32; + value |= static_cast(aml_data[6]) << 40; + value |= static_cast(aml_data[7]) << 48; + value |= static_cast(aml_data[8]) << 56; + aml_data = aml_data.slice(9); + return ParseResult(MUST(BAN::RefPtr::create(value))); + } + default: + ASSERT_NOT_REACHED(); + } + } + + void AML::Integer::debug_print(int indent) const + { + AML_DEBUG_PRINT_INDENT(indent); + if (!constant) + AML_DEBUG_PRINT("0x{H}", value); + else + { + AML_DEBUG_PRINT("Const "); + if (value == Constants::Zero->value) + AML_DEBUG_PRINT("Zero"); + else if (value == Constants::One->value) + AML_DEBUG_PRINT("One"); + else if (value == Constants::Ones->value) + AML_DEBUG_PRINT("Ones"); + else + ASSERT_NOT_REACHED(); + } + } + +} diff --git a/kernel/kernel/ACPI/AML/Register.cpp b/kernel/kernel/ACPI/AML/Register.cpp new file mode 100644 index 00000000..9027a222 --- /dev/null +++ b/kernel/kernel/ACPI/AML/Register.cpp @@ -0,0 +1,71 @@ +#include +#include + +namespace Kernel::ACPI +{ + + AML::Register::Register() + : Node(Node::Type::Register) + {} + AML::Register::Register(BAN::RefPtr node) + : Node(Node::Type::Register) + { + if (!node) + { + value = node; + return; + } + + while (node) + { + if (node->type == AML::Node::Type::Reference) + node = static_cast(node.ptr())->node; + else if (node) + node = node->copy(); + if (node->type == AML::Node::Type::Register) + { + node = static_cast(node.ptr())->value; + continue; + } + break; + } + ASSERT(node); + value = node; + } + + BAN::RefPtr AML::Register::convert(uint8_t mask) + { + if (!value) + { + AML_ERROR("Trying to convert null Register"); + return {}; + } + return value->convert(mask); + } + + BAN::RefPtr AML::Register::store(BAN::RefPtr source) + { + if (source && source->type == AML::Node::Type::Register) + source = static_cast(source.ptr())->value; + if (value && value->type == AML::Node::Type::Reference) + return value->store(source); + value = source->copy(); + return value; + } + + void AML::Register::debug_print(int indent) const + { + AML_DEBUG_PRINT_INDENT(indent); + if (!value) + AML_DEBUG_PRINT("Register { No value }"); + else + { + AML_DEBUG_PRINTLN("Register { "); + value->debug_print(indent + 1); + AML_DEBUG_PRINTLN(""); + AML_DEBUG_PRINT_INDENT(indent); + AML_DEBUG_PRINT(" }"); + } + } + +} diff --git a/kernel/kernel/ACPI/AML/String.cpp b/kernel/kernel/ACPI/AML/String.cpp index 9def9208..a0f8db45 100644 --- a/kernel/kernel/ACPI/AML/String.cpp +++ b/kernel/kernel/ACPI/AML/String.cpp @@ -33,8 +33,11 @@ namespace Kernel::ACPI::AML return this; if (mask & AML::Node::ConvInteger) { - AML_TODO("Convert String to Integer"); - return {}; + // Apparently this is what NT does, but its definitely not spec compliant :D + uint64_t value = 0; + const size_t bytes = BAN::Math::min(string.size(), sizeof(value)); + memcpy(&value, string.data(), bytes); + return MUST(BAN::RefPtr::create(value)); } if (mask & AML::Node::ConvBuffer) return as_buffer();