Kernel: Rewrite the AML conversion API
This doesn't currently make the interpreter any better, but it will make further implementation easier to be spec (or hardware...) compliant
This commit is contained in:
parent
44d5c8c4b4
commit
3f5ee6f414
|
@ -7,7 +7,6 @@ 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
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Alias : public AML::NamedObject
|
||||
struct Alias final : public AML::NamedObject
|
||||
{
|
||||
BAN::RefPtr<AML::Node> target;
|
||||
|
||||
|
@ -18,14 +18,11 @@ namespace Kernel::ACPI::AML
|
|||
|
||||
bool is_scope() const override { return target->is_scope(); }
|
||||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
BAN::RefPtr<Node> copy() override { return target->copy(); }
|
||||
|
||||
BAN::RefPtr<AML::Buffer> as_buffer() override { return target->as_buffer(); }
|
||||
BAN::RefPtr<AML::Integer> as_integer() override { return target->as_integer(); }
|
||||
BAN::RefPtr<AML::String> as_string() override { return target->as_string(); }
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override { return target->evaluate(); }
|
||||
bool store(BAN::RefPtr<AML::Node> node) override { return target->store(node); }
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> node) override { ASSERT(target); return target->store(node); }
|
||||
|
||||
static ParseResult parse(ParseContext& context)
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Buffer : public AML::Node
|
||||
struct Buffer final : public AML::Node
|
||||
{
|
||||
BAN::Vector<uint8_t> buffer;
|
||||
|
||||
|
@ -20,10 +20,10 @@ namespace Kernel::ACPI::AML
|
|||
|
||||
BAN::Optional<bool> logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop)
|
||||
{
|
||||
auto rhs = node ? node->as_buffer() : BAN::RefPtr<AML::Buffer>();
|
||||
if (!rhs)
|
||||
auto rhs_node = node ? node->convert(AML::Node::ConvBuffer) : BAN::RefPtr<AML::Node>();
|
||||
if (!rhs_node)
|
||||
{
|
||||
AML_ERROR("Buffer logical compare RHS is not buffer");
|
||||
AML_ERROR("Buffer logical compare RHS cannot be converted to buffer");
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -32,19 +32,18 @@ namespace Kernel::ACPI::AML
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Buffer> as_buffer() override { return this; }
|
||||
|
||||
BAN::RefPtr<AML::Integer> as_integer() override
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override
|
||||
{
|
||||
uint64_t value = 0;
|
||||
for (size_t i = 0; i < BAN::Math::min<size_t>(buffer.size(), 8); i++)
|
||||
value |= static_cast<uint64_t>(buffer[i]) << (8 * i);
|
||||
return MUST(BAN::RefPtr<Integer>::create(value));
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override
|
||||
{
|
||||
return this;
|
||||
if (mask & AML::Node::ConvBuffer)
|
||||
return this;
|
||||
if (mask & AML::Node::ConvInteger)
|
||||
return as_integer();
|
||||
if (mask & AML::Node::ConvString)
|
||||
{
|
||||
AML_TODO("Convert BufferField to String");
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static ParseResult parse(AML::ParseContext& context)
|
||||
|
@ -60,15 +59,21 @@ namespace Kernel::ACPI::AML
|
|||
auto buffer_context = context;
|
||||
buffer_context.aml_data = buffer_pkg.value();
|
||||
|
||||
auto buffer_size_object = AML::parse_object(buffer_context);
|
||||
if (!buffer_size_object.success())
|
||||
auto buffer_size_result = AML::parse_object(buffer_context);
|
||||
if (!buffer_size_result.success())
|
||||
return ParseResult::Failure;
|
||||
|
||||
auto buffer_size = buffer_size_object.node()->as_integer();
|
||||
if (!buffer_size)
|
||||
auto buffer_size_node = buffer_size_result.node() ? buffer_size_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!buffer_size_node)
|
||||
{
|
||||
AML_ERROR("Buffer size is not an integer");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
uint32_t actual_buffer_size = BAN::Math::max<uint32_t>(buffer_size->value, buffer_context.aml_data.size());
|
||||
const uint32_t actual_buffer_size = BAN::Math::max<uint32_t>(
|
||||
static_cast<AML::Integer*>(buffer_size_node.ptr())->value,
|
||||
buffer_context.aml_data.size()
|
||||
);
|
||||
|
||||
auto buffer = MUST(BAN::RefPtr<Buffer>::create());
|
||||
MUST(buffer->buffer.resize(actual_buffer_size, 0));
|
||||
|
@ -88,9 +93,18 @@ namespace Kernel::ACPI::AML
|
|||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("Buffer ({} bytes)", buffer.size());
|
||||
}
|
||||
|
||||
private:
|
||||
BAN::RefPtr<AML::Integer> as_integer()
|
||||
{
|
||||
uint64_t value = 0;
|
||||
for (size_t i = 0; i < BAN::Math::min<size_t>(buffer.size(), 8); i++)
|
||||
value |= static_cast<uint64_t>(buffer[i]) << (8 * i);
|
||||
return MUST(BAN::RefPtr<Integer>::create(value));
|
||||
}
|
||||
};
|
||||
|
||||
struct BufferField : AML::NamedObject
|
||||
struct BufferField final : AML::NamedObject
|
||||
{
|
||||
BAN::RefPtr<AML::Node> buffer;
|
||||
size_t field_bit_offset;
|
||||
|
@ -104,49 +118,26 @@ namespace Kernel::ACPI::AML
|
|||
, field_bit_size(field_bit_size)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Integer> as_integer() override
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) 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<AML::Buffer*>(this->buffer.ptr())->buffer
|
||||
: static_cast<AML::String*>(this->buffer.ptr())->string;
|
||||
|
||||
uint64_t value = 0;
|
||||
|
||||
// TODO: optimize for whole byte accesses
|
||||
for (size_t i = 0; i < BAN::Math::min<size_t>(field_bit_size, 64); i++)
|
||||
if (mask & AML::Node::ConvBufferField)
|
||||
return this;
|
||||
if (mask & AML::Node::ConvInteger)
|
||||
return as_integer();
|
||||
if (mask & AML::Node::ConvBuffer)
|
||||
{
|
||||
const size_t bit = field_bit_offset + i;
|
||||
value |= static_cast<uint64_t>((buffer[bit / 8] >> (bit % 8)) & 1) << i;
|
||||
AML_TODO("Convert BufferField to Buffer");
|
||||
return {};
|
||||
}
|
||||
|
||||
return MUST(BAN::RefPtr<Integer>::create(value));
|
||||
if (mask & AML::Node::ConvString)
|
||||
{
|
||||
AML_TODO("Convert BufferField to String");
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() 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<AML::Buffer*>(this->buffer.ptr())->buffer
|
||||
: static_cast<AML::String*>(this->buffer.ptr())->string;
|
||||
ASSERT(field_bit_offset + field_bit_size <= buffer.size() * 8);
|
||||
|
||||
uint64_t value = 0;
|
||||
|
||||
// TODO: optimize for whole byte accesses
|
||||
for (size_t i = 0; i < field_bit_size; i++)
|
||||
{
|
||||
const size_t bit = field_bit_offset + i;
|
||||
value |= static_cast<uint64_t>((buffer[bit / 8] >> (bit % 8)) & 1) << i;
|
||||
}
|
||||
|
||||
return MUST(BAN::RefPtr<AML::Integer>::create(value));
|
||||
}
|
||||
|
||||
bool store(BAN::RefPtr<AML::Node> node) override
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> node) override
|
||||
{
|
||||
ASSERT(buffer);
|
||||
ASSERT(buffer->type == AML::Node::Type::Buffer || buffer->type == AML::Node::Type::String);
|
||||
|
@ -155,19 +146,20 @@ namespace Kernel::ACPI::AML
|
|||
: static_cast<AML::String*>(this->buffer.ptr())->string;
|
||||
ASSERT(field_bit_offset + field_bit_size <= buffer.size() * 8);
|
||||
|
||||
auto value = node->as_integer();
|
||||
if (!value)
|
||||
return false;
|
||||
auto value_node = node ? node->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!value_node)
|
||||
return {};
|
||||
const auto value = static_cast<AML::Integer*>(value_node.ptr())->value;
|
||||
|
||||
// TODO: optimize for whole byte accesses
|
||||
for (size_t i = 0; i < field_bit_size; i++)
|
||||
{
|
||||
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 >> i) & 1) << (bit % 8);
|
||||
}
|
||||
|
||||
return true;
|
||||
return value_node;
|
||||
}
|
||||
|
||||
static ParseResult parse(AML::ParseContext& context)
|
||||
|
@ -204,7 +196,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()->as_buffer() : BAN::RefPtr<AML::Buffer>();
|
||||
auto buffer_node = buffer_result.node() ? buffer_result.node()->convert(AML::Node::ConvBuffer) : BAN::RefPtr<AML::Node>();
|
||||
if (!buffer_node || buffer_node->type != Node::Type::Buffer)
|
||||
{
|
||||
AML_ERROR("Buffer source does not evaluate to a Buffer");
|
||||
|
@ -215,28 +207,25 @@ 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::RefPtr<AML::Integer>();
|
||||
if (!index)
|
||||
auto index_node = index_result.node() ? index_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!index_node)
|
||||
{
|
||||
AML_ERROR("Failed to parse index for BufferField");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
size_t field_bit_offset = index->value;
|
||||
if (field_bit_size != 1)
|
||||
field_bit_offset *= 8;
|
||||
|
||||
if (field_bit_size == 0)
|
||||
{
|
||||
auto bit_count_result = AML::parse_object(context);
|
||||
if (!index_result.success())
|
||||
if (!bit_count_result.success())
|
||||
return ParseResult::Failure;
|
||||
auto bit_count = bit_count_result.node() ? bit_count_result.node()->as_integer() : BAN::RefPtr<AML::Integer>();
|
||||
if (!bit_count)
|
||||
auto bit_count_node = bit_count_result.node() ? bit_count_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!bit_count_node)
|
||||
{
|
||||
AML_ERROR("Failed to parse bit count for BufferField");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
field_bit_size = bit_count->value;
|
||||
field_bit_size = static_cast<AML::Integer*>(bit_count_node.ptr())->value;
|
||||
}
|
||||
|
||||
auto field_name = AML::NameString::parse(context.aml_data);
|
||||
|
@ -248,6 +237,10 @@ namespace Kernel::ACPI::AML
|
|||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
size_t field_bit_offset = static_cast<AML::Integer*>(index_node.ptr())->value;
|
||||
if (field_bit_size != 1)
|
||||
field_bit_offset *= 8;
|
||||
|
||||
auto field = MUST(BAN::RefPtr<BufferField>::create(field_name->path.back(), buffer, field_bit_offset, field_bit_size));
|
||||
if (!Namespace::root_namespace()->add_named_object(context, field_name.value(), field))
|
||||
return ParseResult::Success;
|
||||
|
@ -268,6 +261,27 @@ namespace Kernel::ACPI::AML
|
|||
AML_DEBUG_PRINT(" }");
|
||||
}
|
||||
|
||||
private:
|
||||
BAN::RefPtr<AML::Integer> as_integer()
|
||||
{
|
||||
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<AML::Buffer*>(this->buffer.ptr())->buffer
|
||||
: static_cast<AML::String*>(this->buffer.ptr())->string;
|
||||
|
||||
uint64_t value = 0;
|
||||
|
||||
// TODO: optimize for whole byte accesses
|
||||
for (size_t i = 0; i < BAN::Math::min<size_t>(field_bit_size, 64); i++)
|
||||
{
|
||||
const size_t bit = field_bit_offset + i;
|
||||
value |= static_cast<uint64_t>((buffer[bit / 8] >> (bit % 8)) & 1) << i;
|
||||
}
|
||||
|
||||
return MUST(BAN::RefPtr<Integer>::create(value));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -61,13 +61,13 @@ namespace Kernel::ACPI::AML
|
|||
switch (opcode)
|
||||
{
|
||||
case AML::Byte::ToBufferOp:
|
||||
converted = data_node->as_buffer();
|
||||
converted = data_node->convert(AML::Node::ConvBuffer);
|
||||
break;
|
||||
case AML::Byte::ToIntegerOp:
|
||||
converted = data_node->as_integer();
|
||||
converted = data_node->convert(AML::Node::ConvInteger);
|
||||
break;
|
||||
case AML::Byte::ToStringOp:
|
||||
converted = data_node->as_string();
|
||||
converted = data_node->convert(AML::Node::ConvString);
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Device : public AML::Scope
|
||||
struct Device final : public AML::Scope
|
||||
{
|
||||
Device(NameSeg name)
|
||||
: Scope(Node::Type::Device, name)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
static ParseResult parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 2);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Event : public AML::NamedObject
|
||||
struct Event final : public AML::NamedObject
|
||||
{
|
||||
BAN::Atomic<uint32_t> signal_count { 0 };
|
||||
ThreadBlocker thread_blocker;
|
||||
|
@ -19,6 +19,8 @@ namespace Kernel::ACPI::AML
|
|||
: NamedObject(Node::Type::Event, name)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
static ParseResult parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 2);
|
||||
|
@ -43,7 +45,7 @@ namespace Kernel::ACPI::AML
|
|||
if (!event_result.success())
|
||||
return ParseResult::Failure;
|
||||
|
||||
auto general_node = event_result.node() ? event_result.node()->evaluate() : BAN::RefPtr<AML::Node>();
|
||||
auto general_node = event_result.node();
|
||||
if (!general_node || general_node->type != Node::Type::Event)
|
||||
{
|
||||
AML_ERROR("Release, Wait or Signal does not name an event");
|
||||
|
@ -58,12 +60,15 @@ namespace Kernel::ACPI::AML
|
|||
if (!timeout_result.success())
|
||||
return ParseResult::Failure;
|
||||
|
||||
auto timeout = timeout_result.node() ? timeout_result.node()->as_integer() : BAN::RefPtr<AML::Integer>();
|
||||
if (!timeout)
|
||||
auto timeout_node = timeout_result.node()
|
||||
? timeout_result.node()->convert(AML::Node::ConvInteger)
|
||||
: BAN::RefPtr<AML::Node>();
|
||||
if (!timeout_node)
|
||||
{
|
||||
AML_ERROR("Wait timeout does not evaluate to integer");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
const auto timeout_value = static_cast<AML::Integer*>(timeout_node.ptr())->value;
|
||||
|
||||
const uint64_t start_ms = SystemTimer::get().ms_since_boot();
|
||||
while (true)
|
||||
|
@ -77,14 +82,14 @@ namespace Kernel::ACPI::AML
|
|||
return ParseResult(Integer::Constants::Zero);
|
||||
}
|
||||
|
||||
if (timeout->value >= 0xFFFF)
|
||||
if (timeout_value >= 0xFFFF)
|
||||
event_node->thread_blocker.block_indefinite();
|
||||
else
|
||||
{
|
||||
const uint64_t current_ms = SystemTimer::get().ms_since_boot();
|
||||
if (current_ms >= start_ms + timeout->value)
|
||||
if (current_ms >= start_ms + timeout_value)
|
||||
return ParseResult(Integer::Constants::Ones);
|
||||
event_node->thread_blocker.block_with_timeout_ms(start_ms + timeout->value - current_ms);
|
||||
event_node->thread_blocker.block_with_timeout_ms(start_ms + timeout_value - current_ms);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <kernel/ACPI/AML/Buffer.h>
|
||||
#include <kernel/ACPI/AML/Bytes.h>
|
||||
#include <kernel/ACPI/AML/Integer.h>
|
||||
#include <kernel/ACPI/AML/Node.h>
|
||||
#include <kernel/ACPI/AML/ParseContext.h>
|
||||
#include <kernel/ACPI/AML/String.h>
|
||||
|
||||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
@ -25,13 +26,14 @@ 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()->as_integer(): BAN::RefPtr<AML::Integer>();
|
||||
if (!source_node)
|
||||
auto conv_node = source_result.node() ? source_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!conv_node)
|
||||
{
|
||||
AML_ERROR("UnaryOp source not integer");
|
||||
AML_ERROR("UnaryOp source not integer, type {}", static_cast<uint8_t>(source_result.node()->type));
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
auto source_node = static_cast<AML::Integer*>(conv_node.ptr());
|
||||
if (source_node->constant)
|
||||
{
|
||||
AML_ERROR("UnaryOp source is constant");
|
||||
|
@ -48,18 +50,23 @@ namespace Kernel::ACPI::AML
|
|||
{
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
|
||||
auto node_result = AML::parse_object(context);
|
||||
if (!node_result.success())
|
||||
auto source_result = AML::parse_object(context);
|
||||
if (!source_result.success())
|
||||
return ParseResult::Failure;
|
||||
|
||||
auto value = node_result.node() ? node_result.node()->as_integer() : BAN::RefPtr<AML::Integer>();
|
||||
if (!value)
|
||||
auto conv_node = source_result.node() ? source_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!conv_node)
|
||||
{
|
||||
AML_ERROR("UnaryOp source not integer, type {}", static_cast<uint8_t>(source_result.node()->type));
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
auto source_node = static_cast<AML::Integer*>(conv_node.ptr());
|
||||
if (!source_node)
|
||||
{
|
||||
AML_ERROR("Logical NotOp source is not integer");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
auto result = value->value ? Integer::Constants::Zero : Integer::Constants::Ones;
|
||||
auto result = source_node->value ? Integer::Constants::Zero : Integer::Constants::Ones;
|
||||
return ParseResult(result);
|
||||
}
|
||||
case AML::Byte::AddOp:
|
||||
|
@ -97,21 +104,25 @@ 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::RefPtr<AML::Integer>();
|
||||
if (!lhs_value)
|
||||
auto lhs_conv = lhs_result.node() ? lhs_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!lhs_conv)
|
||||
{
|
||||
AML_ERROR("BinaryOP {2H} LHS not an integer", static_cast<uint8_t>(opcode));
|
||||
AML_ERROR("BinaryOP {2H} LHS not an integer, type {}",
|
||||
static_cast<uint8_t>(opcode),
|
||||
static_cast<uint8_t>(lhs_result.node()->type)
|
||||
);
|
||||
if (lhs_result.node())
|
||||
lhs_result.node()->debug_print(1);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
const auto lhs_value = static_cast<AML::Integer*>(lhs_conv.ptr())->value;
|
||||
|
||||
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::RefPtr<AML::Integer>();
|
||||
if (!rhs_value)
|
||||
auto rhs_conv = rhs_result.node() ? rhs_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!rhs_conv)
|
||||
{
|
||||
AML_ERROR("BinaryOP {2H} RHS not an integer", static_cast<uint8_t>(opcode));
|
||||
if (rhs_result.node())
|
||||
|
@ -119,12 +130,14 @@ namespace Kernel::ACPI::AML
|
|||
AML_DEBUG_PRINTLN("");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
const auto rhs_value = static_cast<AML::Integer*>(rhs_conv.ptr())->value;
|
||||
|
||||
if (context.aml_data.size() < 1)
|
||||
{
|
||||
AML_ERROR("BinaryOP {2H} missing target", static_cast<uint8_t>(opcode));
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> target_node;
|
||||
if (context.aml_data[0] == 0x00)
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
|
@ -159,9 +172,7 @@ namespace Kernel::ACPI::AML
|
|||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
uint64_t result = func(lhs_value->value, rhs_value->value);
|
||||
auto result_node = MUST(BAN::RefPtr<AML::Integer>::create(result));
|
||||
|
||||
auto result_node = MUST(BAN::RefPtr<AML::Integer>::create(func(lhs_value, rhs_value)));
|
||||
if (target_node && !target_node->store(result_node))
|
||||
{
|
||||
AML_ERROR("BinaryOp {2H} failed to store result", static_cast<uint8_t>(opcode));
|
||||
|
@ -176,10 +187,26 @@ namespace Kernel::ACPI::AML
|
|||
auto opcode = static_cast<AML::Byte>(context.aml_data[0]);
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
|
||||
uint8_t mask;
|
||||
switch (opcode)
|
||||
{
|
||||
case AML::Byte::LAndOp:
|
||||
case AML::Byte::LOrOp:
|
||||
mask = AML::Node::ConvInteger;
|
||||
break;
|
||||
case AML::Byte::LEqualOp:
|
||||
case AML::Byte::LGreaterOp:
|
||||
case AML::Byte::LLessOp:
|
||||
mask = AML::Node::ConvInteger | AML::Node::ConvString | AML::Node::ConvBuffer;
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
auto lhs_result = AML::parse_object(context);
|
||||
if (!lhs_result.success())
|
||||
return ParseResult::Failure;
|
||||
auto lhs_node = lhs_result.node() ? lhs_result.node()->evaluate() : BAN::RefPtr<AML::Node>();
|
||||
auto lhs_node = lhs_result.node() ? lhs_result.node()->convert(mask) : BAN::RefPtr<AML::Node>();
|
||||
if (!lhs_node)
|
||||
{
|
||||
AML_TODO("Logical BinaryOP {2H} LHS evaluated to nothing", static_cast<uint8_t>(opcode));
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace Kernel::ACPI::AML
|
|||
uint8_t access_length = 0;
|
||||
};
|
||||
|
||||
struct FieldElement : public NamedObject
|
||||
struct FieldElement final : public AML::NamedObject
|
||||
{
|
||||
uint64_t bit_offset;
|
||||
uint64_t bit_count;
|
||||
|
@ -63,14 +63,30 @@ namespace Kernel::ACPI::AML
|
|||
, access_rules(access_rules)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Integer> as_integer() override;
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override
|
||||
{
|
||||
if (mask & AML::Node::ConvInteger)
|
||||
return as_integer();
|
||||
if (mask & AML::Node::ConvBuffer)
|
||||
{
|
||||
AML_TODO("Convert BankFieldElement to Buffer");
|
||||
return {};
|
||||
}
|
||||
if (mask & AML::Node::ConvString)
|
||||
{
|
||||
AML_TODO("Convert BankFieldElement to String");
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<Node> evaluate() override { return as_integer(); }
|
||||
bool store(BAN::RefPtr<Node> source) override;
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<Node> source) override;
|
||||
|
||||
void debug_print(int indent) const override;
|
||||
|
||||
private:
|
||||
BAN::RefPtr<AML::Integer> as_integer();
|
||||
|
||||
BAN::Optional<uint64_t> evaluate_internal();
|
||||
bool store_internal(uint64_t value);
|
||||
|
||||
|
@ -83,7 +99,7 @@ namespace Kernel::ACPI::AML
|
|||
static ParseResult parse(ParseContext& context);
|
||||
};
|
||||
|
||||
struct IndexFieldElement : public NamedObject
|
||||
struct IndexFieldElement final : public AML::NamedObject
|
||||
{
|
||||
uint64_t bit_offset;
|
||||
uint64_t bit_count;
|
||||
|
@ -100,12 +116,30 @@ namespace Kernel::ACPI::AML
|
|||
, access_rules(access_rules)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Integer> as_integer() override;
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override
|
||||
{
|
||||
if (mask & AML::Node::ConvInteger)
|
||||
if (auto node = as_integer())
|
||||
return node;
|
||||
if (mask & AML::Node::ConvBuffer)
|
||||
{
|
||||
AML_TODO("convert BankFieldElement to Buffer");
|
||||
return {};
|
||||
}
|
||||
if (mask & AML::Node::ConvString)
|
||||
{
|
||||
AML_TODO("convert BankFieldElement to String");
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override { return as_integer(); }
|
||||
bool store(BAN::RefPtr<Node> source) override;
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<Node> source) override;
|
||||
|
||||
void debug_print(int indent) const override;
|
||||
|
||||
private:
|
||||
BAN::RefPtr<AML::Integer> as_integer();
|
||||
};
|
||||
|
||||
struct IndexField
|
||||
|
@ -113,7 +147,7 @@ namespace Kernel::ACPI::AML
|
|||
static ParseResult parse(ParseContext& context);
|
||||
};
|
||||
|
||||
struct BankFieldElement : public NamedObject
|
||||
struct BankFieldElement final : public AML::NamedObject
|
||||
{
|
||||
uint64_t bit_offset;
|
||||
uint64_t bit_count;
|
||||
|
@ -131,10 +165,30 @@ namespace Kernel::ACPI::AML
|
|||
, access_rules(access_rules)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<Node> evaluate() override;
|
||||
bool store(BAN::RefPtr<Node> source) override;
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override
|
||||
{
|
||||
if (mask & AML::Node::ConvInteger)
|
||||
if (auto node = as_integer())
|
||||
return node;
|
||||
if (mask & AML::Node::ConvBuffer)
|
||||
{
|
||||
AML_TODO("convert BankFieldElement to Buffer");
|
||||
return {};
|
||||
}
|
||||
if (mask & AML::Node::ConvString)
|
||||
{
|
||||
AML_TODO("convert BankFieldElement to String");
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<Node> source) override;
|
||||
|
||||
void debug_print(int indent) const override;
|
||||
|
||||
private:
|
||||
BAN::RefPtr<AML::Integer> as_integer();
|
||||
};
|
||||
|
||||
struct BankField
|
||||
|
|
|
@ -26,12 +26,13 @@ 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::RefPtr<AML::Integer>();
|
||||
if (!predicate)
|
||||
auto predicate_node = predicate_result.node() ? predicate_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!predicate_node)
|
||||
{
|
||||
AML_ERROR("If predicate is not an integer");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
const auto predicate_value = static_cast<AML::Integer*>(predicate_node.ptr())->value;
|
||||
|
||||
// Else
|
||||
BAN::ConstByteSpan else_pkg;
|
||||
|
@ -43,7 +44,7 @@ namespace Kernel::ACPI::AML
|
|||
return ParseResult::Failure;
|
||||
else_pkg = else_pkg_result.value();
|
||||
}
|
||||
if (predicate->value == 0)
|
||||
if (predicate_value == 0)
|
||||
context.aml_data = else_pkg;
|
||||
|
||||
while (context.aml_data.size() > 0)
|
||||
|
|
|
@ -20,22 +20,32 @@ namespace Kernel::ACPI::AML
|
|||
auto source_result = AML::parse_object(context);
|
||||
if (!source_result.success())
|
||||
return ParseResult::Failure;
|
||||
auto source = source_result.node() ? source_result.node()->evaluate() : BAN::RefPtr<AML::Node>();
|
||||
auto source = source_result.node()
|
||||
? source_result.node()->convert(AML::Node::ConvBuffer | AML::Node::ConvInteger | AML::Node::ConvString)
|
||||
: BAN::RefPtr<AML::Node>();
|
||||
if (!source)
|
||||
{
|
||||
AML_ERROR("IndexOp source is null");
|
||||
AML_ERROR("IndexOp source could not be converted");
|
||||
if (source)
|
||||
{
|
||||
source->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
}
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
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::RefPtr<AML::Integer>();
|
||||
if (!index)
|
||||
auto index_node = source_result.node()
|
||||
? source_result.node()->convert(AML::Node::ConvInteger)
|
||||
: BAN::RefPtr<AML::Node>();
|
||||
if (!index_node)
|
||||
{
|
||||
AML_ERROR("IndexOp index is not an integer");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
const auto index = static_cast<AML::Integer*>(index_node.ptr())->value;
|
||||
|
||||
BAN::RefPtr<AML::Reference> result;
|
||||
switch (source->type)
|
||||
|
@ -43,36 +53,36 @@ namespace Kernel::ACPI::AML
|
|||
case AML::Node::Type::Buffer:
|
||||
{
|
||||
auto buffer = BAN::RefPtr<AML::Buffer>(static_cast<AML::Buffer*>(source.ptr()));
|
||||
if (index->value >= buffer->buffer.size())
|
||||
if (index >= buffer->buffer.size())
|
||||
{
|
||||
AML_ERROR("IndexOp index is out of buffer bounds");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
auto buffer_field = MUST(BAN::RefPtr<BufferField>::create(NameSeg(""_sv), buffer, index->value * 8, 8));
|
||||
auto buffer_field = MUST(BAN::RefPtr<BufferField>::create(NameSeg(""_sv), buffer, index * 8, 8));
|
||||
result = MUST(BAN::RefPtr<AML::Reference>::create(buffer_field));
|
||||
break;
|
||||
}
|
||||
case AML::Node::Type::Package:
|
||||
{
|
||||
auto package = static_cast<AML::Package*>(source.ptr());
|
||||
if (index->value >= package->elements.size())
|
||||
if (index >= 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];
|
||||
result = MUST(BAN::RefPtr<AML::Reference>::create(package_element));
|
||||
break;
|
||||
}
|
||||
case AML::Node::Type::String:
|
||||
{
|
||||
auto string = BAN::RefPtr<AML::String>(static_cast<AML::String*>(source.ptr()));
|
||||
if (index->value >= string->string.size())
|
||||
if (index >= string->string.size())
|
||||
{
|
||||
AML_ERROR("IndexOp index is out of string bounds");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
auto buffer_field = MUST(BAN::RefPtr<BufferField>::create(NameSeg(""_sv), string, index->value * 8, 8));
|
||||
auto buffer_field = MUST(BAN::RefPtr<BufferField>::create(NameSeg(""_sv), string, index * 8, 8));
|
||||
result = MUST(BAN::RefPtr<AML::Reference>::create(buffer_field));
|
||||
break;
|
||||
}
|
||||
|
@ -82,7 +92,7 @@ namespace Kernel::ACPI::AML
|
|||
}
|
||||
|
||||
#if AML_DEBUG_LEVEL >= 2
|
||||
AML_DEBUG_PRINT("Index {}, ", index->value);
|
||||
AML_DEBUG_PRINT("Index {}, ", index);
|
||||
source->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Integer : public Node
|
||||
struct Integer final : public AML::Node
|
||||
{
|
||||
struct Constants
|
||||
{
|
||||
|
@ -31,49 +31,70 @@ namespace Kernel::ACPI::AML
|
|||
|
||||
BAN::Optional<bool> logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop)
|
||||
{
|
||||
auto rhs = node ? node->as_integer() : BAN::RefPtr<AML::Integer>();
|
||||
if (!rhs)
|
||||
auto rhs_node = node ? node->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!rhs_node)
|
||||
{
|
||||
AML_ERROR("Integer logical compare RHS is not integer");
|
||||
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;
|
||||
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> as_integer() override { return this; }
|
||||
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 {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<Node> copy() override { return MUST(BAN::RefPtr<Integer>::create(value)); }
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
bool store(BAN::RefPtr<AML::Node> store_node) override
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> store_node) override
|
||||
{
|
||||
if (constant)
|
||||
{
|
||||
AML_ERROR("Cannot store to constant integer");
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
auto store_value = store_node->as_integer();
|
||||
if (!store_value)
|
||||
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 false;
|
||||
return {};
|
||||
}
|
||||
value = store_value->value;
|
||||
return true;
|
||||
value = static_cast<AML::Integer*>(conv_node.ptr())->value;
|
||||
return MUST(BAN::RefPtr<AML::Integer>::create(value));
|
||||
}
|
||||
|
||||
static ParseResult parse(BAN::ConstByteSpan& aml_data)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Method : public AML::Scope
|
||||
struct Method final : public AML::Scope
|
||||
{
|
||||
Kernel::Mutex mutex;
|
||||
uint8_t arg_count;
|
||||
|
@ -27,6 +27,8 @@ namespace Kernel::ACPI::AML
|
|||
, sync_level(sync_level)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
static ParseResult parse(AML::ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
|
@ -98,13 +100,13 @@ namespace Kernel::ACPI::AML
|
|||
ParseContext context;
|
||||
context.aml_data = term_list;
|
||||
context.scope = scope;
|
||||
context.method_args[0] = MUST(BAN::RefPtr<AML::Register>::create(arg0));
|
||||
context.method_args[1] = MUST(BAN::RefPtr<AML::Register>::create(arg1));
|
||||
context.method_args[2] = MUST(BAN::RefPtr<AML::Register>::create(arg2));
|
||||
context.method_args[3] = MUST(BAN::RefPtr<AML::Register>::create(arg3));
|
||||
context.method_args[4] = MUST(BAN::RefPtr<AML::Register>::create(arg4));
|
||||
context.method_args[5] = MUST(BAN::RefPtr<AML::Register>::create(arg5));
|
||||
context.method_args[6] = MUST(BAN::RefPtr<AML::Register>::create(arg6));
|
||||
context.method_args[0] = MUST(BAN::RefPtr<AML::Register>::create(arg0 && arg0->type == AML::Node::Type::Register ? static_cast<AML::Register*>(arg0.ptr())->value : arg0));
|
||||
context.method_args[1] = MUST(BAN::RefPtr<AML::Register>::create(arg1 && arg1->type == AML::Node::Type::Register ? static_cast<AML::Register*>(arg1.ptr())->value : arg1));
|
||||
context.method_args[2] = MUST(BAN::RefPtr<AML::Register>::create(arg2 && arg2->type == AML::Node::Type::Register ? static_cast<AML::Register*>(arg2.ptr())->value : arg2));
|
||||
context.method_args[3] = MUST(BAN::RefPtr<AML::Register>::create(arg3 && arg3->type == AML::Node::Type::Register ? static_cast<AML::Register*>(arg3.ptr())->value : arg3));
|
||||
context.method_args[4] = MUST(BAN::RefPtr<AML::Register>::create(arg4 && arg4->type == AML::Node::Type::Register ? static_cast<AML::Register*>(arg4.ptr())->value : arg4));
|
||||
context.method_args[5] = MUST(BAN::RefPtr<AML::Register>::create(arg5 && arg5->type == AML::Node::Type::Register ? static_cast<AML::Register*>(arg5.ptr())->value : arg5));
|
||||
context.method_args[6] = MUST(BAN::RefPtr<AML::Register>::create(arg6 && arg6->type == AML::Node::Type::Register ? static_cast<AML::Register*>(arg6.ptr())->value : arg6));
|
||||
context.sync_stack = BAN::move(current_sync_stack);
|
||||
for (auto& local : context.method_locals)
|
||||
local = MUST(BAN::RefPtr<AML::Register>::create());
|
||||
|
@ -142,8 +144,8 @@ namespace Kernel::ACPI::AML
|
|||
}
|
||||
}
|
||||
|
||||
if (return_value.has_value() && return_value.value())
|
||||
return_value = return_value.value()->evaluate();
|
||||
if (return_value.has_value() && return_value.value() && return_value.value()->type == AML::Node::Type::Register)
|
||||
return_value.value() = static_cast<AML::Register*>(return_value.value().ptr())->value;
|
||||
|
||||
while (!context.created_objects.empty())
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Mutex : public AML::NamedObject
|
||||
struct Mutex final : public AML::NamedObject
|
||||
{
|
||||
Kernel::Mutex mutex;
|
||||
uint8_t sync_level;
|
||||
|
@ -20,6 +20,8 @@ namespace Kernel::ACPI::AML
|
|||
, sync_level(sync_level)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
static ParseResult parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 2);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct NamedObject : public Node
|
||||
struct NamedObject : public AML::Node
|
||||
{
|
||||
BAN::RefPtr<NamedObject> parent;
|
||||
NameSeg name;
|
||||
|
@ -14,7 +14,7 @@ namespace Kernel::ACPI::AML
|
|||
NamedObject(Node::Type type, NameSeg name) : Node(type), name(name) {}
|
||||
};
|
||||
|
||||
struct Name : public NamedObject
|
||||
struct Name final : public AML::NamedObject
|
||||
{
|
||||
BAN::RefPtr<AML::Node> object;
|
||||
|
||||
|
@ -22,21 +22,15 @@ namespace Kernel::ACPI::AML
|
|||
: NamedObject(Node::Type::Name, name), object(BAN::move(object))
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Buffer> as_buffer() override;
|
||||
BAN::RefPtr<AML::Integer> as_integer() override;
|
||||
BAN::RefPtr<AML::String> as_string() override;
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override
|
||||
{
|
||||
ASSERT(object);
|
||||
return object->evaluate();
|
||||
}
|
||||
|
||||
bool store(BAN::RefPtr<AML::Node> node) override
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> node) override
|
||||
{
|
||||
ASSERT(object);
|
||||
if (object->type == AML::Node::Type::Reference)
|
||||
return object->store(node);
|
||||
object = node;
|
||||
return true;
|
||||
return node;
|
||||
}
|
||||
|
||||
static ParseResult parse(ParseContext& context);
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Namespace : public AML::Scope
|
||||
struct Namespace final : public AML::Scope
|
||||
{
|
||||
static BAN::RefPtr<AML::Namespace> create_root_namespace();
|
||||
static BAN::RefPtr<AML::Namespace> root_namespace();
|
||||
static BAN::RefPtr<AML::Node> debug_node;
|
||||
|
||||
|
@ -35,7 +36,8 @@ namespace Kernel::ACPI::AML
|
|||
|
||||
Namespace(NameSeg name) : AML::Scope(Node::Type::Namespace, name) {}
|
||||
|
||||
static BAN::RefPtr<AML::Namespace> create_root_namespace();
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
bool parse(const SDTHeader& header);
|
||||
|
||||
void debug_print(int indent) const override;
|
||||
|
|
|
@ -17,8 +17,18 @@ namespace Kernel::ACPI::AML
|
|||
{
|
||||
static uint64_t total_node_count;
|
||||
|
||||
enum class Type
|
||||
enum Conversion : uint8_t
|
||||
{
|
||||
ConvBuffer = 1 << 0,
|
||||
ConvBufferField = 1 << 1,
|
||||
ConvFieldUnit = 1 << 2,
|
||||
ConvInteger = 1 << 3,
|
||||
ConvString = 1 << 4,
|
||||
};
|
||||
|
||||
enum class Type : uint8_t
|
||||
{
|
||||
None,
|
||||
Alias,
|
||||
BankFieldElement,
|
||||
Buffer,
|
||||
|
@ -50,14 +60,9 @@ namespace Kernel::ACPI::AML
|
|||
|
||||
virtual bool is_scope() const { return false; }
|
||||
|
||||
virtual BAN::RefPtr<Node> copy() { return this; }
|
||||
|
||||
[[nodiscard]] virtual BAN::RefPtr<AML::Buffer> as_buffer();
|
||||
[[nodiscard]] virtual BAN::RefPtr<AML::Integer> as_integer();
|
||||
[[nodiscard]] virtual BAN::RefPtr<AML::String> as_string();
|
||||
|
||||
[[nodiscard]] virtual BAN::RefPtr<AML::Node> evaluate() { AML_TODO("evaluate, type {}", static_cast<uint8_t>(type)); return nullptr; }
|
||||
[[nodiscard]] virtual bool store(BAN::RefPtr<AML::Node>) { AML_TODO("store, type {}", static_cast<uint8_t>(type)); return false; }
|
||||
[[nodiscard]] virtual BAN::RefPtr<AML::Node> convert(uint8_t mask) = 0;
|
||||
[[nodiscard]] virtual BAN::RefPtr<Node> copy() { return this; }
|
||||
[[nodiscard]] virtual BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node>) { AML_TODO("store, type {}", static_cast<uint8_t>(type)); return {}; }
|
||||
|
||||
virtual void debug_print(int indent) const = 0;
|
||||
};
|
||||
|
|
|
@ -29,12 +29,13 @@ 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::RefPtr<AML::Integer>();
|
||||
if (!value)
|
||||
auto value_node = value_result.node() ? value_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!value_node)
|
||||
{
|
||||
AML_ERROR("Notify value is not an integer");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
const auto value = static_cast<AML::Integer*>(value_node.ptr())->value;
|
||||
|
||||
BAN::StringView object_type_sv;
|
||||
BAN::StringView object_name_sv;
|
||||
|
@ -58,7 +59,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);
|
||||
return ParseResult::Success;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace Kernel::ACPI::AML
|
|||
|
||||
struct PackageElement;
|
||||
|
||||
struct Package : public AML::Node
|
||||
struct Package final : public AML::Node
|
||||
{
|
||||
BAN::Vector<BAN::RefPtr<PackageElement>> elements;
|
||||
AML::NameString scope;
|
||||
|
@ -22,16 +22,13 @@ namespace Kernel::ACPI::AML
|
|||
, scope(scope)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
static ParseResult parse(AML::ParseContext& context);
|
||||
virtual void debug_print(int indent) const override;
|
||||
};
|
||||
|
||||
struct PackageElement : public AML::Node
|
||||
struct PackageElement final : public AML::Node
|
||||
{
|
||||
BAN::RefPtr<AML::Package> parent;
|
||||
BAN::RefPtr<AML::Node> element;
|
||||
|
@ -82,7 +79,19 @@ namespace Kernel::ACPI::AML
|
|||
return true;
|
||||
}
|
||||
|
||||
bool store(BAN::RefPtr<AML::Node> node) override
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
AML_ERROR("Trying to store into uninitialized PackageElement");
|
||||
return {};
|
||||
}
|
||||
if (!resolved && !resolve())
|
||||
return {};
|
||||
return element->convert(mask);
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> node) override
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
|
@ -94,31 +103,7 @@ namespace Kernel::ACPI::AML
|
|||
if (element->type == AML::Node::Type::Reference)
|
||||
return element->store(node);
|
||||
element = node->copy();
|
||||
return true;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Integer> as_integer() override
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
AML_ERROR("Trying to evaluate uninitialized PackageElement");
|
||||
return {};
|
||||
}
|
||||
if (!resolved && !resolve())
|
||||
return {};
|
||||
return element->as_integer();
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
AML_ERROR("Trying to evaluate uninitialized PackageElement");
|
||||
return {};
|
||||
}
|
||||
if (!resolved && !resolve())
|
||||
return {};
|
||||
return element->evaluate();
|
||||
return element;
|
||||
}
|
||||
|
||||
static ParseResult parse(AML::ParseContext& context, BAN::RefPtr<AML::Package> package)
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct PowerResource : public AML::Scope
|
||||
struct PowerResource final : public AML::Scope
|
||||
{
|
||||
uint8_t system_level;
|
||||
uint16_t resource_order;
|
||||
|
@ -20,6 +20,8 @@ namespace Kernel::ACPI::AML
|
|||
, resource_order(resource_order)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
static ParseResult parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 2);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Processor : public AML::Scope
|
||||
struct Processor final : public AML::Scope
|
||||
{
|
||||
uint8_t id;
|
||||
uint32_t pblk_addr;
|
||||
|
@ -22,6 +22,8 @@ namespace Kernel::ACPI::AML
|
|||
, pblk_len(pblk_len)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
static ParseResult parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 2);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Reference : public AML::Node
|
||||
struct Reference final : public AML::Node
|
||||
{
|
||||
BAN::RefPtr<AML::Node> node;
|
||||
|
||||
|
@ -21,24 +21,22 @@ namespace Kernel::ACPI::AML
|
|||
ASSERT(node);
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Integer> as_integer() override
|
||||
{
|
||||
if (node)
|
||||
return node->as_integer();
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
bool store(BAN::RefPtr<AML::Node> value) override
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
AML_ERROR("Storing to null reference");
|
||||
return false;
|
||||
AML_ERROR("Trying to convert null Reference");
|
||||
return {};
|
||||
}
|
||||
return node->convert(mask);
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> value) override
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
AML_ERROR("Storing to null Reference");
|
||||
return {};
|
||||
}
|
||||
return node->store(value);
|
||||
}
|
||||
|
@ -79,6 +77,8 @@ namespace Kernel::ACPI::AML
|
|||
if (!parse_result.success())
|
||||
return ParseResult::Failure;
|
||||
object = parse_result.node();
|
||||
if (object && object->type == AML::Node::Type::Register)
|
||||
object = static_cast<AML::Register*>(object.ptr())->value;
|
||||
}
|
||||
|
||||
if (!conditional)
|
||||
|
@ -96,18 +96,26 @@ namespace Kernel::ACPI::AML
|
|||
return ParseResult(reference);
|
||||
}
|
||||
|
||||
if (context.aml_data.size() >= 1 && context.aml_data[0] != 0x00)
|
||||
if (context.aml_data.size() < 1)
|
||||
{
|
||||
AML_ERROR("CondRefOf missing target");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> target_node;
|
||||
if (context.aml_data[0] == 0x00)
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
else
|
||||
{
|
||||
auto target_result = AML::parse_object(context);
|
||||
if (!target_result.success())
|
||||
return ParseResult::Failure;
|
||||
auto target_node = target_result.node();
|
||||
target_node = target_result.node();
|
||||
if (!target_node)
|
||||
{
|
||||
AML_ERROR("CondRefOf failed to resolve target");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
target_node->store(MUST(BAN::RefPtr<Reference>::create(object)));
|
||||
}
|
||||
|
||||
#if AML_DEBUG_LEVEL >= 2
|
||||
|
@ -119,8 +127,16 @@ namespace Kernel::ACPI::AML
|
|||
AML_DEBUG_PRINTLN("");
|
||||
#endif
|
||||
|
||||
auto return_value = object ? Integer::Constants::Ones : Integer::Constants::Zero;
|
||||
return AML::ParseResult(return_value);
|
||||
if (!object)
|
||||
return AML::ParseResult(Integer::Constants::Zero);
|
||||
|
||||
if (target_node && !target_node->store(object))
|
||||
{
|
||||
AML_ERROR("CondRefOf failed to store into target");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
return AML::ParseResult(Integer::Constants::Ones);
|
||||
}
|
||||
|
||||
static ParseResult parse_dereference(ParseContext& context)
|
||||
|
@ -144,18 +160,20 @@ namespace Kernel::ACPI::AML
|
|||
auto parse_result = AML::parse_object(context);
|
||||
if (!parse_result.success())
|
||||
return ParseResult::Failure;
|
||||
auto object = parse_result.node() ? parse_result.node()->evaluate() : BAN::RefPtr<AML::Node>();
|
||||
if (!object || object->type != AML::Node::Type::Reference)
|
||||
auto node = parse_result.node();
|
||||
if (node && node->type == AML::Node::Type::Register)
|
||||
node = static_cast<AML::Register*>(node.ptr())->value;
|
||||
if (!node || node->type != AML::Node::Type::Reference)
|
||||
{
|
||||
AML_TODO("DerefOf source is not a Reference, but a {}", object ? static_cast<uint8_t>(object->type) : 999);
|
||||
AML_TODO("DerefOf source is not a Reference, but a {}", node ? static_cast<uint8_t>(node->type) : 999);
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
#if AML_DEBUG_LEVEL >= 2
|
||||
AML_DEBUG_PRINT("DerefOf ");
|
||||
object->debug_print(0);
|
||||
node->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
#endif
|
||||
return ParseResult(static_cast<Reference*>(object.ptr())->node);
|
||||
return ParseResult(static_cast<Reference*>(node.ptr())->node);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,6 +182,7 @@ namespace Kernel::ACPI::AML
|
|||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINTLN("Reference {");
|
||||
node->debug_print(indent + 1);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("}");
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct OpRegion : public NamedObject
|
||||
struct OpRegion final : public AML::NamedObject
|
||||
{
|
||||
using RegionSpace = GAS::AddressSpaceID;
|
||||
RegionSpace region_space;
|
||||
|
@ -24,6 +24,8 @@ namespace Kernel::ACPI::AML
|
|||
, region_length(region_length)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
static ParseResult parse(AML::ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() > 2);
|
||||
|
@ -43,8 +45,10 @@ namespace Kernel::ACPI::AML
|
|||
auto offset_result = AML::parse_object(context);
|
||||
if (!offset_result.success())
|
||||
return ParseResult::Failure;
|
||||
auto offset = offset_result.node()->as_integer();
|
||||
if (!offset)
|
||||
auto offset_node = offset_result.node()
|
||||
? offset_result.node()->convert(AML::Node::ConvInteger)
|
||||
: BAN::RefPtr<AML::Node>();
|
||||
if (!offset_node)
|
||||
{
|
||||
AML_ERROR("OpRegion offset must be an integer");
|
||||
return ParseResult::Failure;
|
||||
|
@ -53,18 +57,23 @@ namespace Kernel::ACPI::AML
|
|||
auto length_result = AML::parse_object(context);
|
||||
if (!length_result.success())
|
||||
return ParseResult::Failure;
|
||||
auto length = length_result.node()->as_integer();
|
||||
if (!length)
|
||||
auto length_node = length_result.node()
|
||||
? length_result.node()->convert(AML::Node::ConvInteger)
|
||||
: BAN::RefPtr<AML::Node>();
|
||||
if (!length_node)
|
||||
{
|
||||
AML_ERROR("OpRegion length must be an integer");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
const auto offset = static_cast<AML::Integer*>(offset_node.ptr())->value;
|
||||
const auto length = static_cast<AML::Integer*>(length_node.ptr())->value;
|
||||
|
||||
auto op_region = MUST(BAN::RefPtr<OpRegion>::create(
|
||||
name->path.back(),
|
||||
region_space,
|
||||
offset->value,
|
||||
length->value
|
||||
offset,
|
||||
length
|
||||
));
|
||||
|
||||
if (!Namespace::root_namespace()->add_named_object(context, name.value(), op_region))
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct Register : public AML::Node
|
||||
struct Register final : public AML::Node
|
||||
{
|
||||
BAN::RefPtr<AML::Node> value;
|
||||
|
||||
|
@ -17,30 +17,22 @@ namespace Kernel::ACPI::AML
|
|||
, value(value)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Buffer> as_buffer() override;
|
||||
BAN::RefPtr<AML::Integer> as_integer() override;
|
||||
BAN::RefPtr<AML::String> as_string() override;
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override
|
||||
{
|
||||
if (value)
|
||||
return value->evaluate();
|
||||
return {};
|
||||
if (!value)
|
||||
{
|
||||
AML_ERROR("Trying to convert null Register");
|
||||
return {};
|
||||
}
|
||||
return value->convert(mask);
|
||||
}
|
||||
|
||||
bool 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);
|
||||
|
||||
auto evaluated = source->evaluate();
|
||||
if (!evaluated)
|
||||
{
|
||||
AML_ERROR("Failed to evaluate source for store");
|
||||
return false;
|
||||
}
|
||||
value = evaluated->copy();
|
||||
return true;
|
||||
value = source->copy();
|
||||
return value;
|
||||
}
|
||||
|
||||
void debug_print(int indent) const override
|
||||
|
|
|
@ -21,30 +21,34 @@ namespace Kernel::ACPI::AML
|
|||
auto object_result = AML::parse_object(context);
|
||||
if (!object_result.success())
|
||||
return ParseResult::Failure;
|
||||
auto object = object_result.node()->evaluate();
|
||||
if (object && object->type == AML::Node::Type::Reference)
|
||||
object = static_cast<AML::Reference*>(object.ptr())->node->evaluate();
|
||||
if (!object)
|
||||
auto object_node = object_result.node();
|
||||
if (!object_node)
|
||||
{
|
||||
AML_ERROR("SizeOf object is null");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
if (object_node->type != AML::Node::Type::Package)
|
||||
object_node = object_node->convert(AML::Node::ConvBuffer | AML::Node::ConvString);
|
||||
if (!object_node)
|
||||
{
|
||||
AML_ERROR("SizeOf object is not Buffer, String or Package");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
uint64_t size = 0;
|
||||
switch (object->type)
|
||||
switch (object_node->type)
|
||||
{
|
||||
case AML::Node::Type::Buffer:
|
||||
size = static_cast<AML::Buffer*>(object.ptr())->buffer.size();
|
||||
size = static_cast<AML::Buffer*>(object_node.ptr())->buffer.size();
|
||||
break;
|
||||
case AML::Node::Type::String:
|
||||
size = static_cast<AML::String*>(object.ptr())->string.size();
|
||||
size = static_cast<AML::String*>(object_node.ptr())->string.size();
|
||||
break;
|
||||
case AML::Node::Type::Package:
|
||||
size = static_cast<AML::Package*>(object.ptr())->elements.size();
|
||||
size = static_cast<AML::Package*>(object_node.ptr())->elements.size();
|
||||
break;
|
||||
default:
|
||||
AML_ERROR("SizeOf object is not a buffer, string or package ({})", static_cast<uint8_t>(object->type));
|
||||
return ParseResult::Failure;
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
return ParseResult(MUST(BAN::RefPtr<Integer>::create(size)));
|
||||
|
|
|
@ -19,18 +19,22 @@ 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::RefPtr<AML::Integer>();
|
||||
if (!sleep_time)
|
||||
auto sleep_time_node = sleep_time_result.node()
|
||||
? sleep_time_result.node()->convert(AML::Node::ConvInteger)
|
||||
: BAN::RefPtr<AML::Node>();
|
||||
if (!sleep_time_node)
|
||||
{
|
||||
AML_ERROR("Sleep time cannot be evaluated to an integer");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
const auto sleep_time_value = static_cast<AML::Integer*>(sleep_time_node.ptr())->value;
|
||||
|
||||
#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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,10 +17,10 @@ namespace Kernel::ACPI::AML
|
|||
auto source_result = AML::parse_object(context);
|
||||
if (!source_result.success())
|
||||
return ParseResult::Failure;
|
||||
auto source = source_result.node() ? source_result.node()->evaluate() : BAN::RefPtr<AML::Node>();
|
||||
auto source = source_result.node();
|
||||
if (!source)
|
||||
{
|
||||
AML_ERROR("Store source cannot be evaluated");
|
||||
AML_ERROR("Store source is null");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct String : public AML::Node
|
||||
struct String final : public AML::Node
|
||||
{
|
||||
BAN::Vector<uint8_t> string;
|
||||
|
||||
|
@ -22,12 +22,7 @@ namespace Kernel::ACPI::AML
|
|||
|
||||
BAN::Optional<bool> logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop);
|
||||
|
||||
BAN::RefPtr<AML::Buffer> as_buffer() override;
|
||||
|
||||
BAN::RefPtr<AML::Node> evaluate() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t mask) override;
|
||||
|
||||
BAN::StringView string_view() const
|
||||
{
|
||||
|
@ -41,6 +36,9 @@ namespace Kernel::ACPI::AML
|
|||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("String \"{}\"", string_view());
|
||||
}
|
||||
|
||||
private:
|
||||
BAN::RefPtr<AML::Buffer> as_buffer();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -9,12 +9,14 @@
|
|||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
struct ThermalZone : public AML::Scope
|
||||
struct ThermalZone final : public AML::Scope
|
||||
{
|
||||
ThermalZone(NameSeg name)
|
||||
: Scope(Node::Type::ThermalZone, name)
|
||||
{}
|
||||
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
|
||||
static ParseResult parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 2);
|
||||
|
|
|
@ -29,14 +29,16 @@ 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::RefPtr<AML::Integer>();
|
||||
if (!predicate)
|
||||
auto predicate_node = predicate_result.node()
|
||||
? predicate_result.node()->convert(AML::Node::ConvInteger)
|
||||
: BAN::RefPtr<AML::Node>();
|
||||
if (!predicate_node)
|
||||
{
|
||||
AML_ERROR("While predicate is not an integer");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
if (!predicate->value)
|
||||
if (!static_cast<AML::Integer*>(predicate_node.ptr())->value)
|
||||
break;
|
||||
|
||||
while (context.aml_data.size() > 0)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <BAN/StringView.h>
|
||||
#include <kernel/ACPI/ACPI.h>
|
||||
#include <kernel/ACPI/AML.h>
|
||||
#include <kernel/ACPI/AML/Alias.h>
|
||||
#include <kernel/ACPI/AML/Device.h>
|
||||
#include <kernel/ACPI/AML/Field.h>
|
||||
#include <kernel/ACPI/AML/Integer.h>
|
||||
|
@ -144,10 +145,10 @@ acpi_release_global_lock:
|
|||
auto field_element = MUST(BAN::RefPtr<AML::FieldElement>::create(""_sv, register_bit_offset, register_bit_width, field_rules));
|
||||
field_element->op_region = op_region;
|
||||
|
||||
auto result = field_element->as_integer();
|
||||
auto result = field_element->convert(AML::Node::ConvInteger);
|
||||
if (!result)
|
||||
return {};
|
||||
return result->value;
|
||||
return static_cast<AML::Integer*>(result.ptr())->value;
|
||||
}
|
||||
|
||||
bool GAS::write(uint64_t value)
|
||||
|
@ -168,7 +169,7 @@ acpi_release_global_lock:
|
|||
auto field_element = MUST(BAN::RefPtr<AML::FieldElement>::create(""_sv, register_bit_offset, register_bit_width, field_rules));
|
||||
field_element->op_region = op_region;
|
||||
|
||||
return field_element->store(MUST(BAN::RefPtr<AML::Integer>::create(value)));
|
||||
return !!field_element->store(MUST(BAN::RefPtr<AML::Integer>::create(value)));
|
||||
}
|
||||
|
||||
enum PM1Event : uint16_t
|
||||
|
@ -494,7 +495,25 @@ acpi_release_global_lock:
|
|||
dwarnln("\\_S5 not found");
|
||||
return;
|
||||
}
|
||||
auto s5_evaluated = s5_object->evaluate();
|
||||
BAN::RefPtr<AML::Node> s5_evaluated = s5_object;
|
||||
while (true)
|
||||
{
|
||||
bool done = false;
|
||||
switch (s5_evaluated->type)
|
||||
{
|
||||
case AML::Node::Type::Alias:
|
||||
s5_evaluated = static_cast<AML::Alias*>(s5_evaluated.ptr())->target;
|
||||
break;
|
||||
case AML::Node::Type::Name:
|
||||
s5_evaluated = static_cast<AML::Name*>(s5_evaluated.ptr())->object;
|
||||
break;
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
if (done)
|
||||
break;
|
||||
}
|
||||
if (!s5_evaluated)
|
||||
{
|
||||
dwarnln("Failed to evaluate \\_S5");
|
||||
|
@ -512,9 +531,9 @@ acpi_release_global_lock:
|
|||
return;
|
||||
}
|
||||
|
||||
auto slp_typa = s5_package->elements[0]->as_integer();
|
||||
auto slp_typb = s5_package->elements[1]->as_integer();
|
||||
if (!slp_typa || !slp_typb)
|
||||
auto slp_typa_node = s5_package->elements[0]->convert(AML::Node::ConvInteger);
|
||||
auto slp_typb_node = s5_package->elements[1]->convert(AML::Node::ConvInteger);
|
||||
if (!slp_typa_node || !slp_typb_node)
|
||||
{
|
||||
dwarnln("Failed to get SLP_TYPx values");
|
||||
return;
|
||||
|
@ -525,9 +544,12 @@ acpi_release_global_lock:
|
|||
|
||||
dprintln("Entering sleep state S5");
|
||||
|
||||
const auto slp_typa_value = static_cast<AML::Integer*>(slp_typa_node.ptr())->value;
|
||||
const auto slp_typb_value = static_cast<AML::Integer*>(slp_typb_node.ptr())->value;
|
||||
|
||||
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 +557,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);
|
||||
}
|
||||
|
|
|
@ -492,13 +492,14 @@ namespace Kernel::ACPI
|
|||
return MUST(BAN::RefPtr<Integer>::create(result.value()));
|
||||
}
|
||||
|
||||
bool AML::FieldElement::store(BAN::RefPtr<AML::Node> source)
|
||||
BAN::RefPtr<AML::Node> AML::FieldElement::store(BAN::RefPtr<AML::Node> source)
|
||||
{
|
||||
auto source_integer = source->as_integer();
|
||||
ASSERT(source);
|
||||
auto source_integer = source->convert(AML::Node::ConvInteger);
|
||||
if (!source_integer)
|
||||
{
|
||||
AML_TODO("FieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type));
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
op_region->mutex.lock();
|
||||
|
@ -510,7 +511,9 @@ namespace Kernel::ACPI
|
|||
ACPI::release_global_lock();
|
||||
});
|
||||
|
||||
return store_internal(source_integer->value);
|
||||
if (!store_internal(static_cast<AML::Integer*>(source_integer.ptr())->value))
|
||||
return {};
|
||||
return source_integer;
|
||||
}
|
||||
|
||||
void AML::FieldElement::debug_print(int indent) const
|
||||
|
@ -626,28 +629,30 @@ namespace Kernel::ACPI
|
|||
return MUST(BAN::RefPtr<Integer>::create(result.value()));
|
||||
}
|
||||
|
||||
bool AML::IndexFieldElement::store(BAN::RefPtr<Node> source)
|
||||
BAN::RefPtr<AML::Node> AML::IndexFieldElement::store(BAN::RefPtr<Node> source)
|
||||
{
|
||||
if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal)
|
||||
{
|
||||
AML_TODO("FieldElement with access attribute {}", static_cast<uint8_t>(access_rules.access_attrib));
|
||||
return {};
|
||||
}
|
||||
auto source_integer = source->as_integer();
|
||||
|
||||
ASSERT(source);
|
||||
auto source_integer = source->convert(AML::Node::ConvInteger);
|
||||
if (!source_integer)
|
||||
{
|
||||
AML_TODO("IndexFieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type));
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto access_size = determine_access_size(access_rules.access_type);
|
||||
if (!access_size.has_value())
|
||||
return false;
|
||||
return {};
|
||||
|
||||
if (access_size.value() > data_element->bit_count)
|
||||
{
|
||||
AML_ERROR("IndexFieldElement write_field with access size {} > data element bit count {}", access_size.value(), data_element->bit_count);
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto read_func = [&](uint64_t byte_offset) -> BAN::Optional<uint64_t> {
|
||||
|
@ -657,7 +662,7 @@ namespace Kernel::ACPI
|
|||
};
|
||||
auto write_func = [&](uint64_t byte_offset, uint64_t value) -> bool {
|
||||
if (!index_element->store_internal(byte_offset))
|
||||
return false;
|
||||
return {};
|
||||
return data_element->store_internal(value);
|
||||
};
|
||||
|
||||
|
@ -670,10 +675,10 @@ 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))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
const auto source_value = static_cast<AML::Integer*>(source_integer.ptr())->value;
|
||||
if (!perform_write_general(0, bit_count, bit_offset, access_size.value(), source_value, access_rules.update_rule, read_func, write_func))
|
||||
return {};
|
||||
return source_integer;
|
||||
}
|
||||
|
||||
void AML::IndexFieldElement::debug_print(int indent) const
|
||||
|
@ -734,8 +739,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::RefPtr<AML::Integer>();
|
||||
if (!bank_value)
|
||||
auto bank_value_node = bank_value_result.node() ? bank_value_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!bank_value_node)
|
||||
{
|
||||
AML_ERROR("BankField BankValue is not an integer");
|
||||
return ParseResult::Failure;
|
||||
|
@ -756,11 +761,12 @@ namespace Kernel::ACPI
|
|||
if (!parse_field_element(field_context))
|
||||
return ParseResult::Failure;
|
||||
|
||||
const auto bank_value = static_cast<AML::Integer*>(bank_value_node.ptr())->value;
|
||||
for (auto& [_, element] : field_context.elements)
|
||||
{
|
||||
element->op_region = static_cast<OpRegion*>(op_region.ptr());
|
||||
element->bank_selector = static_cast<FieldElement*>(bank_selector.ptr());
|
||||
element->bank_value = bank_value->value;
|
||||
element->bank_value = bank_value;
|
||||
|
||||
NameString element_name;
|
||||
MUST(element_name.path.push_back(element->name));
|
||||
|
@ -776,7 +782,7 @@ namespace Kernel::ACPI
|
|||
return ParseResult::Success;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> AML::BankFieldElement::evaluate()
|
||||
BAN::RefPtr<AML::Integer> AML::BankFieldElement::as_integer()
|
||||
{
|
||||
if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal)
|
||||
{
|
||||
|
@ -812,7 +818,7 @@ namespace Kernel::ACPI
|
|||
return MUST(BAN::RefPtr<Integer>::create(result.value()));
|
||||
}
|
||||
|
||||
bool AML::BankFieldElement::store(BAN::RefPtr<AML::Node> source)
|
||||
BAN::RefPtr<AML::Node> AML::BankFieldElement::store(BAN::RefPtr<AML::Node> source)
|
||||
{
|
||||
if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal)
|
||||
{
|
||||
|
@ -820,16 +826,17 @@ namespace Kernel::ACPI
|
|||
return {};
|
||||
}
|
||||
|
||||
auto source_integer = source->as_integer();
|
||||
ASSERT(source);
|
||||
auto source_integer = source->convert(AML::Node::ConvInteger);
|
||||
if (!source_integer)
|
||||
{
|
||||
AML_TODO("BankFieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type));
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto access_size = determine_access_size(access_rules.access_type);
|
||||
if (!access_size.has_value())
|
||||
return false;
|
||||
return {};
|
||||
auto read_func = [&](uint64_t byte_offset) -> BAN::Optional<uint64_t> {
|
||||
return perform_read(op_region->region_space, byte_offset, access_size.value());
|
||||
};
|
||||
|
@ -852,7 +859,10 @@ 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);
|
||||
const auto source_value = static_cast<AML::Integer*>(source_integer.ptr())->value;
|
||||
if (!perform_write_general(op_region->region_offset, bit_count, bit_offset, access_size.value(), source_value, access_rules.update_rule, read_func, write_func))
|
||||
return {};
|
||||
return source_integer;
|
||||
}
|
||||
|
||||
void AML::BankFieldElement::debug_print(int indent) const
|
||||
|
|
|
@ -7,24 +7,6 @@
|
|||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
BAN::RefPtr<AML::Buffer> AML::Name::as_buffer()
|
||||
{
|
||||
ASSERT(object);
|
||||
return object->as_buffer();
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Integer> AML::Name::as_integer()
|
||||
{
|
||||
ASSERT(object);
|
||||
return object->as_integer();
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::String> AML::Name::as_string()
|
||||
{
|
||||
ASSERT(object);
|
||||
return object->as_string();
|
||||
}
|
||||
|
||||
AML::ParseResult AML::Name::parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
|
|
|
@ -20,11 +20,12 @@ namespace Kernel::ACPI
|
|||
struct DebugNode : AML::Node
|
||||
{
|
||||
DebugNode() : AML::Node(AML::Node::Type::Debug) {}
|
||||
bool store(BAN::RefPtr<AML::Node> node)
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> node)
|
||||
{
|
||||
node->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
return true;
|
||||
return node;
|
||||
}
|
||||
void debug_print(int indent) const override
|
||||
{
|
||||
|
@ -236,7 +237,7 @@ namespace Kernel::ACPI
|
|||
auto osi = MUST(BAN::RefPtr<AML::Method>::create(NameSeg("_OSI"_sv), 1, false, 0));
|
||||
osi->override_function = [](AML::ParseContext& context) -> BAN::RefPtr<AML::Node> {
|
||||
ASSERT(context.method_args[0]);
|
||||
auto arg = context.method_args[0]->evaluate();
|
||||
auto arg = context.method_args[0]->convert(AML::Node::ConvString);
|
||||
if (!arg || arg->type != AML::Node::Type::String)
|
||||
{
|
||||
AML_ERROR("Invalid _OSI argument");
|
||||
|
|
|
@ -36,24 +36,6 @@ namespace Kernel::ACPI
|
|||
|
||||
uint64_t AML::Node::total_node_count = 0;
|
||||
|
||||
BAN::RefPtr<AML::Buffer> AML::Node::as_buffer()
|
||||
{
|
||||
AML_TODO("Node type {} to buffer", static_cast<uint32_t>(type));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Integer> AML::Node::as_integer()
|
||||
{
|
||||
AML_TODO("Node type {} to integer", static_cast<uint32_t>(type));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::String> AML::Node::as_string()
|
||||
{
|
||||
AML_TODO("Node type {} to string", static_cast<uint32_t>(type));
|
||||
return {};
|
||||
}
|
||||
|
||||
AML::ParseResult AML::parse_object(AML::ParseContext& context)
|
||||
{
|
||||
if (context.aml_data.size() < 1)
|
||||
|
@ -204,6 +186,7 @@ namespace Kernel::ACPI
|
|||
return AML::Notify::parse(context);
|
||||
case AML::Byte::SizeOfOp:
|
||||
return AML::SizeOf::parse(context);
|
||||
case AML::Byte::BreakPointOp: // TODO: support breakpoints?
|
||||
case AML::Byte::NoopOp:
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
return ParseResult::Success;
|
||||
|
@ -269,6 +252,9 @@ namespace Kernel::ACPI
|
|||
return ParseResult::Success;
|
||||
return ParseResult(result.value());
|
||||
}
|
||||
|
||||
if (aml_object->type == AML::Node::Type::Name)
|
||||
return ParseResult(static_cast<AML::Name*>(aml_object.ptr())->object);
|
||||
return ParseResult(aml_object);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
#include <kernel/ACPI/AML/Buffer.h>
|
||||
#include <kernel/ACPI/AML/Integer.h>
|
||||
#include <kernel/ACPI/AML/Register.h>
|
||||
#include <kernel/ACPI/AML/String.h>
|
||||
|
||||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
BAN::RefPtr<AML::Buffer> Register::as_buffer()
|
||||
{
|
||||
if (value)
|
||||
return value->as_buffer();
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Integer> Register::as_integer()
|
||||
{
|
||||
if (value)
|
||||
return value->as_integer();
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::String> Register::as_string()
|
||||
{
|
||||
if (value)
|
||||
return value->as_string();
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
|
@ -25,7 +25,7 @@ namespace Kernel::ACPI
|
|||
auto named_object = Namespace::root_namespace()->find_object(context.scope, name_string.value(), Namespace::FindMode::Normal);
|
||||
if (!named_object)
|
||||
{
|
||||
AML_DEBUG_PRINT("Scope '{}' not found in namespace", name_string.value());
|
||||
AML_PRINT("Scope '{}' not found in namespace", name_string.value());
|
||||
return ParseResult::Success;
|
||||
}
|
||||
if (!named_object->is_scope())
|
||||
|
@ -69,7 +69,12 @@ namespace Kernel::ACPI
|
|||
static BAN::RefPtr<AML::Integer> evaluate_or_invoke(BAN::RefPtr<AML::Node> object)
|
||||
{
|
||||
if (object->type != AML::Node::Type::Method)
|
||||
return object->as_integer();
|
||||
{
|
||||
auto converted = object->convert(AML::Node::ConvInteger);
|
||||
if (!converted)
|
||||
return {};
|
||||
return static_cast<AML::Integer*>(converted.ptr());
|
||||
}
|
||||
|
||||
auto* method = static_cast<AML::Method*>(object.ptr());
|
||||
if (method->arg_count != 0)
|
||||
|
@ -85,7 +90,10 @@ namespace Kernel::ACPI
|
|||
return {};
|
||||
}
|
||||
|
||||
return result.value() ? result.value()->as_integer() : BAN::RefPtr<AML::Integer>();
|
||||
auto result_integer = result.value()
|
||||
? result.value()->convert(AML::Node::ConvInteger)
|
||||
: BAN::RefPtr<AML::Node>();
|
||||
return static_cast<AML::Integer*>(result_integer.ptr());
|
||||
}
|
||||
|
||||
bool AML::initialize_scope(BAN::RefPtr<AML::Scope> scope)
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace Kernel::ACPI::AML
|
|||
|
||||
BAN::Optional<bool> String::logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop)
|
||||
{
|
||||
auto rhs = node ? node->as_string() : BAN::RefPtr<AML::String>();
|
||||
auto rhs = node ? node->convert(AML::Node::ConvString) : BAN::RefPtr<AML::Node>();
|
||||
if (!rhs)
|
||||
{
|
||||
AML_ERROR("String logical compare RHS is not string");
|
||||
|
@ -27,6 +27,20 @@ namespace Kernel::ACPI::AML
|
|||
return buffer;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> String::convert(uint8_t mask)
|
||||
{
|
||||
if (mask & AML::Node::ConvString)
|
||||
return this;
|
||||
if (mask & AML::Node::ConvInteger)
|
||||
{
|
||||
AML_TODO("Convert String to Integer");
|
||||
return {};
|
||||
}
|
||||
if (mask & AML::Node::ConvBuffer)
|
||||
return as_buffer();
|
||||
return {};
|
||||
}
|
||||
|
||||
ParseResult String::parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
|
|
Loading…
Reference in New Issue