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/Namespace.cpp
kernel/ACPI/AML/Node.cpp kernel/ACPI/AML/Node.cpp
kernel/ACPI/AML/Package.cpp kernel/ACPI/AML/Package.cpp
kernel/ACPI/AML/Register.cpp
kernel/ACPI/AML/Scope.cpp kernel/ACPI/AML/Scope.cpp
kernel/ACPI/AML/String.cpp kernel/ACPI/AML/String.cpp
kernel/APIC.cpp kernel/APIC.cpp

View File

@ -7,7 +7,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct Alias : public AML::NamedObject struct Alias final : public AML::NamedObject
{ {
BAN::RefPtr<AML::Node> target; BAN::RefPtr<AML::Node> target;
@ -18,14 +18,11 @@ namespace Kernel::ACPI::AML
bool is_scope() const override { return target->is_scope(); } 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<Node> copy() override { return target->copy(); }
BAN::RefPtr<AML::Buffer> as_buffer() override { return target->as_buffer(); } BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> node) override { ASSERT(target); return target->store(node); }
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); }
static ParseResult parse(ParseContext& context) static ParseResult parse(ParseContext& context)
{ {

View File

@ -10,7 +10,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct Buffer : public AML::Node struct Buffer final : public AML::Node
{ {
BAN::Vector<uint8_t> buffer; 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) BAN::Optional<bool> logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop)
{ {
auto rhs = node ? node->as_buffer() : BAN::RefPtr<AML::Buffer>(); auto rhs_node = node ? node->convert(AML::Node::ConvBuffer) : BAN::RefPtr<AML::Node>();
if (!rhs) if (!rhs_node)
{ {
AML_ERROR("Buffer logical compare RHS is not buffer"); AML_ERROR("Buffer logical compare RHS cannot be converted to buffer");
return {}; return {};
} }
@ -32,19 +32,18 @@ namespace Kernel::ACPI::AML
return {}; return {};
} }
BAN::RefPtr<AML::Buffer> as_buffer() override { return this; } BAN::RefPtr<AML::Node> convert(uint8_t mask) override
BAN::RefPtr<AML::Integer> as_integer() override
{ {
uint64_t value = 0; if (mask & AML::Node::ConvBuffer)
for (size_t i = 0; i < BAN::Math::min<size_t>(buffer.size(), 8); i++) return this;
value |= static_cast<uint64_t>(buffer[i]) << (8 * i); if (mask & AML::Node::ConvInteger)
return MUST(BAN::RefPtr<Integer>::create(value)); return as_integer();
} if (mask & AML::Node::ConvString)
{
BAN::RefPtr<AML::Node> evaluate() override AML_TODO("Convert BufferField to String");
{ return {};
return this; }
return {};
} }
static ParseResult parse(AML::ParseContext& context) static ParseResult parse(AML::ParseContext& context)
@ -60,15 +59,21 @@ namespace Kernel::ACPI::AML
auto buffer_context = context; auto buffer_context = context;
buffer_context.aml_data = buffer_pkg.value(); buffer_context.aml_data = buffer_pkg.value();
auto buffer_size_object = AML::parse_object(buffer_context); auto buffer_size_result = AML::parse_object(buffer_context);
if (!buffer_size_object.success()) if (!buffer_size_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto buffer_size = buffer_size_object.node()->as_integer(); auto buffer_size_node = buffer_size_result.node() ? buffer_size_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!buffer_size) if (!buffer_size_node)
{
AML_ERROR("Buffer size is not an integer");
return ParseResult::Failure; 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()); auto buffer = MUST(BAN::RefPtr<Buffer>::create());
MUST(buffer->buffer.resize(actual_buffer_size, 0)); MUST(buffer->buffer.resize(actual_buffer_size, 0));
@ -88,9 +93,18 @@ namespace Kernel::ACPI::AML
AML_DEBUG_PRINT_INDENT(indent); AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("Buffer ({} bytes)", buffer.size()); 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; BAN::RefPtr<AML::Node> buffer;
size_t field_bit_offset; size_t field_bit_offset;
@ -104,49 +118,26 @@ namespace Kernel::ACPI::AML
, field_bit_size(field_bit_size) , field_bit_size(field_bit_size)
{} {}
BAN::RefPtr<AML::Integer> as_integer() override BAN::RefPtr<AML::Node> convert(uint8_t mask) override
{ {
ASSERT(buffer); if (mask & AML::Node::ConvBufferField)
ASSERT(buffer->type == AML::Node::Type::Buffer || buffer->type == AML::Node::Type::String); return this;
if (mask & AML::Node::ConvInteger)
const auto& buffer = (this->buffer->type == AML::Node::Type::Buffer) return as_integer();
? static_cast<AML::Buffer*>(this->buffer.ptr())->buffer if (mask & AML::Node::ConvBuffer)
: 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; AML_TODO("Convert BufferField to Buffer");
value |= static_cast<uint64_t>((buffer[bit / 8] >> (bit % 8)) & 1) << i; return {};
} }
if (mask & AML::Node::ConvString)
return MUST(BAN::RefPtr<Integer>::create(value)); {
AML_TODO("Convert BufferField to String");
return {};
}
return {};
} }
BAN::RefPtr<AML::Node> evaluate() 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);
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
{ {
ASSERT(buffer); ASSERT(buffer);
ASSERT(buffer->type == AML::Node::Type::Buffer || buffer->type == AML::Node::Type::String); 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; : static_cast<AML::String*>(this->buffer.ptr())->string;
ASSERT(field_bit_offset + field_bit_size <= buffer.size() * 8); ASSERT(field_bit_offset + field_bit_size <= buffer.size() * 8);
auto value = node->as_integer(); auto value_node = node ? node->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!value) if (!value_node)
return false; return {};
const auto value = static_cast<AML::Integer*>(value_node.ptr())->value;
// TODO: optimize for whole byte accesses // TODO: optimize for whole byte accesses
for (size_t i = 0; i < field_bit_size; i++) for (size_t i = 0; i < field_bit_size; i++)
{ {
const size_t bit = field_bit_offset + 1; const size_t bit = field_bit_offset + 1;
buffer[bit / 8] &= ~(1 << (bit % 8)); 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) static ParseResult parse(AML::ParseContext& context)
@ -204,7 +196,7 @@ namespace Kernel::ACPI::AML
auto buffer_result = AML::parse_object(context); auto buffer_result = AML::parse_object(context);
if (!buffer_result.success()) if (!buffer_result.success())
return ParseResult::Failure; 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) if (!buffer_node || buffer_node->type != Node::Type::Buffer)
{ {
AML_ERROR("Buffer source does not evaluate to a 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); auto index_result = AML::parse_object(context);
if (!index_result.success()) if (!index_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto index = index_result.node() ? index_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto index_node = index_result.node() ? index_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!index) if (!index_node)
{ {
AML_ERROR("Failed to parse index for BufferField"); AML_ERROR("Failed to parse index for BufferField");
return ParseResult::Failure; return ParseResult::Failure;
} }
size_t field_bit_offset = index->value;
if (field_bit_size != 1)
field_bit_offset *= 8;
if (field_bit_size == 0) if (field_bit_size == 0)
{ {
auto bit_count_result = AML::parse_object(context); auto bit_count_result = AML::parse_object(context);
if (!index_result.success()) if (!bit_count_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto bit_count = bit_count_result.node() ? bit_count_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto bit_count_node = bit_count_result.node() ? bit_count_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!bit_count) if (!bit_count_node)
{ {
AML_ERROR("Failed to parse bit count for BufferField"); AML_ERROR("Failed to parse bit count for BufferField");
return ParseResult::Failure; 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); auto field_name = AML::NameString::parse(context.aml_data);
@ -248,6 +237,10 @@ namespace Kernel::ACPI::AML
return ParseResult::Failure; 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)); 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)) if (!Namespace::root_namespace()->add_named_object(context, field_name.value(), field))
return ParseResult::Success; return ParseResult::Success;
@ -268,6 +261,27 @@ namespace Kernel::ACPI::AML
AML_DEBUG_PRINT(" }"); 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) switch (opcode)
{ {
case AML::Byte::ToBufferOp: case AML::Byte::ToBufferOp:
converted = data_node->as_buffer(); converted = data_node->convert(AML::Node::ConvBuffer);
break; break;
case AML::Byte::ToIntegerOp: case AML::Byte::ToIntegerOp:
converted = data_node->as_integer(); converted = data_node->convert(AML::Node::ConvInteger);
break; break;
case AML::Byte::ToStringOp: case AML::Byte::ToStringOp:
converted = data_node->as_string(); converted = data_node->convert(AML::Node::ConvString);
break; break;
default: default:
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();

View File

@ -8,12 +8,14 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct Device : public AML::Scope struct Device final : public AML::Scope
{ {
Device(NameSeg name) Device(NameSeg name)
: Scope(Node::Type::Device, name) : Scope(Node::Type::Device, name)
{} {}
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
static ParseResult parse(ParseContext& context) static ParseResult parse(ParseContext& context)
{ {
ASSERT(context.aml_data.size() >= 2); ASSERT(context.aml_data.size() >= 2);

View File

@ -10,7 +10,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct Event : public AML::NamedObject struct Event final : public AML::NamedObject
{ {
BAN::Atomic<uint32_t> signal_count { 0 }; BAN::Atomic<uint32_t> signal_count { 0 };
ThreadBlocker thread_blocker; ThreadBlocker thread_blocker;
@ -19,6 +19,8 @@ namespace Kernel::ACPI::AML
: NamedObject(Node::Type::Event, name) : NamedObject(Node::Type::Event, name)
{} {}
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
static ParseResult parse(ParseContext& context) static ParseResult parse(ParseContext& context)
{ {
ASSERT(context.aml_data.size() >= 2); ASSERT(context.aml_data.size() >= 2);
@ -43,7 +45,7 @@ namespace Kernel::ACPI::AML
if (!event_result.success()) if (!event_result.success())
return ParseResult::Failure; 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) if (!general_node || general_node->type != Node::Type::Event)
{ {
AML_ERROR("Release, Wait or Signal does not name an event"); AML_ERROR("Release, Wait or Signal does not name an event");
@ -58,12 +60,15 @@ namespace Kernel::ACPI::AML
if (!timeout_result.success()) if (!timeout_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto timeout = timeout_result.node() ? timeout_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto timeout_node = timeout_result.node()
if (!timeout) ? timeout_result.node()->convert(AML::Node::ConvInteger)
: BAN::RefPtr<AML::Node>();
if (!timeout_node)
{ {
AML_ERROR("Wait timeout does not evaluate to integer"); AML_ERROR("Wait timeout does not evaluate to integer");
return ParseResult::Failure; 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(); const uint64_t start_ms = SystemTimer::get().ms_since_boot();
while (true) while (true)
@ -77,14 +82,14 @@ namespace Kernel::ACPI::AML
return ParseResult(Integer::Constants::Zero); return ParseResult(Integer::Constants::Zero);
} }
if (timeout->value >= 0xFFFF) if (timeout_value >= 0xFFFF)
event_node->thread_blocker.block_indefinite(); event_node->thread_blocker.block_indefinite();
else else
{ {
const uint64_t current_ms = SystemTimer::get().ms_since_boot(); 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); 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 #pragma once
#include <kernel/ACPI/AML/Buffer.h>
#include <kernel/ACPI/AML/Bytes.h> #include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Integer.h> #include <kernel/ACPI/AML/Integer.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/ParseContext.h> #include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/String.h>
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
@ -25,13 +26,14 @@ namespace Kernel::ACPI::AML
auto source_result = AML::parse_object(context); auto source_result = AML::parse_object(context);
if (!source_result.success()) if (!source_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto source_node = source_result.node() ? source_result.node()->as_integer(): BAN::RefPtr<AML::Integer>(); auto conv_node = source_result.node() ? source_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!source_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; return ParseResult::Failure;
} }
auto source_node = static_cast<AML::Integer*>(conv_node.ptr());
if (source_node->constant) if (source_node->constant)
{ {
AML_ERROR("UnaryOp source is constant"); AML_ERROR("UnaryOp source is constant");
@ -48,18 +50,23 @@ namespace Kernel::ACPI::AML
{ {
context.aml_data = context.aml_data.slice(1); context.aml_data = context.aml_data.slice(1);
auto node_result = AML::parse_object(context); auto source_result = AML::parse_object(context);
if (!node_result.success()) if (!source_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto conv_node = source_result.node() ? source_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
auto value = node_result.node() ? node_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); if (!conv_node)
if (!value) {
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"); AML_ERROR("Logical NotOp source is not integer");
return ParseResult::Failure; 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); return ParseResult(result);
} }
case AML::Byte::AddOp: case AML::Byte::AddOp:
@ -97,21 +104,25 @@ namespace Kernel::ACPI::AML
auto lhs_result = AML::parse_object(context); auto lhs_result = AML::parse_object(context);
if (!lhs_result.success()) if (!lhs_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto lhs_value = lhs_result.node() ? lhs_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto lhs_conv = lhs_result.node() ? lhs_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!lhs_value) 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()) if (lhs_result.node())
lhs_result.node()->debug_print(1); lhs_result.node()->debug_print(1);
AML_DEBUG_PRINTLN(""); AML_DEBUG_PRINTLN("");
return ParseResult::Failure; return ParseResult::Failure;
} }
const auto lhs_value = static_cast<AML::Integer*>(lhs_conv.ptr())->value;
auto rhs_result = AML::parse_object(context); auto rhs_result = AML::parse_object(context);
if (!rhs_result.success()) if (!rhs_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto rhs_value = rhs_result.node() ? rhs_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto rhs_conv = rhs_result.node() ? rhs_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!rhs_value) if (!rhs_conv)
{ {
AML_ERROR("BinaryOP {2H} RHS not an integer", static_cast<uint8_t>(opcode)); AML_ERROR("BinaryOP {2H} RHS not an integer", static_cast<uint8_t>(opcode));
if (rhs_result.node()) if (rhs_result.node())
@ -119,12 +130,14 @@ namespace Kernel::ACPI::AML
AML_DEBUG_PRINTLN(""); AML_DEBUG_PRINTLN("");
return ParseResult::Failure; return ParseResult::Failure;
} }
const auto rhs_value = static_cast<AML::Integer*>(rhs_conv.ptr())->value;
if (context.aml_data.size() < 1) if (context.aml_data.size() < 1)
{ {
AML_ERROR("BinaryOP {2H} missing target", static_cast<uint8_t>(opcode)); AML_ERROR("BinaryOP {2H} missing target", static_cast<uint8_t>(opcode));
return ParseResult::Failure; return ParseResult::Failure;
} }
BAN::RefPtr<AML::Node> target_node; BAN::RefPtr<AML::Node> target_node;
if (context.aml_data[0] == 0x00) if (context.aml_data[0] == 0x00)
context.aml_data = context.aml_data.slice(1); context.aml_data = context.aml_data.slice(1);
@ -159,9 +172,7 @@ namespace Kernel::ACPI::AML
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
uint64_t result = func(lhs_value->value, rhs_value->value); auto result_node = MUST(BAN::RefPtr<AML::Integer>::create(func(lhs_value, rhs_value)));
auto result_node = MUST(BAN::RefPtr<AML::Integer>::create(result));
if (target_node && !target_node->store(result_node)) if (target_node && !target_node->store(result_node))
{ {
AML_ERROR("BinaryOp {2H} failed to store result", static_cast<uint8_t>(opcode)); 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]); auto opcode = static_cast<AML::Byte>(context.aml_data[0]);
context.aml_data = context.aml_data.slice(1); 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); auto lhs_result = AML::parse_object(context);
if (!lhs_result.success()) if (!lhs_result.success())
return ParseResult::Failure; 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) if (!lhs_node)
{ {
AML_TODO("Logical BinaryOP {2H} LHS evaluated to nothing", static_cast<uint8_t>(opcode)); 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; uint8_t access_length = 0;
}; };
struct FieldElement : public NamedObject struct FieldElement final : public AML::NamedObject
{ {
uint64_t bit_offset; uint64_t bit_offset;
uint64_t bit_count; uint64_t bit_count;
@ -63,14 +63,30 @@ namespace Kernel::ACPI::AML
, access_rules(access_rules) , 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(); } BAN::RefPtr<AML::Node> store(BAN::RefPtr<Node> source) override;
bool store(BAN::RefPtr<Node> source) override;
void debug_print(int indent) const override; void debug_print(int indent) const override;
private: private:
BAN::RefPtr<AML::Integer> as_integer();
BAN::Optional<uint64_t> evaluate_internal(); BAN::Optional<uint64_t> evaluate_internal();
bool store_internal(uint64_t value); bool store_internal(uint64_t value);
@ -83,7 +99,7 @@ namespace Kernel::ACPI::AML
static ParseResult parse(ParseContext& context); static ParseResult parse(ParseContext& context);
}; };
struct IndexFieldElement : public NamedObject struct IndexFieldElement final : public AML::NamedObject
{ {
uint64_t bit_offset; uint64_t bit_offset;
uint64_t bit_count; uint64_t bit_count;
@ -100,12 +116,30 @@ namespace Kernel::ACPI::AML
, access_rules(access_rules) , 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(); } BAN::RefPtr<AML::Node> store(BAN::RefPtr<Node> source) override;
bool store(BAN::RefPtr<Node> source) override;
void debug_print(int indent) const override; void debug_print(int indent) const override;
private:
BAN::RefPtr<AML::Integer> as_integer();
}; };
struct IndexField struct IndexField
@ -113,7 +147,7 @@ namespace Kernel::ACPI::AML
static ParseResult parse(ParseContext& context); static ParseResult parse(ParseContext& context);
}; };
struct BankFieldElement : public NamedObject struct BankFieldElement final : public AML::NamedObject
{ {
uint64_t bit_offset; uint64_t bit_offset;
uint64_t bit_count; uint64_t bit_count;
@ -131,10 +165,30 @@ namespace Kernel::ACPI::AML
, access_rules(access_rules) , access_rules(access_rules)
{} {}
BAN::RefPtr<Node> evaluate() override; BAN::RefPtr<AML::Node> convert(uint8_t mask) override
bool store(BAN::RefPtr<Node> source) 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; void debug_print(int indent) const override;
private:
BAN::RefPtr<AML::Integer> as_integer();
}; };
struct BankField struct BankField

View File

@ -26,12 +26,13 @@ namespace Kernel::ACPI::AML
auto predicate_result = AML::parse_object(context); auto predicate_result = AML::parse_object(context);
if (!predicate_result.success()) if (!predicate_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto predicate = predicate_result.node() ? predicate_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto predicate_node = predicate_result.node() ? predicate_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!predicate) if (!predicate_node)
{ {
AML_ERROR("If predicate is not an integer"); AML_ERROR("If predicate is not an integer");
return ParseResult::Failure; return ParseResult::Failure;
} }
const auto predicate_value = static_cast<AML::Integer*>(predicate_node.ptr())->value;
// Else // Else
BAN::ConstByteSpan else_pkg; BAN::ConstByteSpan else_pkg;
@ -43,7 +44,7 @@ namespace Kernel::ACPI::AML
return ParseResult::Failure; return ParseResult::Failure;
else_pkg = else_pkg_result.value(); else_pkg = else_pkg_result.value();
} }
if (predicate->value == 0) if (predicate_value == 0)
context.aml_data = else_pkg; context.aml_data = else_pkg;
while (context.aml_data.size() > 0) while (context.aml_data.size() > 0)

View File

@ -20,22 +20,32 @@ namespace Kernel::ACPI::AML
auto source_result = AML::parse_object(context); auto source_result = AML::parse_object(context);
if (!source_result.success()) if (!source_result.success())
return ParseResult::Failure; 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) 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; return ParseResult::Failure;
} }
auto index_result = AML::parse_object(context); auto index_result = AML::parse_object(context);
if (!index_result.success()) if (!index_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto index = index_result.node() ? index_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto index_node = source_result.node()
if (!index) ? source_result.node()->convert(AML::Node::ConvInteger)
: BAN::RefPtr<AML::Node>();
if (!index_node)
{ {
AML_ERROR("IndexOp index is not an integer"); AML_ERROR("IndexOp index is not an integer");
return ParseResult::Failure; return ParseResult::Failure;
} }
const auto index = static_cast<AML::Integer*>(index_node.ptr())->value;
BAN::RefPtr<AML::Reference> result; BAN::RefPtr<AML::Reference> result;
switch (source->type) switch (source->type)
@ -43,36 +53,36 @@ namespace Kernel::ACPI::AML
case AML::Node::Type::Buffer: case AML::Node::Type::Buffer:
{ {
auto buffer = BAN::RefPtr<AML::Buffer>(static_cast<AML::Buffer*>(source.ptr())); 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"); AML_ERROR("IndexOp index is out of buffer bounds");
return ParseResult::Failure; 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)); result = MUST(BAN::RefPtr<AML::Reference>::create(buffer_field));
break; break;
} }
case AML::Node::Type::Package: case AML::Node::Type::Package:
{ {
auto package = static_cast<AML::Package*>(source.ptr()); 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"); AML_ERROR("IndexOp index is out of package bounds");
return ParseResult::Failure; 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)); result = MUST(BAN::RefPtr<AML::Reference>::create(package_element));
break; break;
} }
case AML::Node::Type::String: case AML::Node::Type::String:
{ {
auto string = BAN::RefPtr<AML::String>(static_cast<AML::String*>(source.ptr())); 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"); AML_ERROR("IndexOp index is out of string bounds");
return ParseResult::Failure; 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)); result = MUST(BAN::RefPtr<AML::Reference>::create(buffer_field));
break; break;
} }
@ -82,7 +92,7 @@ namespace Kernel::ACPI::AML
} }
#if AML_DEBUG_LEVEL >= 2 #if AML_DEBUG_LEVEL >= 2
AML_DEBUG_PRINT("Index {}, ", index->value); AML_DEBUG_PRINT("Index {}, ", index);
source->debug_print(0); source->debug_print(0);
AML_DEBUG_PRINTLN(""); AML_DEBUG_PRINTLN("");
#endif #endif

View File

@ -10,7 +10,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct Integer : public Node struct Integer final : public AML::Node
{ {
struct Constants struct Constants
{ {
@ -31,49 +31,70 @@ namespace Kernel::ACPI::AML
BAN::Optional<bool> logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop) BAN::Optional<bool> logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop)
{ {
auto rhs = node ? node->as_integer() : BAN::RefPtr<AML::Integer>(); auto rhs_node = node ? node->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!rhs) if (!rhs_node)
{ {
AML_ERROR("Integer logical compare RHS is not integer"); AML_ERROR("Integer logical compare RHS cannot be converted to");
return {}; return {};
} }
const auto rhs_value = static_cast<AML::Integer*>(rhs_node.ptr())->value;
switch (binaryop) switch (binaryop)
{ {
case AML::Byte::LAndOp: return value && rhs->value; case AML::Byte::LAndOp: return value && rhs_value;
case AML::Byte::LEqualOp: return value == rhs->value; case AML::Byte::LEqualOp: return value == rhs_value;
case AML::Byte::LGreaterOp: return value > rhs->value; case AML::Byte::LGreaterOp: return value > rhs_value;
case AML::Byte::LLessOp: return value < rhs->value; case AML::Byte::LLessOp: return value < rhs_value;
case AML::Byte::LOrOp: return value || rhs->value; case AML::Byte::LOrOp: return value || rhs_value;
default: default:
ASSERT_NOT_REACHED(); 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<Node> copy() override { return MUST(BAN::RefPtr<Integer>::create(value)); }
BAN::RefPtr<AML::Node> evaluate() override BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> store_node) override
{
return this;
}
bool store(BAN::RefPtr<AML::Node> store_node) override
{ {
if (constant) if (constant)
{ {
AML_ERROR("Cannot store to constant integer"); AML_ERROR("Cannot store to constant integer");
return false; return {};
} }
auto store_value = store_node->as_integer(); auto conv_node = store_node ? store_node->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!store_value) if (!conv_node)
{ {
AML_ERROR("Cannot store non-integer to integer"); AML_ERROR("Cannot store non-integer to integer");
return false; return {};
} }
value = store_value->value; value = static_cast<AML::Integer*>(conv_node.ptr())->value;
return true; return MUST(BAN::RefPtr<AML::Integer>::create(value));
} }
static ParseResult parse(BAN::ConstByteSpan& aml_data) static ParseResult parse(BAN::ConstByteSpan& aml_data)

View File

@ -10,7 +10,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct Method : public AML::Scope struct Method final : public AML::Scope
{ {
Kernel::Mutex mutex; Kernel::Mutex mutex;
uint8_t arg_count; uint8_t arg_count;
@ -27,6 +27,8 @@ namespace Kernel::ACPI::AML
, sync_level(sync_level) , sync_level(sync_level)
{} {}
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
static ParseResult parse(AML::ParseContext& context) static ParseResult parse(AML::ParseContext& context)
{ {
ASSERT(context.aml_data.size() >= 1); ASSERT(context.aml_data.size() >= 1);
@ -98,13 +100,13 @@ namespace Kernel::ACPI::AML
ParseContext context; ParseContext context;
context.aml_data = term_list; context.aml_data = term_list;
context.scope = scope; context.scope = scope;
context.method_args[0] = MUST(BAN::RefPtr<AML::Register>::create(arg0)); 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)); 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)); 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)); 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)); 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)); 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)); 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); context.sync_stack = BAN::move(current_sync_stack);
for (auto& local : context.method_locals) for (auto& local : context.method_locals)
local = MUST(BAN::RefPtr<AML::Register>::create()); local = MUST(BAN::RefPtr<AML::Register>::create());
@ -142,8 +144,8 @@ namespace Kernel::ACPI::AML
} }
} }
if (return_value.has_value() && return_value.value()) if (return_value.has_value() && return_value.value() && return_value.value()->type == AML::Node::Type::Register)
return_value = return_value.value()->evaluate(); return_value.value() = static_cast<AML::Register*>(return_value.value().ptr())->value;
while (!context.created_objects.empty()) while (!context.created_objects.empty())
{ {

View File

@ -10,7 +10,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct Mutex : public AML::NamedObject struct Mutex final : public AML::NamedObject
{ {
Kernel::Mutex mutex; Kernel::Mutex mutex;
uint8_t sync_level; uint8_t sync_level;
@ -20,6 +20,8 @@ namespace Kernel::ACPI::AML
, sync_level(sync_level) , sync_level(sync_level)
{} {}
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
static ParseResult parse(ParseContext& context) static ParseResult parse(ParseContext& context)
{ {
ASSERT(context.aml_data.size() >= 2); ASSERT(context.aml_data.size() >= 2);

View File

@ -6,7 +6,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct NamedObject : public Node struct NamedObject : public AML::Node
{ {
BAN::RefPtr<NamedObject> parent; BAN::RefPtr<NamedObject> parent;
NameSeg name; NameSeg name;
@ -14,7 +14,7 @@ namespace Kernel::ACPI::AML
NamedObject(Node::Type type, NameSeg name) : Node(type), name(name) {} 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; BAN::RefPtr<AML::Node> object;
@ -22,21 +22,15 @@ namespace Kernel::ACPI::AML
: NamedObject(Node::Type::Name, name), object(BAN::move(object)) : NamedObject(Node::Type::Name, name), object(BAN::move(object))
{} {}
BAN::RefPtr<AML::Buffer> as_buffer() override; BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
BAN::RefPtr<AML::Integer> as_integer() override;
BAN::RefPtr<AML::String> as_string() override;
BAN::RefPtr<AML::Node> evaluate() override BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> node) override
{
ASSERT(object);
return object->evaluate();
}
bool store(BAN::RefPtr<AML::Node> node) override
{ {
ASSERT(object); ASSERT(object);
if (object->type == AML::Node::Type::Reference)
return object->store(node);
object = node; object = node;
return true; return node;
} }
static ParseResult parse(ParseContext& context); static ParseResult parse(ParseContext& context);

View File

@ -8,8 +8,9 @@
namespace Kernel::ACPI::AML 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::Namespace> root_namespace();
static BAN::RefPtr<AML::Node> debug_node; static BAN::RefPtr<AML::Node> debug_node;
@ -35,7 +36,8 @@ namespace Kernel::ACPI::AML
Namespace(NameSeg name) : AML::Scope(Node::Type::Namespace, name) {} 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); bool parse(const SDTHeader& header);
void debug_print(int indent) const override; void debug_print(int indent) const override;

View File

@ -17,8 +17,18 @@ namespace Kernel::ACPI::AML
{ {
static uint64_t total_node_count; 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, Alias,
BankFieldElement, BankFieldElement,
Buffer, Buffer,
@ -50,14 +60,9 @@ namespace Kernel::ACPI::AML
virtual bool is_scope() const { return false; } virtual bool is_scope() const { return false; }
virtual BAN::RefPtr<Node> copy() { return this; } [[nodiscard]] virtual BAN::RefPtr<AML::Node> convert(uint8_t mask) = 0;
[[nodiscard]] virtual BAN::RefPtr<Node> copy() { return this; }
[[nodiscard]] virtual BAN::RefPtr<AML::Buffer> as_buffer(); [[nodiscard]] virtual BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node>) { AML_TODO("store, type {}", static_cast<uint8_t>(type)); return {}; }
[[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; }
virtual void debug_print(int indent) const = 0; 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); auto value_result = AML::parse_object(context);
if (!value_result.success()) if (!value_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto value = value_result.node() ? value_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto value_node = value_result.node() ? value_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!value) if (!value_node)
{ {
AML_ERROR("Notify value is not an integer"); AML_ERROR("Notify value is not an integer");
return ParseResult::Failure; return ParseResult::Failure;
} }
const auto value = static_cast<AML::Integer*>(value_node.ptr())->value;
BAN::StringView object_type_sv; BAN::StringView object_type_sv;
BAN::StringView object_name_sv; BAN::StringView object_name_sv;
@ -58,7 +59,7 @@ namespace Kernel::ACPI::AML
break; 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; return ParseResult::Success;
} }
}; };

View File

@ -11,7 +11,7 @@ namespace Kernel::ACPI::AML
struct PackageElement; struct PackageElement;
struct Package : public AML::Node struct Package final : public AML::Node
{ {
BAN::Vector<BAN::RefPtr<PackageElement>> elements; BAN::Vector<BAN::RefPtr<PackageElement>> elements;
AML::NameString scope; AML::NameString scope;
@ -22,16 +22,13 @@ namespace Kernel::ACPI::AML
, scope(scope) , scope(scope)
{} {}
BAN::RefPtr<AML::Node> evaluate() override BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
{
return this;
}
static ParseResult parse(AML::ParseContext& context); static ParseResult parse(AML::ParseContext& context);
virtual void debug_print(int indent) const override; 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::Package> parent;
BAN::RefPtr<AML::Node> element; BAN::RefPtr<AML::Node> element;
@ -82,7 +79,19 @@ namespace Kernel::ACPI::AML
return true; 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) if (!initialized)
{ {
@ -94,31 +103,7 @@ namespace Kernel::ACPI::AML
if (element->type == AML::Node::Type::Reference) if (element->type == AML::Node::Type::Reference)
return element->store(node); return element->store(node);
element = node->copy(); element = node->copy();
return true; return element;
}
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();
} }
static ParseResult parse(AML::ParseContext& context, BAN::RefPtr<AML::Package> package) static ParseResult parse(AML::ParseContext& context, BAN::RefPtr<AML::Package> package)

View File

@ -9,7 +9,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct PowerResource : public AML::Scope struct PowerResource final : public AML::Scope
{ {
uint8_t system_level; uint8_t system_level;
uint16_t resource_order; uint16_t resource_order;
@ -20,6 +20,8 @@ namespace Kernel::ACPI::AML
, resource_order(resource_order) , resource_order(resource_order)
{} {}
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
static ParseResult parse(ParseContext& context) static ParseResult parse(ParseContext& context)
{ {
ASSERT(context.aml_data.size() >= 2); ASSERT(context.aml_data.size() >= 2);

View File

@ -9,7 +9,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct Processor : public AML::Scope struct Processor final : public AML::Scope
{ {
uint8_t id; uint8_t id;
uint32_t pblk_addr; uint32_t pblk_addr;
@ -22,6 +22,8 @@ namespace Kernel::ACPI::AML
, pblk_len(pblk_len) , pblk_len(pblk_len)
{} {}
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
static ParseResult parse(ParseContext& context) static ParseResult parse(ParseContext& context)
{ {
ASSERT(context.aml_data.size() >= 2); ASSERT(context.aml_data.size() >= 2);

View File

@ -10,7 +10,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct Reference : public AML::Node struct Reference final : public AML::Node
{ {
BAN::RefPtr<AML::Node> node; BAN::RefPtr<AML::Node> node;
@ -21,24 +21,22 @@ namespace Kernel::ACPI::AML
ASSERT(node); ASSERT(node);
} }
BAN::RefPtr<AML::Integer> as_integer() override BAN::RefPtr<AML::Node> convert(uint8_t mask) override
{
if (node)
return node->as_integer();
return {};
}
BAN::RefPtr<AML::Node> evaluate() override
{
return this;
}
bool store(BAN::RefPtr<AML::Node> value) override
{ {
if (!node) if (!node)
{ {
AML_ERROR("Storing to null reference"); AML_ERROR("Trying to convert null Reference");
return false; 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); return node->store(value);
} }
@ -79,6 +77,8 @@ namespace Kernel::ACPI::AML
if (!parse_result.success()) if (!parse_result.success())
return ParseResult::Failure; return ParseResult::Failure;
object = parse_result.node(); object = parse_result.node();
if (object && object->type == AML::Node::Type::Register)
object = static_cast<AML::Register*>(object.ptr())->value;
} }
if (!conditional) if (!conditional)
@ -96,18 +96,26 @@ namespace Kernel::ACPI::AML
return ParseResult(reference); 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); auto target_result = AML::parse_object(context);
if (!target_result.success()) if (!target_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto target_node = target_result.node(); target_node = target_result.node();
if (!target_node) if (!target_node)
{ {
AML_ERROR("CondRefOf failed to resolve target"); AML_ERROR("CondRefOf failed to resolve target");
return ParseResult::Failure; return ParseResult::Failure;
} }
target_node->store(MUST(BAN::RefPtr<Reference>::create(object)));
} }
#if AML_DEBUG_LEVEL >= 2 #if AML_DEBUG_LEVEL >= 2
@ -119,8 +127,16 @@ namespace Kernel::ACPI::AML
AML_DEBUG_PRINTLN(""); AML_DEBUG_PRINTLN("");
#endif #endif
auto return_value = object ? Integer::Constants::Ones : Integer::Constants::Zero; if (!object)
return AML::ParseResult(return_value); 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) static ParseResult parse_dereference(ParseContext& context)
@ -144,18 +160,20 @@ namespace Kernel::ACPI::AML
auto parse_result = AML::parse_object(context); auto parse_result = AML::parse_object(context);
if (!parse_result.success()) if (!parse_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto object = parse_result.node() ? parse_result.node()->evaluate() : BAN::RefPtr<AML::Node>(); auto node = parse_result.node();
if (!object || object->type != AML::Node::Type::Reference) 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; return ParseResult::Failure;
} }
#if AML_DEBUG_LEVEL >= 2 #if AML_DEBUG_LEVEL >= 2
AML_DEBUG_PRINT("DerefOf "); AML_DEBUG_PRINT("DerefOf ");
object->debug_print(0); node->debug_print(0);
AML_DEBUG_PRINTLN(""); AML_DEBUG_PRINTLN("");
#endif #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_PRINT_INDENT(indent);
AML_DEBUG_PRINTLN("Reference {"); AML_DEBUG_PRINTLN("Reference {");
node->debug_print(indent + 1); node->debug_print(indent + 1);
AML_DEBUG_PRINTLN("");
AML_DEBUG_PRINT_INDENT(indent); AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("}"); AML_DEBUG_PRINT("}");
} }

View File

@ -8,7 +8,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct OpRegion : public NamedObject struct OpRegion final : public AML::NamedObject
{ {
using RegionSpace = GAS::AddressSpaceID; using RegionSpace = GAS::AddressSpaceID;
RegionSpace region_space; RegionSpace region_space;
@ -24,6 +24,8 @@ namespace Kernel::ACPI::AML
, region_length(region_length) , region_length(region_length)
{} {}
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
static ParseResult parse(AML::ParseContext& context) static ParseResult parse(AML::ParseContext& context)
{ {
ASSERT(context.aml_data.size() > 2); ASSERT(context.aml_data.size() > 2);
@ -43,8 +45,10 @@ namespace Kernel::ACPI::AML
auto offset_result = AML::parse_object(context); auto offset_result = AML::parse_object(context);
if (!offset_result.success()) if (!offset_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto offset = offset_result.node()->as_integer(); auto offset_node = offset_result.node()
if (!offset) ? offset_result.node()->convert(AML::Node::ConvInteger)
: BAN::RefPtr<AML::Node>();
if (!offset_node)
{ {
AML_ERROR("OpRegion offset must be an integer"); AML_ERROR("OpRegion offset must be an integer");
return ParseResult::Failure; return ParseResult::Failure;
@ -53,18 +57,23 @@ namespace Kernel::ACPI::AML
auto length_result = AML::parse_object(context); auto length_result = AML::parse_object(context);
if (!length_result.success()) if (!length_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto length = length_result.node()->as_integer(); auto length_node = length_result.node()
if (!length) ? length_result.node()->convert(AML::Node::ConvInteger)
: BAN::RefPtr<AML::Node>();
if (!length_node)
{ {
AML_ERROR("OpRegion length must be an integer"); AML_ERROR("OpRegion length must be an integer");
return ParseResult::Failure; 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( auto op_region = MUST(BAN::RefPtr<OpRegion>::create(
name->path.back(), name->path.back(),
region_space, region_space,
offset->value, offset,
length->value length
)); ));
if (!Namespace::root_namespace()->add_named_object(context, name.value(), op_region)) if (!Namespace::root_namespace()->add_named_object(context, name.value(), op_region))

View File

@ -5,7 +5,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct Register : public AML::Node struct Register final : public AML::Node
{ {
BAN::RefPtr<AML::Node> value; BAN::RefPtr<AML::Node> value;
@ -17,30 +17,22 @@ namespace Kernel::ACPI::AML
, value(value) , value(value)
{} {}
BAN::RefPtr<AML::Buffer> as_buffer() override; BAN::RefPtr<AML::Node> convert(uint8_t mask) override
BAN::RefPtr<AML::Integer> as_integer() override;
BAN::RefPtr<AML::String> as_string() override;
BAN::RefPtr<AML::Node> evaluate() override
{ {
if (value) if (!value)
return value->evaluate(); {
return {}; 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) if (value && value->type == AML::Node::Type::Reference)
return value->store(source); return value->store(source);
value = source->copy();
auto evaluated = source->evaluate(); return value;
if (!evaluated)
{
AML_ERROR("Failed to evaluate source for store");
return false;
}
value = evaluated->copy();
return true;
} }
void debug_print(int indent) const override void debug_print(int indent) const override

View File

@ -21,30 +21,34 @@ namespace Kernel::ACPI::AML
auto object_result = AML::parse_object(context); auto object_result = AML::parse_object(context);
if (!object_result.success()) if (!object_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto object = object_result.node()->evaluate(); auto object_node = object_result.node();
if (object && object->type == AML::Node::Type::Reference) if (!object_node)
object = static_cast<AML::Reference*>(object.ptr())->node->evaluate();
if (!object)
{ {
AML_ERROR("SizeOf object is null"); AML_ERROR("SizeOf object is null");
return ParseResult::Failure; 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; uint64_t size = 0;
switch (object->type) switch (object_node->type)
{ {
case AML::Node::Type::Buffer: 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; break;
case AML::Node::Type::String: 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; break;
case AML::Node::Type::Package: 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; break;
default: default:
AML_ERROR("SizeOf object is not a buffer, string or package ({})", static_cast<uint8_t>(object->type)); ASSERT_NOT_REACHED();
return ParseResult::Failure;
} }
return ParseResult(MUST(BAN::RefPtr<Integer>::create(size))); 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); auto sleep_time_result = AML::parse_object(context);
if (!sleep_time_result.success()) if (!sleep_time_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto sleep_time = sleep_time_result.node() ? sleep_time_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto sleep_time_node = sleep_time_result.node()
if (!sleep_time) ? 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"); AML_ERROR("Sleep time cannot be evaluated to an integer");
return ParseResult::Failure; return ParseResult::Failure;
} }
const auto sleep_time_value = static_cast<AML::Integer*>(sleep_time_node.ptr())->value;
#if AML_DEBUG_LEVEL >= 2 #if AML_DEBUG_LEVEL >= 2
AML_DEBUG_PRINTLN("Sleeping for {} ms", sleep_time->value); AML_DEBUG_PRINTLN("Sleeping for {} ms", sleep_time_value);
#endif #endif
SystemTimer::get().sleep_ms(sleep_time->value); SystemTimer::get().sleep_ms(sleep_time_value);
return ParseResult::Success; return ParseResult::Success;
} }
}; };

View File

@ -17,10 +17,10 @@ namespace Kernel::ACPI::AML
auto source_result = AML::parse_object(context); auto source_result = AML::parse_object(context);
if (!source_result.success()) if (!source_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto source = source_result.node() ? source_result.node()->evaluate() : BAN::RefPtr<AML::Node>(); auto source = source_result.node();
if (!source) if (!source)
{ {
AML_ERROR("Store source cannot be evaluated"); AML_ERROR("Store source is null");
return ParseResult::Failure; return ParseResult::Failure;
} }

View File

@ -7,7 +7,7 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct String : public AML::Node struct String final : public AML::Node
{ {
BAN::Vector<uint8_t> string; 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::Optional<bool> logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop);
BAN::RefPtr<AML::Buffer> as_buffer() override; BAN::RefPtr<AML::Node> convert(uint8_t mask) override;
BAN::RefPtr<AML::Node> evaluate() override
{
return this;
}
BAN::StringView string_view() const BAN::StringView string_view() const
{ {
@ -41,6 +36,9 @@ namespace Kernel::ACPI::AML
AML_DEBUG_PRINT_INDENT(indent); AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("String \"{}\"", string_view()); AML_DEBUG_PRINT("String \"{}\"", string_view());
} }
private:
BAN::RefPtr<AML::Buffer> as_buffer();
}; };
} }

View File

@ -9,12 +9,14 @@
namespace Kernel::ACPI::AML namespace Kernel::ACPI::AML
{ {
struct ThermalZone : public AML::Scope struct ThermalZone final : public AML::Scope
{ {
ThermalZone(NameSeg name) ThermalZone(NameSeg name)
: Scope(Node::Type::ThermalZone, name) : Scope(Node::Type::ThermalZone, name)
{} {}
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
static ParseResult parse(ParseContext& context) static ParseResult parse(ParseContext& context)
{ {
ASSERT(context.aml_data.size() >= 2); ASSERT(context.aml_data.size() >= 2);

View File

@ -29,14 +29,16 @@ namespace Kernel::ACPI::AML
auto predicate_result = AML::parse_object(context); auto predicate_result = AML::parse_object(context);
if (!predicate_result.success()) if (!predicate_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto predicate = predicate_result.node() ? predicate_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto predicate_node = predicate_result.node()
if (!predicate) ? predicate_result.node()->convert(AML::Node::ConvInteger)
: BAN::RefPtr<AML::Node>();
if (!predicate_node)
{ {
AML_ERROR("While predicate is not an integer"); AML_ERROR("While predicate is not an integer");
return ParseResult::Failure; return ParseResult::Failure;
} }
if (!predicate->value) if (!static_cast<AML::Integer*>(predicate_node.ptr())->value)
break; break;
while (context.aml_data.size() > 0) while (context.aml_data.size() > 0)

View File

@ -2,6 +2,7 @@
#include <BAN/StringView.h> #include <BAN/StringView.h>
#include <kernel/ACPI/ACPI.h> #include <kernel/ACPI/ACPI.h>
#include <kernel/ACPI/AML.h> #include <kernel/ACPI/AML.h>
#include <kernel/ACPI/AML/Alias.h>
#include <kernel/ACPI/AML/Device.h> #include <kernel/ACPI/AML/Device.h>
#include <kernel/ACPI/AML/Field.h> #include <kernel/ACPI/AML/Field.h>
#include <kernel/ACPI/AML/Integer.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)); auto field_element = MUST(BAN::RefPtr<AML::FieldElement>::create(""_sv, register_bit_offset, register_bit_width, field_rules));
field_element->op_region = op_region; field_element->op_region = op_region;
auto result = field_element->as_integer(); auto result = field_element->convert(AML::Node::ConvInteger);
if (!result) if (!result)
return {}; return {};
return result->value; return static_cast<AML::Integer*>(result.ptr())->value;
} }
bool GAS::write(uint64_t 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)); auto field_element = MUST(BAN::RefPtr<AML::FieldElement>::create(""_sv, register_bit_offset, register_bit_width, field_rules));
field_element->op_region = op_region; 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 enum PM1Event : uint16_t
@ -494,7 +495,25 @@ acpi_release_global_lock:
dwarnln("\\_S5 not found"); dwarnln("\\_S5 not found");
return; 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) if (!s5_evaluated)
{ {
dwarnln("Failed to evaluate \\_S5"); dwarnln("Failed to evaluate \\_S5");
@ -512,9 +531,9 @@ acpi_release_global_lock:
return; return;
} }
auto slp_typa = s5_package->elements[0]->as_integer(); auto slp_typa_node = s5_package->elements[0]->convert(AML::Node::ConvInteger);
auto slp_typb = s5_package->elements[1]->as_integer(); auto slp_typb_node = s5_package->elements[1]->convert(AML::Node::ConvInteger);
if (!slp_typa || !slp_typb) if (!slp_typa_node || !slp_typb_node)
{ {
dwarnln("Failed to get SLP_TYPx values"); dwarnln("Failed to get SLP_TYPx values");
return; return;
@ -525,9 +544,12 @@ acpi_release_global_lock:
dprintln("Entering sleep state S5"); 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); uint16_t pm1a_data = IO::inw(fadt().pm1a_cnt_blk);
pm1a_data &= ~(PM1_CNT_SLP_TYP_MASK << PM1_CNT_SLP_TYP_SHIFT); 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; pm1a_data |= PM1_CNT_SLP_EN;
IO::outw(fadt().pm1a_cnt_blk, pm1a_data); 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); uint16_t pm1b_data = IO::inw(fadt().pm1b_cnt_blk);
pm1b_data &= ~(PM1_CNT_SLP_TYP_MASK << PM1_CNT_SLP_TYP_SHIFT); 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; pm1b_data |= PM1_CNT_SLP_EN;
IO::outw(fadt().pm1b_cnt_blk, pm1b_data); 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())); 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) if (!source_integer)
{ {
AML_TODO("FieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type)); AML_TODO("FieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type));
return false; return {};
} }
op_region->mutex.lock(); op_region->mutex.lock();
@ -510,7 +511,9 @@ namespace Kernel::ACPI
ACPI::release_global_lock(); 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 void AML::FieldElement::debug_print(int indent) const
@ -626,28 +629,30 @@ namespace Kernel::ACPI
return MUST(BAN::RefPtr<Integer>::create(result.value())); 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) if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal)
{ {
AML_TODO("FieldElement with access attribute {}", static_cast<uint8_t>(access_rules.access_attrib)); AML_TODO("FieldElement with access attribute {}", static_cast<uint8_t>(access_rules.access_attrib));
return {}; return {};
} }
auto source_integer = source->as_integer();
ASSERT(source);
auto source_integer = source->convert(AML::Node::ConvInteger);
if (!source_integer) if (!source_integer)
{ {
AML_TODO("IndexFieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type)); 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); auto access_size = determine_access_size(access_rules.access_type);
if (!access_size.has_value()) if (!access_size.has_value())
return false; return {};
if (access_size.value() > data_element->bit_count) 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); 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> { 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 { auto write_func = [&](uint64_t byte_offset, uint64_t value) -> bool {
if (!index_element->store_internal(byte_offset)) if (!index_element->store_internal(byte_offset))
return false; return {};
return data_element->store_internal(value); return data_element->store_internal(value);
}; };
@ -670,10 +675,10 @@ namespace Kernel::ACPI
ACPI::release_global_lock(); 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)) const auto source_value = static_cast<AML::Integer*>(source_integer.ptr())->value;
return false; if (!perform_write_general(0, bit_count, bit_offset, access_size.value(), source_value, access_rules.update_rule, read_func, write_func))
return {};
return true; return source_integer;
} }
void AML::IndexFieldElement::debug_print(int indent) const void AML::IndexFieldElement::debug_print(int indent) const
@ -734,8 +739,8 @@ namespace Kernel::ACPI
context.aml_data = temp_aml_data; context.aml_data = temp_aml_data;
if (!bank_value_result.success()) if (!bank_value_result.success())
return ParseResult::Failure; return ParseResult::Failure;
auto bank_value = bank_value_result.node() ? bank_value_result.node()->as_integer() : BAN::RefPtr<AML::Integer>(); auto bank_value_node = bank_value_result.node() ? bank_value_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
if (!bank_value) if (!bank_value_node)
{ {
AML_ERROR("BankField BankValue is not an integer"); AML_ERROR("BankField BankValue is not an integer");
return ParseResult::Failure; return ParseResult::Failure;
@ -756,11 +761,12 @@ namespace Kernel::ACPI
if (!parse_field_element(field_context)) if (!parse_field_element(field_context))
return ParseResult::Failure; return ParseResult::Failure;
const auto bank_value = static_cast<AML::Integer*>(bank_value_node.ptr())->value;
for (auto& [_, element] : field_context.elements) for (auto& [_, element] : field_context.elements)
{ {
element->op_region = static_cast<OpRegion*>(op_region.ptr()); element->op_region = static_cast<OpRegion*>(op_region.ptr());
element->bank_selector = static_cast<FieldElement*>(bank_selector.ptr()); element->bank_selector = static_cast<FieldElement*>(bank_selector.ptr());
element->bank_value = bank_value->value; element->bank_value = bank_value;
NameString element_name; NameString element_name;
MUST(element_name.path.push_back(element->name)); MUST(element_name.path.push_back(element->name));
@ -776,7 +782,7 @@ namespace Kernel::ACPI
return ParseResult::Success; 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) if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal)
{ {
@ -812,7 +818,7 @@ namespace Kernel::ACPI
return MUST(BAN::RefPtr<Integer>::create(result.value())); 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) if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal)
{ {
@ -820,16 +826,17 @@ namespace Kernel::ACPI
return {}; return {};
} }
auto source_integer = source->as_integer(); ASSERT(source);
auto source_integer = source->convert(AML::Node::ConvInteger);
if (!source_integer) if (!source_integer)
{ {
AML_TODO("BankFieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type)); 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); auto access_size = determine_access_size(access_rules.access_type);
if (!access_size.has_value()) if (!access_size.has_value())
return false; return {};
auto read_func = [&](uint64_t byte_offset) -> BAN::Optional<uint64_t> { auto read_func = [&](uint64_t byte_offset) -> BAN::Optional<uint64_t> {
return perform_read(op_region->region_space, byte_offset, access_size.value()); return perform_read(op_region->region_space, byte_offset, access_size.value());
}; };
@ -852,7 +859,10 @@ namespace Kernel::ACPI
return {}; 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 void AML::BankFieldElement::debug_print(int indent) const

View File

@ -7,24 +7,6 @@
namespace Kernel::ACPI 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) AML::ParseResult AML::Name::parse(ParseContext& context)
{ {
ASSERT(context.aml_data.size() >= 1); ASSERT(context.aml_data.size() >= 1);

View File

@ -20,11 +20,12 @@ namespace Kernel::ACPI
struct DebugNode : AML::Node struct DebugNode : AML::Node
{ {
DebugNode() : AML::Node(AML::Node::Type::Debug) {} 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); node->debug_print(0);
AML_DEBUG_PRINTLN(""); AML_DEBUG_PRINTLN("");
return true; return node;
} }
void debug_print(int indent) const override 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)); auto osi = MUST(BAN::RefPtr<AML::Method>::create(NameSeg("_OSI"_sv), 1, false, 0));
osi->override_function = [](AML::ParseContext& context) -> BAN::RefPtr<AML::Node> { osi->override_function = [](AML::ParseContext& context) -> BAN::RefPtr<AML::Node> {
ASSERT(context.method_args[0]); 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) if (!arg || arg->type != AML::Node::Type::String)
{ {
AML_ERROR("Invalid _OSI argument"); AML_ERROR("Invalid _OSI argument");

View File

@ -36,24 +36,6 @@ namespace Kernel::ACPI
uint64_t AML::Node::total_node_count = 0; 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) AML::ParseResult AML::parse_object(AML::ParseContext& context)
{ {
if (context.aml_data.size() < 1) if (context.aml_data.size() < 1)
@ -204,6 +186,7 @@ namespace Kernel::ACPI
return AML::Notify::parse(context); return AML::Notify::parse(context);
case AML::Byte::SizeOfOp: case AML::Byte::SizeOfOp:
return AML::SizeOf::parse(context); return AML::SizeOf::parse(context);
case AML::Byte::BreakPointOp: // TODO: support breakpoints?
case AML::Byte::NoopOp: case AML::Byte::NoopOp:
context.aml_data = context.aml_data.slice(1); context.aml_data = context.aml_data.slice(1);
return ParseResult::Success; return ParseResult::Success;
@ -269,6 +252,9 @@ namespace Kernel::ACPI
return ParseResult::Success; return ParseResult::Success;
return ParseResult(result.value()); 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); 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); auto named_object = Namespace::root_namespace()->find_object(context.scope, name_string.value(), Namespace::FindMode::Normal);
if (!named_object) 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; return ParseResult::Success;
} }
if (!named_object->is_scope()) 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) static BAN::RefPtr<AML::Integer> evaluate_or_invoke(BAN::RefPtr<AML::Node> object)
{ {
if (object->type != AML::Node::Type::Method) 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()); auto* method = static_cast<AML::Method*>(object.ptr());
if (method->arg_count != 0) if (method->arg_count != 0)
@ -85,7 +90,10 @@ namespace Kernel::ACPI
return {}; 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) 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) 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) if (!rhs)
{ {
AML_ERROR("String logical compare RHS is not string"); AML_ERROR("String logical compare RHS is not string");
@ -27,6 +27,20 @@ namespace Kernel::ACPI::AML
return buffer; 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) ParseResult String::parse(ParseContext& context)
{ {
ASSERT(context.aml_data.size() >= 1); ASSERT(context.aml_data.size() >= 1);