Kernel: Fix and cleanup a lot of AML code
Node now have APIs to convert them to buffer, integer and string. This allows possibility to handle methods that need explicitly use one of the overloads instead of integer. This patch also adds handling of DebugOp. This is used quite heavily in uACPIs test suite.
This commit is contained in:
@@ -145,9 +145,9 @@ acpi_release_global_lock:
|
||||
field_element->op_region = op_region;
|
||||
|
||||
auto result = field_element->as_integer();
|
||||
if (!result.has_value())
|
||||
if (!result)
|
||||
return {};
|
||||
return result.value();
|
||||
return result->value;
|
||||
}
|
||||
|
||||
bool GAS::write(uint64_t value)
|
||||
@@ -514,7 +514,7 @@ acpi_release_global_lock:
|
||||
|
||||
auto slp_typa = s5_package->elements[0]->as_integer();
|
||||
auto slp_typb = s5_package->elements[1]->as_integer();
|
||||
if (!slp_typa.has_value() || !slp_typb.has_value())
|
||||
if (!slp_typa || !slp_typb)
|
||||
{
|
||||
dwarnln("Failed to get SLP_TYPx values");
|
||||
return;
|
||||
@@ -527,7 +527,7 @@ acpi_release_global_lock:
|
||||
|
||||
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 +535,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);
|
||||
}
|
||||
|
||||
@@ -479,7 +479,7 @@ namespace Kernel::ACPI
|
||||
return perform_write_general(op_region->region_offset, bit_count, bit_offset, access_size.value(), value, access_rules.update_rule, read_func, write_func);
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> AML::FieldElement::evaluate()
|
||||
BAN::RefPtr<AML::Integer> AML::FieldElement::as_integer()
|
||||
{
|
||||
op_region->mutex.lock();
|
||||
BAN::ScopeGuard unlock_guard([&] {
|
||||
@@ -495,7 +495,7 @@ namespace Kernel::ACPI
|
||||
bool AML::FieldElement::store(BAN::RefPtr<AML::Node> source)
|
||||
{
|
||||
auto source_integer = source->as_integer();
|
||||
if (!source_integer.has_value())
|
||||
if (!source_integer)
|
||||
{
|
||||
AML_TODO("FieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type));
|
||||
return false;
|
||||
@@ -510,7 +510,7 @@ namespace Kernel::ACPI
|
||||
ACPI::release_global_lock();
|
||||
});
|
||||
|
||||
return store_internal(source_integer.value());
|
||||
return store_internal(source_integer->value);
|
||||
}
|
||||
|
||||
void AML::FieldElement::debug_print(int indent) const
|
||||
@@ -590,7 +590,7 @@ namespace Kernel::ACPI
|
||||
return AML::ParseResult::Success;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> AML::IndexFieldElement::evaluate()
|
||||
BAN::RefPtr<AML::Integer> AML::IndexFieldElement::as_integer()
|
||||
{
|
||||
if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal)
|
||||
{
|
||||
@@ -634,7 +634,7 @@ namespace Kernel::ACPI
|
||||
return {};
|
||||
}
|
||||
auto source_integer = source->as_integer();
|
||||
if (!source_integer.has_value())
|
||||
if (!source_integer)
|
||||
{
|
||||
AML_TODO("IndexFieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type));
|
||||
return false;
|
||||
@@ -670,7 +670,7 @@ 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))
|
||||
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;
|
||||
@@ -734,8 +734,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::Optional<uint64_t>();
|
||||
if (!bank_value.has_value())
|
||||
auto bank_value = bank_value_result.node() ? bank_value_result.node()->as_integer() : BAN::RefPtr<AML::Integer>();
|
||||
if (!bank_value)
|
||||
{
|
||||
AML_ERROR("BankField BankValue is not an integer");
|
||||
return ParseResult::Failure;
|
||||
@@ -760,7 +760,7 @@ namespace Kernel::ACPI
|
||||
{
|
||||
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->value;
|
||||
|
||||
NameString element_name;
|
||||
MUST(element_name.path.push_back(element->name));
|
||||
@@ -821,7 +821,7 @@ namespace Kernel::ACPI
|
||||
}
|
||||
|
||||
auto source_integer = source->as_integer();
|
||||
if (!source_integer.has_value())
|
||||
if (!source_integer)
|
||||
{
|
||||
AML_TODO("BankFieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type));
|
||||
return false;
|
||||
@@ -852,7 +852,7 @@ 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);
|
||||
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);
|
||||
}
|
||||
|
||||
void AML::BankFieldElement::debug_print(int indent) const
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
#include <kernel/ACPI/AML/Buffer.h>
|
||||
#include <kernel/ACPI/AML/Integer.h>
|
||||
#include <kernel/ACPI/AML/NamedObject.h>
|
||||
#include <kernel/ACPI/AML/ParseContext.h>
|
||||
#include <kernel/ACPI/AML/String.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
BAN::RefPtr<AML::Buffer> AML::Name::as_buffer()
|
||||
{
|
||||
ASSERT(object);
|
||||
return object->as_buffer();
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Integer> AML::Name::as_integer()
|
||||
{
|
||||
ASSERT(object);
|
||||
return object->as_integer();
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::String> AML::Name::as_string()
|
||||
{
|
||||
ASSERT(object);
|
||||
return object->as_string();
|
||||
}
|
||||
|
||||
AML::ParseResult AML::Name::parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
@@ -20,7 +41,7 @@ namespace Kernel::ACPI
|
||||
|
||||
auto name = MUST(BAN::RefPtr<Name>::create(name_string.value().path.back(), object.node()));
|
||||
if (!Namespace::root_namespace()->add_named_object(context, name_string.value(), name))
|
||||
return ParseResult::Failure;
|
||||
return ParseResult::Success;
|
||||
|
||||
#if AML_DEBUG_LEVEL >= 2
|
||||
name->debug_print(0);
|
||||
|
||||
@@ -17,6 +17,24 @@ namespace Kernel::ACPI
|
||||
BAN::RefPtr<AML::Integer> AML::Integer::Constants::One;
|
||||
BAN::RefPtr<AML::Integer> AML::Integer::Constants::Ones;
|
||||
|
||||
struct DebugNode : AML::Node
|
||||
{
|
||||
DebugNode() : AML::Node(AML::Node::Type::Debug) {}
|
||||
bool store(BAN::RefPtr<AML::Node> node)
|
||||
{
|
||||
node->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
return true;
|
||||
}
|
||||
void debug_print(int indent) const override
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("DEBUG");
|
||||
}
|
||||
};
|
||||
|
||||
BAN::RefPtr<AML::Node> AML::Namespace::debug_node;
|
||||
|
||||
BAN::RefPtr<AML::Namespace> AML::Namespace::root_namespace()
|
||||
{
|
||||
ASSERT(s_root_namespace);
|
||||
@@ -147,7 +165,7 @@ namespace Kernel::ACPI
|
||||
|
||||
if (m_objects.contains(canonical_path.value()))
|
||||
{
|
||||
AML_ERROR("Object '{}' already exists", canonical_path.value());
|
||||
AML_PRINT("Object '{}' already exists", canonical_path.value());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -194,6 +212,9 @@ namespace Kernel::ACPI
|
||||
s_root_namespace = MUST(BAN::RefPtr<Namespace>::create(NameSeg("\\"_sv)));
|
||||
s_root_namespace->scope = AML::NameString("\\"_sv);
|
||||
|
||||
ASSERT(!Namespace::debug_node);
|
||||
Namespace::debug_node = MUST(BAN::RefPtr<DebugNode>::create());
|
||||
|
||||
Integer::Constants::Zero = MUST(BAN::RefPtr<Integer>::create(0, true));
|
||||
Integer::Constants::One = MUST(BAN::RefPtr<Integer>::create(1, true));
|
||||
Integer::Constants::Ones = MUST(BAN::RefPtr<Integer>::create(0xFFFFFFFFFFFFFFFF, true));
|
||||
|
||||
@@ -33,15 +33,21 @@ namespace Kernel::ACPI
|
||||
|
||||
uint64_t AML::Node::total_node_count = 0;
|
||||
|
||||
BAN::Optional<uint64_t> AML::Node::as_integer()
|
||||
BAN::RefPtr<AML::Buffer> AML::Node::as_buffer()
|
||||
{
|
||||
if (type == Type::Integer)
|
||||
return static_cast<const Integer*>(this)->value;
|
||||
auto evaluated = evaluate();
|
||||
if (!evaluated)
|
||||
return {};
|
||||
if (evaluated->type == Type::Integer)
|
||||
return static_cast<const Integer*>(evaluated.ptr())->value;
|
||||
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 {};
|
||||
}
|
||||
|
||||
@@ -83,6 +89,9 @@ namespace Kernel::ACPI
|
||||
return AML::Reference::parse(context);
|
||||
case AML::ExtOp::SleepOp:
|
||||
return AML::Sleep::parse(context);
|
||||
case AML::ExtOp::DebugOp:
|
||||
context.aml_data = context.aml_data.slice(2);
|
||||
return ParseResult(AML::Namespace::debug_node);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
30
kernel/kernel/ACPI/AML/Register.cpp
Normal file
30
kernel/kernel/ACPI/AML/Register.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <kernel/ACPI/AML/Buffer.h>
|
||||
#include <kernel/ACPI/AML/Integer.h>
|
||||
#include <kernel/ACPI/AML/Register.h>
|
||||
#include <kernel/ACPI/AML/String.h>
|
||||
|
||||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
BAN::RefPtr<AML::Buffer> Register::as_buffer()
|
||||
{
|
||||
if (value)
|
||||
return value->as_buffer();
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Integer> Register::as_integer()
|
||||
{
|
||||
if (value)
|
||||
return value->as_integer();
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::String> Register::as_string()
|
||||
{
|
||||
if (value)
|
||||
return value->as_string();
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,8 +25,8 @@ namespace Kernel::ACPI
|
||||
auto named_object = Namespace::root_namespace()->find_object(context.scope, name_string.value(), Namespace::FindMode::Normal);
|
||||
if (!named_object)
|
||||
{
|
||||
AML_ERROR("Scope '{}' not found in namespace", name_string.value());
|
||||
return ParseResult::Failure;
|
||||
AML_DEBUG_PRINT("Scope '{}' not found in namespace", name_string.value());
|
||||
return ParseResult::Success;
|
||||
}
|
||||
if (!named_object->is_scope())
|
||||
{
|
||||
@@ -66,7 +66,7 @@ namespace Kernel::ACPI
|
||||
return ParseResult::Success;
|
||||
}
|
||||
|
||||
static BAN::Optional<uint64_t> 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)
|
||||
return object->as_integer();
|
||||
@@ -85,7 +85,7 @@ namespace Kernel::ACPI
|
||||
return {};
|
||||
}
|
||||
|
||||
return result.value() ? result.value()->as_integer() : BAN::Optional<uint64_t>();
|
||||
return result.value() ? result.value()->as_integer() : BAN::RefPtr<AML::Integer>();
|
||||
}
|
||||
|
||||
bool AML::initialize_scope(BAN::RefPtr<AML::Scope> scope)
|
||||
@@ -138,14 +138,14 @@ namespace Kernel::ACPI
|
||||
if (auto sta = Namespace::root_namespace()->find_object(scope->scope, AML::NameString("_STA"_sv), Namespace::FindMode::ForceAbsolute))
|
||||
{
|
||||
auto result = evaluate_or_invoke(sta);
|
||||
if (!result.has_value())
|
||||
if (!result)
|
||||
{
|
||||
AML_ERROR("Failed to evaluate {}._STA, return value could not be resolved to integer", scope->scope);
|
||||
return false;
|
||||
}
|
||||
|
||||
run_ini = (result.value() & 0x01);
|
||||
init_children = run_ini || (result.value() & 0x02);
|
||||
run_ini = (result->value & 0x01);
|
||||
init_children = run_ini || (result->value & 0x02);
|
||||
}
|
||||
|
||||
if (run_ini)
|
||||
|
||||
58
kernel/kernel/ACPI/AML/String.cpp
Normal file
58
kernel/kernel/ACPI/AML/String.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include <kernel/ACPI/AML/Buffer.h>
|
||||
#include <kernel/ACPI/AML/String.h>
|
||||
|
||||
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>();
|
||||
if (!rhs)
|
||||
{
|
||||
AML_ERROR("String logical compare RHS is not string");
|
||||
return {};
|
||||
}
|
||||
|
||||
(void)binaryop;
|
||||
AML_TODO("Logical compare string");
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Buffer> String::as_buffer()
|
||||
{
|
||||
auto buffer = MUST(BAN::RefPtr<AML::Buffer>::create());
|
||||
MUST(buffer->buffer.resize(string.size()));
|
||||
for (size_t i = 0; i < string.size(); i++)
|
||||
buffer->buffer[i] = string[i];
|
||||
return buffer;
|
||||
}
|
||||
|
||||
ParseResult String::parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::StringPrefix);
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
|
||||
BAN::Vector<uint8_t> string;
|
||||
|
||||
while (context.aml_data.size() > 0)
|
||||
{
|
||||
if (context.aml_data[0] == 0x00)
|
||||
break;
|
||||
MUST(string.push_back(context.aml_data[0]));
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
}
|
||||
|
||||
if (context.aml_data.size() == 0)
|
||||
return ParseResult::Failure;
|
||||
if (context.aml_data[0] != 0x00)
|
||||
return ParseResult::Failure;
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
|
||||
auto string_node = MUST(BAN::RefPtr<String>::create());
|
||||
string_node->string = BAN::move(string);
|
||||
|
||||
return ParseResult(string_node);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user