Kernel: Add more conversions for AML Integer, Register, String
This commit is contained in:
parent
cf970d5914
commit
d9b3a4bf77
|
@ -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
|
||||
|
|
|
@ -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<bool> logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop)
|
||||
{
|
||||
auto rhs_node = node ? node->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!rhs_node)
|
||||
{
|
||||
AML_ERROR("Integer logical compare RHS cannot be converted to");
|
||||
return {};
|
||||
}
|
||||
const auto rhs_value = static_cast<AML::Integer*>(rhs_node.ptr())->value;
|
||||
BAN::Optional<bool> logical_compare(BAN::RefPtr<AML::Node> 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<AML::Node> convert(uint8_t mask) override;
|
||||
BAN::RefPtr<Node> copy() override;
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> store_node) override;
|
||||
|
||||
BAN::RefPtr<AML::Node> 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<Node> copy() override { return MUST(BAN::RefPtr<Integer>::create(value)); }
|
||||
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> 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<AML::Node>();
|
||||
if (!conv_node)
|
||||
{
|
||||
AML_ERROR("Cannot store non-integer to integer");
|
||||
return {};
|
||||
}
|
||||
value = static_cast<AML::Integer*>(conv_node.ptr())->value;
|
||||
return MUST(BAN::RefPtr<AML::Integer>::create(value));
|
||||
}
|
||||
|
||||
static ParseResult parse(BAN::ConstByteSpan& aml_data)
|
||||
{
|
||||
switch (static_cast<AML::Byte>(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<Integer>::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<Integer>::create(value)));
|
||||
}
|
||||
case AML::Byte::DWordPrefix:
|
||||
{
|
||||
if (aml_data.size() < 5)
|
||||
return ParseResult::Failure;
|
||||
uint32_t value = 0;
|
||||
value |= static_cast<uint32_t>(aml_data[1]) << 0;
|
||||
value |= static_cast<uint32_t>(aml_data[2]) << 8;
|
||||
value |= static_cast<uint32_t>(aml_data[3]) << 16;
|
||||
value |= static_cast<uint32_t>(aml_data[4]) << 24;
|
||||
aml_data = aml_data.slice(5);
|
||||
return ParseResult(MUST(BAN::RefPtr<Integer>::create(value)));
|
||||
}
|
||||
case AML::Byte::QWordPrefix:
|
||||
{
|
||||
if (aml_data.size() < 9)
|
||||
return ParseResult::Failure;
|
||||
uint64_t value = 0;
|
||||
value |= static_cast<uint64_t>(aml_data[1]) << 0;
|
||||
value |= static_cast<uint64_t>(aml_data[2]) << 8;
|
||||
value |= static_cast<uint64_t>(aml_data[3]) << 16;
|
||||
value |= static_cast<uint64_t>(aml_data[4]) << 24;
|
||||
value |= static_cast<uint64_t>(aml_data[5]) << 32;
|
||||
value |= static_cast<uint64_t>(aml_data[6]) << 40;
|
||||
value |= static_cast<uint64_t>(aml_data[7]) << 48;
|
||||
value |= static_cast<uint64_t>(aml_data[8]) << 56;
|
||||
aml_data = aml_data.slice(9);
|
||||
return ParseResult(MUST(BAN::RefPtr<Integer>::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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -9,46 +9,13 @@ namespace Kernel::ACPI::AML
|
|||
{
|
||||
BAN::RefPtr<AML::Node> value;
|
||||
|
||||
Register()
|
||||
: Node(Node::Type::Register)
|
||||
{}
|
||||
Register(BAN::RefPtr<AML::Node> value)
|
||||
: Node(Node::Type::Register)
|
||||
, value(value)
|
||||
{}
|
||||
Register();
|
||||
Register(BAN::RefPtr<AML::Node> node);
|
||||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override
|
||||
{
|
||||
if (!value)
|
||||
{
|
||||
AML_ERROR("Trying to convert null Register");
|
||||
return {};
|
||||
}
|
||||
return value->convert(mask);
|
||||
}
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override;
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> source) override;
|
||||
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,31 @@ namespace Kernel::ACPI::AML
|
|||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override;
|
||||
|
||||
BAN::RefPtr<AML::Node> copy() override
|
||||
{
|
||||
auto new_string = MUST(BAN::RefPtr<AML::String>::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<AML::Node> store(BAN::RefPtr<AML::Node> 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<AML::String*>(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<const char*>(string.data()), string.size());
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
#include <kernel/ACPI/AML/Buffer.h>
|
||||
#include <kernel/ACPI/AML/Integer.h>
|
||||
#include <kernel/ACPI/AML/String.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
AML::Integer::Integer(uint64_t value, bool constant)
|
||||
: Node(Node::Type::Integer)
|
||||
, value(value)
|
||||
, constant(constant)
|
||||
{}
|
||||
|
||||
BAN::Optional<bool> AML::Integer::logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop)
|
||||
{
|
||||
auto rhs_node = node ? node->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!rhs_node)
|
||||
{
|
||||
AML_ERROR("Integer logical compare RHS cannot be converted to");
|
||||
return {};
|
||||
}
|
||||
const auto rhs_value = static_cast<AML::Integer*>(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::Node> AML::Integer::convert(uint8_t mask)
|
||||
{
|
||||
if (mask & AML::Node::ConvInteger)
|
||||
return this;
|
||||
if (mask & AML::Node::ConvBuffer)
|
||||
{
|
||||
auto buffer = MUST(BAN::RefPtr<AML::Buffer>::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<AML::String>::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::Node> AML::Integer::copy()
|
||||
{
|
||||
return MUST(BAN::RefPtr<Integer>::create(value));
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> AML::Integer::store(BAN::RefPtr<AML::Node> 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<AML::Node>();
|
||||
if (!conv_node)
|
||||
{
|
||||
AML_ERROR("Cannot store non-integer to integer");
|
||||
return {};
|
||||
}
|
||||
value = static_cast<AML::Integer*>(conv_node.ptr())->value;
|
||||
return MUST(BAN::RefPtr<AML::Integer>::create(value));
|
||||
}
|
||||
|
||||
AML::ParseResult AML::Integer::parse(BAN::ConstByteSpan& aml_data)
|
||||
{
|
||||
switch (static_cast<AML::Byte>(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<Integer>::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<Integer>::create(value)));
|
||||
}
|
||||
case AML::Byte::DWordPrefix:
|
||||
{
|
||||
if (aml_data.size() < 5)
|
||||
return ParseResult::Failure;
|
||||
uint32_t value = 0;
|
||||
value |= static_cast<uint32_t>(aml_data[1]) << 0;
|
||||
value |= static_cast<uint32_t>(aml_data[2]) << 8;
|
||||
value |= static_cast<uint32_t>(aml_data[3]) << 16;
|
||||
value |= static_cast<uint32_t>(aml_data[4]) << 24;
|
||||
aml_data = aml_data.slice(5);
|
||||
return ParseResult(MUST(BAN::RefPtr<Integer>::create(value)));
|
||||
}
|
||||
case AML::Byte::QWordPrefix:
|
||||
{
|
||||
if (aml_data.size() < 9)
|
||||
return ParseResult::Failure;
|
||||
uint64_t value = 0;
|
||||
value |= static_cast<uint64_t>(aml_data[1]) << 0;
|
||||
value |= static_cast<uint64_t>(aml_data[2]) << 8;
|
||||
value |= static_cast<uint64_t>(aml_data[3]) << 16;
|
||||
value |= static_cast<uint64_t>(aml_data[4]) << 24;
|
||||
value |= static_cast<uint64_t>(aml_data[5]) << 32;
|
||||
value |= static_cast<uint64_t>(aml_data[6]) << 40;
|
||||
value |= static_cast<uint64_t>(aml_data[7]) << 48;
|
||||
value |= static_cast<uint64_t>(aml_data[8]) << 56;
|
||||
aml_data = aml_data.slice(9);
|
||||
return ParseResult(MUST(BAN::RefPtr<Integer>::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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
#include <kernel/ACPI/AML/Reference.h>
|
||||
#include <kernel/ACPI/AML/Register.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
AML::Register::Register()
|
||||
: Node(Node::Type::Register)
|
||||
{}
|
||||
AML::Register::Register(BAN::RefPtr<AML::Node> node)
|
||||
: Node(Node::Type::Register)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
value = node;
|
||||
return;
|
||||
}
|
||||
|
||||
while (node)
|
||||
{
|
||||
if (node->type == AML::Node::Type::Reference)
|
||||
node = static_cast<AML::Reference*>(node.ptr())->node;
|
||||
else if (node)
|
||||
node = node->copy();
|
||||
if (node->type == AML::Node::Type::Register)
|
||||
{
|
||||
node = static_cast<AML::Register*>(node.ptr())->value;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ASSERT(node);
|
||||
value = node;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> AML::Register::convert(uint8_t mask)
|
||||
{
|
||||
if (!value)
|
||||
{
|
||||
AML_ERROR("Trying to convert null Register");
|
||||
return {};
|
||||
}
|
||||
return value->convert(mask);
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> AML::Register::store(BAN::RefPtr<AML::Node> source)
|
||||
{
|
||||
if (source && source->type == AML::Node::Type::Register)
|
||||
source = static_cast<AML::Register*>(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(" }");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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<size_t>(string.size(), sizeof(value));
|
||||
memcpy(&value, string.data(), bytes);
|
||||
return MUST(BAN::RefPtr<AML::Integer>::create(value));
|
||||
}
|
||||
if (mask & AML::Node::ConvBuffer)
|
||||
return as_buffer();
|
||||
|
|
Loading…
Reference in New Issue