#pragma once #include #include #include #include namespace Kernel::ACPI::AML { struct OpRegion final : public AML::NamedObject { using RegionSpace = GAS::AddressSpaceID; RegionSpace region_space; uint64_t region_offset; uint64_t region_length; Kernel::Mutex mutex; OpRegion(NameSeg name, RegionSpace region_space, uint64_t region_offset, uint64_t region_length) : NamedObject(Node::Type::OpRegion, name) , region_space(region_space) , region_offset(region_offset) , region_length(region_length) {} BAN::RefPtr convert(uint8_t) override { return {}; } static ParseResult parse(AML::ParseContext& context) { ASSERT(context.aml_data.size() > 2); ASSERT(static_cast(context.aml_data[0]) == Byte::ExtOpPrefix); ASSERT(static_cast(context.aml_data[1]) == ExtOp::OpRegionOp); context.aml_data = context.aml_data.slice(2); auto name = NameString::parse(context.aml_data); if (!name.has_value()) return ParseResult::Failure; if (context.aml_data.size() < 1) return ParseResult::Failure; auto region_space = static_cast(context.aml_data[0]); context.aml_data = context.aml_data.slice(1); auto offset_result = AML::parse_object(context); if (!offset_result.success()) return ParseResult::Failure; auto offset_node = offset_result.node() ? offset_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); if (!offset_node) { AML_ERROR("OpRegion offset must be an integer"); return ParseResult::Failure; } auto length_result = AML::parse_object(context); if (!length_result.success()) return ParseResult::Failure; auto length_node = length_result.node() ? length_result.node()->convert(AML::Node::ConvInteger) : BAN::RefPtr(); if (!length_node) { AML_ERROR("OpRegion length must be an integer"); return ParseResult::Failure; } const auto offset = static_cast(offset_node.ptr())->value; const auto length = static_cast(length_node.ptr())->value; auto op_region = MUST(BAN::RefPtr::create( name->path.back(), region_space, offset, length )); if (!Namespace::root_namespace()->add_named_object(context, name.value(), op_region)) return ParseResult::Success; #if AML_DEBUG_LEVEL >= 2 op_region->debug_print(0); AML_DEBUG_PRINTLN(""); #endif return ParseResult::Success; } virtual void debug_print(int indent) const override { BAN::StringView region_space_name; switch (region_space) { case RegionSpace::SystemMemory: region_space_name = "SystemMemory"_sv; break; case RegionSpace::SystemIO: region_space_name = "SystemIO"_sv; break; case RegionSpace::PCIConfig: region_space_name = "PCIConfig"_sv; break; case RegionSpace::EmbeddedController: region_space_name = "EmbeddedController"_sv; break; case RegionSpace::SMBus: region_space_name = "SMBus"_sv; break; case RegionSpace::SystemCMOS: region_space_name = "SystemCMOS"_sv; break; case RegionSpace::PCIBarTarget: region_space_name = "PCIBarTarget"_sv; break; case RegionSpace::IPMI: region_space_name = "IPMI"_sv; break; case RegionSpace::GeneralPurposeIO: region_space_name = "GeneralPurposeIO"_sv; break; case RegionSpace::GenericSerialBus: region_space_name = "GenericSerialBus"_sv; break; case RegionSpace::PlatformCommunicationChannel: region_space_name = "PlatformCommunicationChannel"_sv; break; default: region_space_name = "Unknown"_sv; break; } AML_DEBUG_PRINT_INDENT(indent); AML_DEBUG_PRINT("OperationRegion("); name.debug_print(); AML_DEBUG_PRINT(", {}, 0x{H}, 0x{H})", region_space_name, region_offset, region_length); } }; }