forked from Bananymous/banan-os
Kernel: Implement more features for AML parser/interpreter
Added - BankField - BufferField - PowerResource - ThermalZone - Reference - Package element forward declare
This commit is contained in:
@@ -607,4 +607,100 @@ namespace Kernel::ACPI
|
||||
);
|
||||
}
|
||||
|
||||
AML::ParseResult AML::BankField::parse(ParseContext& context)
|
||||
{
|
||||
// BankFieldOp PkgLength NameString NameString BankValue FieldFlags FieldList
|
||||
|
||||
ASSERT(context.aml_data.size() >= 2);
|
||||
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix);
|
||||
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::BankFieldOp);
|
||||
context.aml_data = context.aml_data.slice(2);
|
||||
|
||||
auto opt_field_pkg = AML::parse_pkg(context.aml_data);
|
||||
if (!opt_field_pkg.has_value())
|
||||
return ParseResult::Failure;
|
||||
auto field_pkg = opt_field_pkg.release_value();
|
||||
|
||||
auto op_region_name = NameString::parse(field_pkg);
|
||||
if (!op_region_name.has_value())
|
||||
return ParseResult::Failure;
|
||||
auto op_region = Namespace::root_namespace()->find_object(context.scope, op_region_name.value());
|
||||
if (!op_region || op_region->type != AML::Node::Type::OpRegion)
|
||||
{
|
||||
AML_ERROR("BankField RegionName {} does not name a valid OpRegion", op_region_name.value());
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
auto bank_selector_name = NameString::parse(field_pkg);
|
||||
if (!bank_selector_name.has_value())
|
||||
return ParseResult::Failure;
|
||||
auto bank_selector = Namespace::root_namespace()->find_object(context.scope, bank_selector_name.value());
|
||||
if (!bank_selector)
|
||||
{
|
||||
AML_ERROR("BankField BankSelector {} does not name a valid object", bank_selector_name.value());
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
auto temp_aml_data = context.aml_data;
|
||||
context.aml_data = field_pkg;
|
||||
auto bank_value_result = AML::parse_object(context);
|
||||
field_pkg = context.aml_data;
|
||||
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())
|
||||
{
|
||||
AML_ERROR("BankField BankValue is not an integer");
|
||||
return ParseResult::Failure;
|
||||
}
|
||||
|
||||
if (field_pkg.size() < 1)
|
||||
return ParseResult::Failure;
|
||||
auto field_flags = field_pkg[0];
|
||||
field_pkg = field_pkg.slice(1);
|
||||
|
||||
ParseFieldElementContext<BankFieldElement> field_context;
|
||||
field_context.field_rules.access_type = static_cast<FieldRules::AccessType>(field_flags & 0x0F);
|
||||
field_context.field_rules.lock_rule = static_cast<FieldRules::LockRule>((field_flags >> 4) & 0x01);
|
||||
field_context.field_rules.update_rule = static_cast<FieldRules::UpdateRule>((field_flags >> 5) & 0x03);
|
||||
field_context.field_bit_offset = 0;
|
||||
field_context.field_pkg = field_pkg;
|
||||
while (field_context.field_pkg.size() > 0)
|
||||
if (!parse_field_element(field_context))
|
||||
return ParseResult::Failure;
|
||||
|
||||
for (auto& [_, element] : field_context.elements)
|
||||
{
|
||||
element->op_region = static_cast<OpRegion*>(op_region.ptr());
|
||||
element->bank_selector = bank_selector;
|
||||
element->bank_value = bank_value.value();
|
||||
|
||||
NameString element_name;
|
||||
MUST(element_name.path.push_back(element->name));
|
||||
if (!Namespace::root_namespace()->add_named_object(context, element_name, element))
|
||||
return ParseResult::Failure;
|
||||
|
||||
#if AML_DEBUG_LEVEL >= 2
|
||||
element->debug_print(0);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
#endif
|
||||
}
|
||||
|
||||
return ParseResult::Success;
|
||||
}
|
||||
|
||||
void AML::BankFieldElement::debug_print(int indent) const
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("BankFieldElement {} ({}, offset {}, OpRegion {}, BankSelector {}, BankValue {H})",
|
||||
name,
|
||||
bit_count,
|
||||
bit_offset,
|
||||
op_region->name,
|
||||
bank_selector->name,
|
||||
bank_value
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,12 +33,8 @@ namespace Kernel::ACPI
|
||||
void AML::Name::debug_print(int indent) const
|
||||
{
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("Name ");
|
||||
name.debug_print();
|
||||
AML_DEBUG_PRINTLN(" {");
|
||||
object->debug_print(indent + 1);
|
||||
AML_DEBUG_PRINTLN("");
|
||||
AML_DEBUG_PRINT_INDENT(indent);
|
||||
AML_DEBUG_PRINT("Name {} { ", name);
|
||||
object->debug_print(0);
|
||||
AML_DEBUG_PRINT("}");
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <kernel/ACPI/AML/Expression.h>
|
||||
#include <kernel/ACPI/AML/Field.h>
|
||||
#include <kernel/ACPI/AML/IfElse.h>
|
||||
#include <kernel/ACPI/AML/Index.h>
|
||||
#include <kernel/ACPI/AML/Integer.h>
|
||||
#include <kernel/ACPI/AML/Method.h>
|
||||
#include <kernel/ACPI/AML/Mutex.h>
|
||||
@@ -11,10 +12,13 @@
|
||||
#include <kernel/ACPI/AML/Node.h>
|
||||
#include <kernel/ACPI/AML/Package.h>
|
||||
#include <kernel/ACPI/AML/ParseContext.h>
|
||||
#include <kernel/ACPI/AML/PowerResource.h>
|
||||
#include <kernel/ACPI/AML/Processor.h>
|
||||
#include <kernel/ACPI/AML/Reference.h>
|
||||
#include <kernel/ACPI/AML/Region.h>
|
||||
#include <kernel/ACPI/AML/Store.h>
|
||||
#include <kernel/ACPI/AML/String.h>
|
||||
#include <kernel/ACPI/AML/ThermalZone.h>
|
||||
#include <kernel/ACPI/AML/Utils.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
@@ -31,7 +35,7 @@ namespace Kernel::ACPI
|
||||
if (!evaluated)
|
||||
return {};
|
||||
if (evaluated->type == Type::Integer)
|
||||
return static_cast<const Integer*>(this)->value;
|
||||
return static_cast<const Integer*>(evaluated.ptr())->value;
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -51,6 +55,8 @@ namespace Kernel::ACPI
|
||||
return AML::Field::parse(context);
|
||||
case AML::ExtOp::IndexFieldOp:
|
||||
return AML::IndexField::parse(context);
|
||||
case AML::ExtOp::BankFieldOp:
|
||||
return AML::BankField::parse(context);
|
||||
case AML::ExtOp::OpRegionOp:
|
||||
return AML::OpRegion::parse(context);
|
||||
case AML::ExtOp::DeviceOp:
|
||||
@@ -61,6 +67,12 @@ namespace Kernel::ACPI
|
||||
return AML::Mutex::parse(context);
|
||||
case AML::ExtOp::ProcessorOp:
|
||||
return AML::Processor::parse(context);
|
||||
case AML::ExtOp::PowerResOp:
|
||||
return AML::PowerResource::parse(context);
|
||||
case AML::ExtOp::ThermalZoneOp:
|
||||
return AML::ThermalZone::parse(context);
|
||||
case AML::ExtOp::CondRefOfOp:
|
||||
return AML::Reference::parse(context);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -128,6 +140,12 @@ namespace Kernel::ACPI
|
||||
case AML::Byte::SubtractOp:
|
||||
case AML::Byte::XorOp:
|
||||
return AML::Expression::parse(context);
|
||||
case AML::Byte::CreateBitFieldOp:
|
||||
case AML::Byte::CreateByteFieldOp:
|
||||
case AML::Byte::CreateWordFieldOp:
|
||||
case AML::Byte::CreateDWordFieldOp:
|
||||
case AML::Byte::CreateQWordFieldOp:
|
||||
return AML::BufferField::parse(context);
|
||||
case AML::Byte::NameOp:
|
||||
return AML::Name::parse(context);
|
||||
case AML::Byte::PackageOp:
|
||||
@@ -142,6 +160,11 @@ namespace Kernel::ACPI
|
||||
return AML::IfElse::parse(context);
|
||||
case AML::Byte::StoreOp:
|
||||
return AML::Store::parse(context);
|
||||
case AML::Byte::DerefOfOp:
|
||||
case AML::Byte::RefOfOp:
|
||||
return AML::Reference::parse(context);
|
||||
case AML::Byte::IndexOp:
|
||||
return AML::Index::parse(context);
|
||||
case AML::Byte::ReturnOp:
|
||||
{
|
||||
context.aml_data = context.aml_data.slice(1);
|
||||
|
||||
Reference in New Issue
Block a user