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:
@@ -2,6 +2,7 @@
|
||||
#include <BAN/StringView.h>
|
||||
#include <kernel/ACPI/ACPI.h>
|
||||
#include <kernel/ACPI/AML.h>
|
||||
#include <kernel/ACPI/AML/Alias.h>
|
||||
#include <kernel/ACPI/AML/Device.h>
|
||||
#include <kernel/ACPI/AML/Field.h>
|
||||
#include <kernel/ACPI/AML/Integer.h>
|
||||
@@ -144,10 +145,10 @@ acpi_release_global_lock:
|
||||
auto field_element = MUST(BAN::RefPtr<AML::FieldElement>::create(""_sv, register_bit_offset, register_bit_width, field_rules));
|
||||
field_element->op_region = op_region;
|
||||
|
||||
auto result = field_element->as_integer();
|
||||
auto result = field_element->convert(AML::Node::ConvInteger);
|
||||
if (!result)
|
||||
return {};
|
||||
return result->value;
|
||||
return static_cast<AML::Integer*>(result.ptr())->value;
|
||||
}
|
||||
|
||||
bool GAS::write(uint64_t value)
|
||||
@@ -168,7 +169,7 @@ acpi_release_global_lock:
|
||||
auto field_element = MUST(BAN::RefPtr<AML::FieldElement>::create(""_sv, register_bit_offset, register_bit_width, field_rules));
|
||||
field_element->op_region = op_region;
|
||||
|
||||
return field_element->store(MUST(BAN::RefPtr<AML::Integer>::create(value)));
|
||||
return !!field_element->store(MUST(BAN::RefPtr<AML::Integer>::create(value)));
|
||||
}
|
||||
|
||||
enum PM1Event : uint16_t
|
||||
@@ -494,7 +495,25 @@ acpi_release_global_lock:
|
||||
dwarnln("\\_S5 not found");
|
||||
return;
|
||||
}
|
||||
auto s5_evaluated = s5_object->evaluate();
|
||||
BAN::RefPtr<AML::Node> s5_evaluated = s5_object;
|
||||
while (true)
|
||||
{
|
||||
bool done = false;
|
||||
switch (s5_evaluated->type)
|
||||
{
|
||||
case AML::Node::Type::Alias:
|
||||
s5_evaluated = static_cast<AML::Alias*>(s5_evaluated.ptr())->target;
|
||||
break;
|
||||
case AML::Node::Type::Name:
|
||||
s5_evaluated = static_cast<AML::Name*>(s5_evaluated.ptr())->object;
|
||||
break;
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
if (done)
|
||||
break;
|
||||
}
|
||||
if (!s5_evaluated)
|
||||
{
|
||||
dwarnln("Failed to evaluate \\_S5");
|
||||
@@ -512,9 +531,9 @@ acpi_release_global_lock:
|
||||
return;
|
||||
}
|
||||
|
||||
auto slp_typa = s5_package->elements[0]->as_integer();
|
||||
auto slp_typb = s5_package->elements[1]->as_integer();
|
||||
if (!slp_typa || !slp_typb)
|
||||
auto slp_typa_node = s5_package->elements[0]->convert(AML::Node::ConvInteger);
|
||||
auto slp_typb_node = s5_package->elements[1]->convert(AML::Node::ConvInteger);
|
||||
if (!slp_typa_node || !slp_typb_node)
|
||||
{
|
||||
dwarnln("Failed to get SLP_TYPx values");
|
||||
return;
|
||||
@@ -525,9 +544,12 @@ acpi_release_global_lock:
|
||||
|
||||
dprintln("Entering sleep state S5");
|
||||
|
||||
const auto slp_typa_value = static_cast<AML::Integer*>(slp_typa_node.ptr())->value;
|
||||
const auto slp_typb_value = static_cast<AML::Integer*>(slp_typb_node.ptr())->value;
|
||||
|
||||
uint16_t pm1a_data = IO::inw(fadt().pm1a_cnt_blk);
|
||||
pm1a_data &= ~(PM1_CNT_SLP_TYP_MASK << PM1_CNT_SLP_TYP_SHIFT);
|
||||
pm1a_data |= (slp_typa->value & PM1_CNT_SLP_TYP_MASK) << PM1_CNT_SLP_TYP_SHIFT;
|
||||
pm1a_data |= (slp_typa_value & PM1_CNT_SLP_TYP_MASK) << PM1_CNT_SLP_TYP_SHIFT;
|
||||
pm1a_data |= PM1_CNT_SLP_EN;
|
||||
IO::outw(fadt().pm1a_cnt_blk, pm1a_data);
|
||||
|
||||
@@ -535,7 +557,7 @@ acpi_release_global_lock:
|
||||
{
|
||||
uint16_t pm1b_data = IO::inw(fadt().pm1b_cnt_blk);
|
||||
pm1b_data &= ~(PM1_CNT_SLP_TYP_MASK << PM1_CNT_SLP_TYP_SHIFT);
|
||||
pm1b_data |= (slp_typb->value & PM1_CNT_SLP_TYP_MASK) << PM1_CNT_SLP_TYP_SHIFT;
|
||||
pm1b_data |= (slp_typb_value & PM1_CNT_SLP_TYP_MASK) << PM1_CNT_SLP_TYP_SHIFT;
|
||||
pm1b_data |= PM1_CNT_SLP_EN;
|
||||
IO::outw(fadt().pm1b_cnt_blk, pm1b_data);
|
||||
}
|
||||
|
||||
@@ -492,13 +492,14 @@ namespace Kernel::ACPI
|
||||
return MUST(BAN::RefPtr<Integer>::create(result.value()));
|
||||
}
|
||||
|
||||
bool AML::FieldElement::store(BAN::RefPtr<AML::Node> source)
|
||||
BAN::RefPtr<AML::Node> AML::FieldElement::store(BAN::RefPtr<AML::Node> source)
|
||||
{
|
||||
auto source_integer = source->as_integer();
|
||||
ASSERT(source);
|
||||
auto source_integer = source->convert(AML::Node::ConvInteger);
|
||||
if (!source_integer)
|
||||
{
|
||||
AML_TODO("FieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type));
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
op_region->mutex.lock();
|
||||
@@ -510,7 +511,9 @@ namespace Kernel::ACPI
|
||||
ACPI::release_global_lock();
|
||||
});
|
||||
|
||||
return store_internal(source_integer->value);
|
||||
if (!store_internal(static_cast<AML::Integer*>(source_integer.ptr())->value))
|
||||
return {};
|
||||
return source_integer;
|
||||
}
|
||||
|
||||
void AML::FieldElement::debug_print(int indent) const
|
||||
@@ -626,28 +629,30 @@ namespace Kernel::ACPI
|
||||
return MUST(BAN::RefPtr<Integer>::create(result.value()));
|
||||
}
|
||||
|
||||
bool AML::IndexFieldElement::store(BAN::RefPtr<Node> source)
|
||||
BAN::RefPtr<AML::Node> AML::IndexFieldElement::store(BAN::RefPtr<Node> source)
|
||||
{
|
||||
if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal)
|
||||
{
|
||||
AML_TODO("FieldElement with access attribute {}", static_cast<uint8_t>(access_rules.access_attrib));
|
||||
return {};
|
||||
}
|
||||
auto source_integer = source->as_integer();
|
||||
|
||||
ASSERT(source);
|
||||
auto source_integer = source->convert(AML::Node::ConvInteger);
|
||||
if (!source_integer)
|
||||
{
|
||||
AML_TODO("IndexFieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type));
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto access_size = determine_access_size(access_rules.access_type);
|
||||
if (!access_size.has_value())
|
||||
return false;
|
||||
return {};
|
||||
|
||||
if (access_size.value() > data_element->bit_count)
|
||||
{
|
||||
AML_ERROR("IndexFieldElement write_field with access size {} > data element bit count {}", access_size.value(), data_element->bit_count);
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto read_func = [&](uint64_t byte_offset) -> BAN::Optional<uint64_t> {
|
||||
@@ -657,7 +662,7 @@ namespace Kernel::ACPI
|
||||
};
|
||||
auto write_func = [&](uint64_t byte_offset, uint64_t value) -> bool {
|
||||
if (!index_element->store_internal(byte_offset))
|
||||
return false;
|
||||
return {};
|
||||
return data_element->store_internal(value);
|
||||
};
|
||||
|
||||
@@ -670,10 +675,10 @@ namespace Kernel::ACPI
|
||||
ACPI::release_global_lock();
|
||||
});
|
||||
|
||||
if (!perform_write_general(0, bit_count, bit_offset, access_size.value(), source_integer->value, access_rules.update_rule, read_func, write_func))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
const auto source_value = static_cast<AML::Integer*>(source_integer.ptr())->value;
|
||||
if (!perform_write_general(0, bit_count, bit_offset, access_size.value(), source_value, access_rules.update_rule, read_func, write_func))
|
||||
return {};
|
||||
return source_integer;
|
||||
}
|
||||
|
||||
void AML::IndexFieldElement::debug_print(int indent) const
|
||||
@@ -734,8 +739,8 @@ namespace Kernel::ACPI
|
||||
context.aml_data = temp_aml_data;
|
||||
if (!bank_value_result.success())
|
||||
return ParseResult::Failure;
|
||||
auto bank_value = bank_value_result.node() ? bank_value_result.node()->as_integer() : BAN::RefPtr<AML::Integer>();
|
||||
if (!bank_value)
|
||||
auto bank_value_node = bank_value_result.node() ? bank_value_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr<AML::Node>();
|
||||
if (!bank_value_node)
|
||||
{
|
||||
AML_ERROR("BankField BankValue is not an integer");
|
||||
return ParseResult::Failure;
|
||||
@@ -756,11 +761,12 @@ namespace Kernel::ACPI
|
||||
if (!parse_field_element(field_context))
|
||||
return ParseResult::Failure;
|
||||
|
||||
const auto bank_value = static_cast<AML::Integer*>(bank_value_node.ptr())->value;
|
||||
for (auto& [_, element] : field_context.elements)
|
||||
{
|
||||
element->op_region = static_cast<OpRegion*>(op_region.ptr());
|
||||
element->bank_selector = static_cast<FieldElement*>(bank_selector.ptr());
|
||||
element->bank_value = bank_value->value;
|
||||
element->bank_value = bank_value;
|
||||
|
||||
NameString element_name;
|
||||
MUST(element_name.path.push_back(element->name));
|
||||
@@ -776,7 +782,7 @@ namespace Kernel::ACPI
|
||||
return ParseResult::Success;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> AML::BankFieldElement::evaluate()
|
||||
BAN::RefPtr<AML::Integer> AML::BankFieldElement::as_integer()
|
||||
{
|
||||
if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal)
|
||||
{
|
||||
@@ -812,7 +818,7 @@ namespace Kernel::ACPI
|
||||
return MUST(BAN::RefPtr<Integer>::create(result.value()));
|
||||
}
|
||||
|
||||
bool AML::BankFieldElement::store(BAN::RefPtr<AML::Node> source)
|
||||
BAN::RefPtr<AML::Node> AML::BankFieldElement::store(BAN::RefPtr<AML::Node> source)
|
||||
{
|
||||
if (access_rules.access_attrib != FieldRules::AccessAttrib::Normal)
|
||||
{
|
||||
@@ -820,16 +826,17 @@ namespace Kernel::ACPI
|
||||
return {};
|
||||
}
|
||||
|
||||
auto source_integer = source->as_integer();
|
||||
ASSERT(source);
|
||||
auto source_integer = source->convert(AML::Node::ConvInteger);
|
||||
if (!source_integer)
|
||||
{
|
||||
AML_TODO("BankFieldElement store with non-integer source, type {}", static_cast<uint8_t>(source->type));
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto access_size = determine_access_size(access_rules.access_type);
|
||||
if (!access_size.has_value())
|
||||
return false;
|
||||
return {};
|
||||
auto read_func = [&](uint64_t byte_offset) -> BAN::Optional<uint64_t> {
|
||||
return perform_read(op_region->region_space, byte_offset, access_size.value());
|
||||
};
|
||||
@@ -852,7 +859,10 @@ namespace Kernel::ACPI
|
||||
return {};
|
||||
}
|
||||
|
||||
return perform_write_general(op_region->region_offset, bit_count, bit_offset, access_size.value(), source_integer->value, access_rules.update_rule, read_func, write_func);
|
||||
const auto source_value = static_cast<AML::Integer*>(source_integer.ptr())->value;
|
||||
if (!perform_write_general(op_region->region_offset, bit_count, bit_offset, access_size.value(), source_value, access_rules.update_rule, read_func, write_func))
|
||||
return {};
|
||||
return source_integer;
|
||||
}
|
||||
|
||||
void AML::BankFieldElement::debug_print(int indent) const
|
||||
|
||||
@@ -7,24 +7,6 @@
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
BAN::RefPtr<AML::Buffer> AML::Name::as_buffer()
|
||||
{
|
||||
ASSERT(object);
|
||||
return object->as_buffer();
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Integer> AML::Name::as_integer()
|
||||
{
|
||||
ASSERT(object);
|
||||
return object->as_integer();
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::String> AML::Name::as_string()
|
||||
{
|
||||
ASSERT(object);
|
||||
return object->as_string();
|
||||
}
|
||||
|
||||
AML::ParseResult AML::Name::parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
|
||||
@@ -20,11 +20,12 @@ namespace Kernel::ACPI
|
||||
struct DebugNode : AML::Node
|
||||
{
|
||||
DebugNode() : AML::Node(AML::Node::Type::Debug) {}
|
||||
bool store(BAN::RefPtr<AML::Node> node)
|
||||
BAN::RefPtr<AML::Node> convert(uint8_t) override { return {}; }
|
||||
BAN::RefPtr<AML::Node> store(BAN::RefPtr<AML::Node> node)
|
||||
{
|
||||
node->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
return true;
|
||||
return node;
|
||||
}
|
||||
void debug_print(int indent) const override
|
||||
{
|
||||
@@ -236,7 +237,7 @@ namespace Kernel::ACPI
|
||||
auto osi = MUST(BAN::RefPtr<AML::Method>::create(NameSeg("_OSI"_sv), 1, false, 0));
|
||||
osi->override_function = [](AML::ParseContext& context) -> BAN::RefPtr<AML::Node> {
|
||||
ASSERT(context.method_args[0]);
|
||||
auto arg = context.method_args[0]->evaluate();
|
||||
auto arg = context.method_args[0]->convert(AML::Node::ConvString);
|
||||
if (!arg || arg->type != AML::Node::Type::String)
|
||||
{
|
||||
AML_ERROR("Invalid _OSI argument");
|
||||
|
||||
@@ -36,24 +36,6 @@ namespace Kernel::ACPI
|
||||
|
||||
uint64_t AML::Node::total_node_count = 0;
|
||||
|
||||
BAN::RefPtr<AML::Buffer> AML::Node::as_buffer()
|
||||
{
|
||||
AML_TODO("Node type {} to buffer", static_cast<uint32_t>(type));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Integer> AML::Node::as_integer()
|
||||
{
|
||||
AML_TODO("Node type {} to integer", static_cast<uint32_t>(type));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::String> AML::Node::as_string()
|
||||
{
|
||||
AML_TODO("Node type {} to string", static_cast<uint32_t>(type));
|
||||
return {};
|
||||
}
|
||||
|
||||
AML::ParseResult AML::parse_object(AML::ParseContext& context)
|
||||
{
|
||||
if (context.aml_data.size() < 1)
|
||||
@@ -204,6 +186,7 @@ namespace Kernel::ACPI
|
||||
return AML::Notify::parse(context);
|
||||
case AML::Byte::SizeOfOp:
|
||||
return AML::SizeOf::parse(context);
|
||||
case AML::Byte::BreakPointOp: // TODO: support breakpoints?
|
||||
case AML::Byte::NoopOp:
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
return ParseResult::Success;
|
||||
@@ -269,6 +252,9 @@ namespace Kernel::ACPI
|
||||
return ParseResult::Success;
|
||||
return ParseResult(result.value());
|
||||
}
|
||||
|
||||
if (aml_object->type == AML::Node::Type::Name)
|
||||
return ParseResult(static_cast<AML::Name*>(aml_object.ptr())->object);
|
||||
return ParseResult(aml_object);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#include <kernel/ACPI/AML/Buffer.h>
|
||||
#include <kernel/ACPI/AML/Integer.h>
|
||||
#include <kernel/ACPI/AML/Register.h>
|
||||
#include <kernel/ACPI/AML/String.h>
|
||||
|
||||
namespace Kernel::ACPI::AML
|
||||
{
|
||||
|
||||
BAN::RefPtr<AML::Buffer> Register::as_buffer()
|
||||
{
|
||||
if (value)
|
||||
return value->as_buffer();
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Integer> Register::as_integer()
|
||||
{
|
||||
if (value)
|
||||
return value->as_integer();
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::String> Register::as_string()
|
||||
{
|
||||
if (value)
|
||||
return value->as_string();
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace Kernel::ACPI
|
||||
auto named_object = Namespace::root_namespace()->find_object(context.scope, name_string.value(), Namespace::FindMode::Normal);
|
||||
if (!named_object)
|
||||
{
|
||||
AML_DEBUG_PRINT("Scope '{}' not found in namespace", name_string.value());
|
||||
AML_PRINT("Scope '{}' not found in namespace", name_string.value());
|
||||
return ParseResult::Success;
|
||||
}
|
||||
if (!named_object->is_scope())
|
||||
@@ -69,7 +69,12 @@ namespace Kernel::ACPI
|
||||
static BAN::RefPtr<AML::Integer> evaluate_or_invoke(BAN::RefPtr<AML::Node> object)
|
||||
{
|
||||
if (object->type != AML::Node::Type::Method)
|
||||
return object->as_integer();
|
||||
{
|
||||
auto converted = object->convert(AML::Node::ConvInteger);
|
||||
if (!converted)
|
||||
return {};
|
||||
return static_cast<AML::Integer*>(converted.ptr());
|
||||
}
|
||||
|
||||
auto* method = static_cast<AML::Method*>(object.ptr());
|
||||
if (method->arg_count != 0)
|
||||
@@ -85,7 +90,10 @@ namespace Kernel::ACPI
|
||||
return {};
|
||||
}
|
||||
|
||||
return result.value() ? result.value()->as_integer() : BAN::RefPtr<AML::Integer>();
|
||||
auto result_integer = result.value()
|
||||
? result.value()->convert(AML::Node::ConvInteger)
|
||||
: BAN::RefPtr<AML::Node>();
|
||||
return static_cast<AML::Integer*>(result_integer.ptr());
|
||||
}
|
||||
|
||||
bool AML::initialize_scope(BAN::RefPtr<AML::Scope> scope)
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Kernel::ACPI::AML
|
||||
|
||||
BAN::Optional<bool> String::logical_compare(BAN::RefPtr<AML::Node> node, AML::Byte binaryop)
|
||||
{
|
||||
auto rhs = node ? node->as_string() : BAN::RefPtr<AML::String>();
|
||||
auto rhs = node ? node->convert(AML::Node::ConvString) : BAN::RefPtr<AML::Node>();
|
||||
if (!rhs)
|
||||
{
|
||||
AML_ERROR("String logical compare RHS is not string");
|
||||
@@ -27,6 +27,20 @@ namespace Kernel::ACPI::AML
|
||||
return buffer;
|
||||
}
|
||||
|
||||
BAN::RefPtr<AML::Node> String::convert(uint8_t mask)
|
||||
{
|
||||
if (mask & AML::Node::ConvString)
|
||||
return this;
|
||||
if (mask & AML::Node::ConvInteger)
|
||||
{
|
||||
AML_TODO("Convert String to Integer");
|
||||
return {};
|
||||
}
|
||||
if (mask & AML::Node::ConvBuffer)
|
||||
return as_buffer();
|
||||
return {};
|
||||
}
|
||||
|
||||
ParseResult String::parse(ParseContext& context)
|
||||
{
|
||||
ASSERT(context.aml_data.size() >= 1);
|
||||
|
||||
Reference in New Issue
Block a user