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:
Bananymous 2024-08-15 02:13:41 +03:00
parent 44d5c8c4b4
commit 3f5ee6f414
37 changed files with 564 additions and 416 deletions

View File

@ -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

View File

@ -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)
{

View File

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

View File

@ -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();

View File

@ -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);

View File

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

View File

@ -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));

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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())
{

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
};

View File

@ -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;
}
};

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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("}");
}

View File

@ -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))

View File

@ -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

View File

@ -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)));

View File

@ -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;
}
};

View File

@ -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;
}

View File

@ -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();
};
}

View File

@ -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);

View File

@ -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)

View File

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

View File

@ -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

View File

@ -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);

View File

@ -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");

View File

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

View File

@ -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 {};
}
}

View File

@ -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)

View File

@ -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);