Kernel: Implement more features for AML parser/interpreter
Added - BankField - BufferField - PowerResource - ThermalZone - Reference - Package element forward declare
This commit is contained in:
		
							parent
							
								
									93ddee5956
								
							
						
					
					
						commit
						afb1d7ef0c
					
				|  | @ -1,6 +1,7 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <kernel/ACPI/AML/Bytes.h> | ||||
| #include <kernel/ACPI/AML/Integer.h> | ||||
| #include <kernel/ACPI/AML/Node.h> | ||||
| #include <kernel/ACPI/AML/ParseContext.h> | ||||
| #include <kernel/ACPI/AML/Pkg.h> | ||||
|  | @ -12,7 +13,14 @@ namespace Kernel::ACPI::AML | |||
| 	{ | ||||
| 		BAN::Vector<uint8_t> buffer; | ||||
| 
 | ||||
| 		Buffer() : AML::Node(Node::Type::Buffer) {} | ||||
| 		Buffer() | ||||
| 			: AML::Node(Node::Type::Buffer) | ||||
| 		{} | ||||
| 
 | ||||
| 		BAN::RefPtr<AML::Node> evaluate() override | ||||
| 		{ | ||||
| 			return this; | ||||
| 		} | ||||
| 
 | ||||
| 		static ParseResult parse(AML::ParseContext& context) | ||||
| 		{ | ||||
|  | @ -57,4 +65,147 @@ namespace Kernel::ACPI::AML | |||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| 	struct BufferField : AML::NamedObject | ||||
| 	{ | ||||
| 		BAN::RefPtr<Buffer> buffer; | ||||
| 		size_t field_bit_offset; | ||||
| 		size_t field_bit_size; | ||||
| 
 | ||||
| 		BufferField(AML::NameSeg name, BAN::RefPtr<Buffer> buffer, size_t field_bit_offset, size_t field_bit_size) | ||||
| 			: AML::NamedObject(Node::Type::BufferField, name) | ||||
| 			, buffer(buffer) | ||||
| 			, field_bit_offset(field_bit_offset) | ||||
| 			, field_bit_size(field_bit_size) | ||||
| 		{} | ||||
| 
 | ||||
| 		BAN::RefPtr<AML::Node> evaluate() override | ||||
| 		{ | ||||
| 			ASSERT(buffer); | ||||
| 			ASSERT(field_bit_offset + field_bit_size <= buffer->buffer.size() * 8); | ||||
| 
 | ||||
| 			uint64_t value = 0; | ||||
| 			if (field_bit_size == 1) | ||||
| 			{ | ||||
| 				size_t byte_offset = field_bit_offset / 8; | ||||
| 				size_t bit_offset = field_bit_offset % 8; | ||||
| 				value = (buffer->buffer[byte_offset] >> bit_offset) & 1; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				ASSERT(field_bit_size % 8 == 0); | ||||
| 				for (size_t byte = 0; byte < field_bit_size / 8; byte++) | ||||
| 					value |= buffer->buffer[byte] << byte; | ||||
| 			} | ||||
| 
 | ||||
| 			return MUST(BAN::RefPtr<AML::Integer>::create(value)); | ||||
| 		} | ||||
| 
 | ||||
| 		bool store(BAN::RefPtr<AML::Node> node) override | ||||
| 		{ | ||||
| 			ASSERT(buffer); | ||||
| 			ASSERT(field_bit_offset + field_bit_size <= buffer->buffer.size() * 8); | ||||
| 
 | ||||
| 			auto value = node->as_integer(); | ||||
| 			if (!value.has_value()) | ||||
| 				return false; | ||||
| 
 | ||||
| 			if (field_bit_size == 1) | ||||
| 			{ | ||||
| 				size_t byte_offset = field_bit_offset / 8; | ||||
| 				size_t bit_offset = field_bit_offset % 8; | ||||
| 				buffer->buffer[byte_offset] &= ~(1 << bit_offset); | ||||
| 				buffer->buffer[byte_offset] |= (value.value() & 1) << bit_offset; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				ASSERT(field_bit_size % 8 == 0); | ||||
| 				for (size_t byte = 0; byte < field_bit_size / 8; byte++) | ||||
| 					buffer->buffer[byte] = (value.value() >> (byte * 8)) & 0xFF; | ||||
| 			} | ||||
| 
 | ||||
| 			return true; | ||||
| 		} | ||||
| 
 | ||||
| 		static ParseResult parse(AML::ParseContext& context) | ||||
| 		{ | ||||
| 			ASSERT(context.aml_data.size() >= 1); | ||||
| 
 | ||||
| 			size_t field_bit_size = 0; | ||||
| 			switch (static_cast<Byte>(context.aml_data[0])) | ||||
| 			{ | ||||
| 				case AML::Byte::CreateBitFieldOp: | ||||
| 					field_bit_size = 1; | ||||
| 					break; | ||||
| 				case AML::Byte::CreateByteFieldOp: | ||||
| 					field_bit_size = 8; | ||||
| 					break; | ||||
| 				case AML::Byte::CreateWordFieldOp: | ||||
| 					field_bit_size = 16; | ||||
| 					break; | ||||
| 				case AML::Byte::CreateDWordFieldOp: | ||||
| 					field_bit_size = 32; | ||||
| 					break; | ||||
| 				case AML::Byte::CreateQWordFieldOp: | ||||
| 					field_bit_size = 64; | ||||
| 					break; | ||||
| 				default: | ||||
| 					ASSERT_NOT_REACHED(); | ||||
| 			} | ||||
| 			context.aml_data = context.aml_data.slice(1); | ||||
| 
 | ||||
| 			auto buffer_result = AML::parse_object(context); | ||||
| 			if (!buffer_result.success()) | ||||
| 				return ParseResult::Failure; | ||||
| 			auto buffer_node = buffer_result.node() ? buffer_result.node()->evaluate() : nullptr; | ||||
| 			if (!buffer_node || buffer_node->type != Node::Type::Buffer) | ||||
| 			{ | ||||
| 				AML_ERROR("Buffer source does not evaluate to a Buffer"); | ||||
| 				return ParseResult::Failure; | ||||
| 			} | ||||
| 			auto buffer = static_cast<Buffer*>(buffer_node.ptr()); | ||||
| 
 | ||||
| 			auto index_result = AML::parse_object(context); | ||||
| 			if (!index_result.success()) | ||||
| 				return ParseResult::Failure; | ||||
| 			auto index = index_result.node() ? index_result.node()->as_integer() : BAN::Optional<uint64_t>(); | ||||
| 			if (!index.has_value()) | ||||
| 			{ | ||||
| 				AML_ERROR("Failed to parse index for BufferField"); | ||||
| 				return ParseResult::Failure; | ||||
| 			} | ||||
| 			size_t field_bit_offset = index.value(); | ||||
| 			if (field_bit_size != 1) | ||||
| 				field_bit_offset *= 8; | ||||
| 
 | ||||
| 			auto field_name = AML::NameString::parse(context.aml_data); | ||||
| 			if (!field_name.has_value()) | ||||
| 				return ParseResult::Failure; | ||||
| 			if (field_name->path.empty()) | ||||
| 			{ | ||||
| 				AML_ERROR("Empty field name for BufferField"); | ||||
| 				return ParseResult::Failure; | ||||
| 			} | ||||
| 
 | ||||
| 			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)) | ||||
| 				return ParseResult::Failure; | ||||
| 
 | ||||
| #if AML_DEBUG_LEVEL >= 2 | ||||
| 			field->debug_print(0); | ||||
| 			AML_DEBUG_PRINTLN(""); | ||||
| #endif | ||||
| 
 | ||||
| 			return ParseResult::Success; | ||||
| 		} | ||||
| 
 | ||||
| 		virtual void debug_print(int indent) const override | ||||
| 		{ | ||||
| 			AML_DEBUG_PRINT_INDENT(indent); | ||||
| 			AML_DEBUG_PRINT("BufferField {} at bit offset {} ({} bits) to { ", name, field_bit_offset, field_bit_size); | ||||
| 			buffer->debug_print(0); | ||||
| 			AML_DEBUG_PRINT(" }"); | ||||
| 		} | ||||
| 
 | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -35,6 +35,16 @@ namespace Kernel::ACPI::AML | |||
| 			WriteAsZeros = 2, | ||||
| 		}; | ||||
| 		UpdateRule update_rule; | ||||
| 
 | ||||
| 		enum class AccessAttrib | ||||
| 		{ | ||||
| 			Normal = 0, | ||||
| 			Bytes = 1, | ||||
| 			RawBytes = 2, | ||||
| 			RawProcessBytes = 3, | ||||
| 		}; | ||||
| 		AccessAttrib access_attrib = AccessAttrib::Normal; | ||||
| 		uint8_t access_length = 0; | ||||
| 	}; | ||||
| 
 | ||||
| 	struct FieldElement : public NamedObject | ||||
|  | @ -98,4 +108,30 @@ namespace Kernel::ACPI::AML | |||
| 		static ParseResult parse(ParseContext& context); | ||||
| 	}; | ||||
| 
 | ||||
| 	struct BankFieldElement : public NamedObject | ||||
| 	{ | ||||
| 		uint64_t bit_offset; | ||||
| 		uint64_t bit_count; | ||||
| 
 | ||||
| 		FieldRules access_rules; | ||||
| 
 | ||||
| 		BAN::RefPtr<OpRegion> op_region; | ||||
| 		BAN::RefPtr<NamedObject> bank_selector; | ||||
| 		uint64_t bank_value; | ||||
| 
 | ||||
| 		BankFieldElement(NameSeg name, uint64_t bit_offset, uint64_t bit_count, FieldRules access_rules) | ||||
| 			: NamedObject(Node::Type::BankFieldElement, name) | ||||
| 			, bit_offset(bit_offset) | ||||
| 			, bit_count(bit_count) | ||||
| 			, access_rules(access_rules) | ||||
| 		{} | ||||
| 
 | ||||
| 		void debug_print(int indent) const override; | ||||
| 	}; | ||||
| 
 | ||||
| 	struct BankField | ||||
| 	{ | ||||
| 		static ParseResult parse(ParseContext& context); | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,96 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <kernel/ACPI/AML/Buffer.h> | ||||
| #include <kernel/ACPI/AML/Node.h> | ||||
| #include <kernel/ACPI/AML/ParseContext.h> | ||||
| #include <kernel/ACPI/AML/Reference.h> | ||||
| 
 | ||||
| namespace Kernel::ACPI::AML | ||||
| { | ||||
| 
 | ||||
| 	struct Index | ||||
| 	{ | ||||
| 		static ParseResult parse(ParseContext& context) | ||||
| 		{ | ||||
| 			ASSERT(context.aml_data.size() >= 1); | ||||
| 			ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::IndexOp); | ||||
| 			context.aml_data = context.aml_data.slice(1); | ||||
| 
 | ||||
| 			auto source_result = AML::parse_object(context); | ||||
| 			if (!source_result.success()) | ||||
| 				return ParseResult::Failure; | ||||
| 			auto source = source_result.node() ? source_result.node()->evaluate() : BAN::RefPtr<AML::Node>(); | ||||
| 			if (!source) | ||||
| 			{ | ||||
| 				AML_ERROR("IndexOp source is null"); | ||||
| 				return ParseResult::Failure; | ||||
| 			} | ||||
| 
 | ||||
| 			auto index_result = AML::parse_object(context); | ||||
| 			if (!index_result.success()) | ||||
| 				return ParseResult::Failure; | ||||
| 			auto index = index_result.node() ? index_result.node()->as_integer() : BAN::Optional<uint64_t>(); | ||||
| 			if (!index.has_value()) | ||||
| 			{ | ||||
| 				AML_ERROR("IndexOp index is not an integer"); | ||||
| 				return ParseResult::Failure; | ||||
| 			} | ||||
| 
 | ||||
| 			BAN::RefPtr<AML::Reference> result; | ||||
| 			switch (source->type) | ||||
| 			{ | ||||
| 				case AML::Node::Type::Buffer: | ||||
| 				{ | ||||
| 					auto buffer = static_cast<AML::Buffer*>(source.ptr()); | ||||
| 					if (index.value() >= buffer->buffer.size()) | ||||
| 					{ | ||||
| 						AML_ERROR("IndexOp index is out of buffer bounds"); | ||||
| 						return ParseResult::Failure; | ||||
| 					} | ||||
| 					auto buffer_field = MUST(BAN::RefPtr<BufferField>::create(NameSeg(""sv), buffer, index.value() * 8, 8)); | ||||
| 					result = MUST(BAN::RefPtr<AML::Reference>::create(buffer_field)); | ||||
| 					break; | ||||
| 				} | ||||
| 				case AML::Node::Type::Package: | ||||
| 					AML_TODO("IndexOp source Package"); | ||||
| 					return ParseResult::Failure; | ||||
| 				case AML::Node::Type::String: | ||||
| 					AML_TODO("IndexOp source String"); | ||||
| 					return ParseResult::Failure; | ||||
| 				default: | ||||
| 					AML_ERROR("IndexOp source is not a Buffer, Package, or String"); | ||||
| 					return ParseResult::Failure; | ||||
| 			} | ||||
| 
 | ||||
| #if AML_DEBUG_LEVEL >= 2 | ||||
| 			AML_DEBUG_PRINT("Index {}, ", index.value()); | ||||
| 			source->debug_print(0); | ||||
| 			AML_DEBUG_PRINTLN(""); | ||||
| #endif | ||||
| 
 | ||||
| 			if (context.aml_data.size() < 1) | ||||
| 				return ParseResult::Failure; | ||||
| 
 | ||||
| 			if (context.aml_data[0] == 0x00) | ||||
| 				context.aml_data = context.aml_data.slice(1); | ||||
| 			else | ||||
| 			{ | ||||
| 				auto destination_result = AML::parse_object(context); | ||||
| 				if (!destination_result.success()) | ||||
| 					return ParseResult::Failure; | ||||
| 				auto destination = destination_result.node(); | ||||
| 				if (!destination) | ||||
| 				{ | ||||
| 					AML_ERROR("IndexOp failed to resolve destination"); | ||||
| 					return ParseResult::Failure; | ||||
| 				} | ||||
| 
 | ||||
| 				if (!destination->store(result)) | ||||
| 					return ParseResult::Failure; | ||||
| 			} | ||||
| 
 | ||||
| 			return ParseResult(result); | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  | @ -14,13 +14,16 @@ namespace Kernel::ACPI::AML | |||
| 	struct Integer : public Node | ||||
| 	{ | ||||
| 		static constexpr uint64_t Ones = -1; | ||||
| 		uint64_t value; | ||||
| 		const uint64_t value; | ||||
| 
 | ||||
| 		Integer(uint64_t value) : Node(Node::Type::Integer), value(value) {} | ||||
| 		Integer(uint64_t value) | ||||
| 			: Node(Node::Type::Integer) | ||||
| 			, value(value) | ||||
| 		{} | ||||
| 
 | ||||
| 		BAN::RefPtr<AML::Node> evaluate() override | ||||
| 		{ | ||||
| 			return MUST(BAN::RefPtr<Integer>::create(value)); | ||||
| 			return this; | ||||
| 		} | ||||
| 
 | ||||
| 		static ParseResult parse(BAN::ConstByteSpan& aml_data) | ||||
|  |  | |||
|  | @ -106,6 +106,23 @@ namespace Kernel::ACPI::AML | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		static bool can_parse(BAN::ConstByteSpan aml_data) | ||||
| 		{ | ||||
| 			if (aml_data.size() == 0) | ||||
| 				return false; | ||||
| 			switch (static_cast<AML::Byte>(aml_data[0])) | ||||
| 			{ | ||||
| 				case AML::Byte::RootChar: | ||||
| 				case AML::Byte::ParentPrefixChar: | ||||
| 				case AML::Byte::NullName: | ||||
| 				case AML::Byte::DualNamePrefix: | ||||
| 				case AML::Byte::MultiNamePrefix: | ||||
| 					return true; | ||||
| 				default: | ||||
| 					return is_lead_name_char(aml_data[0]); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		static BAN::Optional<NameString> parse(BAN::ConstByteSpan& aml_data) | ||||
| 		{ | ||||
| 			if (aml_data.size() == 0) | ||||
|  |  | |||
|  | @ -13,7 +13,9 @@ namespace Kernel::ACPI::AML | |||
| 	{ | ||||
| 		enum class Type | ||||
| 		{ | ||||
| 			BankFieldElement, | ||||
| 			Buffer, | ||||
| 			BufferField, | ||||
| 			Device, | ||||
| 			FieldElement, | ||||
| 			IndexFieldElement, | ||||
|  | @ -24,9 +26,12 @@ namespace Kernel::ACPI::AML | |||
| 			Namespace, | ||||
| 			OpRegion, | ||||
| 			Package, | ||||
| 			PowerResource, | ||||
| 			Processor, | ||||
| 			Reference, | ||||
| 			Register, | ||||
| 			String, | ||||
| 			ThermalZone, | ||||
| 		}; | ||||
| 		const Type type; | ||||
| 
 | ||||
|  | @ -35,9 +40,9 @@ namespace Kernel::ACPI::AML | |||
| 
 | ||||
| 		virtual bool is_scope() const { return false; } | ||||
| 
 | ||||
| 		BAN::Optional<uint64_t> as_integer(); | ||||
| 		virtual BAN::RefPtr<AML::Node> evaluate() { AML_TODO("evaluate, type {}", static_cast<uint8_t>(type)); return nullptr; } | ||||
| 		virtual bool store(BAN::RefPtr<AML::Node> source) { AML_TODO("store, type {}", static_cast<uint8_t>(type)); return false; } | ||||
| 		[[nodiscard]] BAN::Optional<uint64_t> as_integer(); | ||||
| 		[[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> source) { AML_TODO("store, type {}", static_cast<uint8_t>(type)); return false; } | ||||
| 
 | ||||
| 		virtual void debug_print(int indent) const = 0; | ||||
| 	}; | ||||
|  |  | |||
|  | @ -10,27 +10,40 @@ namespace Kernel::ACPI::AML | |||
| 
 | ||||
| 	struct Package : public AML::Node | ||||
| 	{ | ||||
| 		struct UnresolvedReference | ||||
| 		{ | ||||
| 			AML::NameString name; | ||||
| 			size_t index; | ||||
| 		}; | ||||
| 		BAN::Vector<UnresolvedReference> unresolved_references; | ||||
| 		AML::NameString scope; // Used for resolving references
 | ||||
| 
 | ||||
| 		BAN::Vector<BAN::RefPtr<AML::Node>> elements; | ||||
| 
 | ||||
| 		Package() : Node(Node::Type::Package) {} | ||||
| 		Package(BAN::Vector<BAN::RefPtr<AML::Node>>&& elements, BAN::Vector<UnresolvedReference>&& unresolved_references, AML::NameString scope) | ||||
| 			: Node(Node::Type::Package) | ||||
| 			, elements(BAN::move(elements)) | ||||
| 			, unresolved_references(BAN::move(unresolved_references)) | ||||
| 			, scope(scope) | ||||
| 		{} | ||||
| 
 | ||||
| 		BAN::RefPtr<AML::Node> evaluate() override | ||||
| 		{ | ||||
| 			BAN::Vector<BAN::RefPtr<AML::Node>> evaluated_elements; | ||||
| 			for (auto& element : elements) | ||||
| 			// resolve references
 | ||||
| 			for (auto& reference : unresolved_references) | ||||
| 			{ | ||||
| 				auto evaluated = element->evaluate(); | ||||
| 				if (!evaluated) | ||||
| 				auto object = Namespace::root_namespace()->find_object(scope, reference.name); | ||||
| 				if (!object) | ||||
| 				{ | ||||
| 					AML_ERROR("Failed to evaluate element in package"); | ||||
| 					AML_ERROR("Failed to resolve reference {} in package", reference.name); | ||||
| 					return {}; | ||||
| 				} | ||||
| 				evaluated_elements.push_back(evaluated); | ||||
| 				ASSERT(!elements[reference.index]); | ||||
| 				elements[reference.index] = object; | ||||
| 			} | ||||
| 			unresolved_references.clear(); | ||||
| 
 | ||||
| 			auto package = MUST(BAN::RefPtr<Package>::create()); | ||||
| 			package->elements = BAN::move(evaluated_elements); | ||||
| 			return package; | ||||
| 			return this; | ||||
| 		} | ||||
| 
 | ||||
| 		static ParseResult parse(AML::ParseContext& context) | ||||
|  | @ -52,18 +65,33 @@ namespace Kernel::ACPI::AML | |||
| 			package_context.aml_data = package_context.aml_data.slice(1); | ||||
| 
 | ||||
| 			BAN::Vector<BAN::RefPtr<AML::Node>> elements; | ||||
| 			BAN::Vector<UnresolvedReference> unresolved_references; | ||||
| 			while (elements.size() < num_elements && package_context.aml_data.size() > 0) | ||||
| 			{ | ||||
| 				auto element_result = AML::parse_object(package_context); | ||||
| 				if (!element_result.success()) | ||||
| 					return ParseResult::Failure; | ||||
| 				MUST(elements.push_back(element_result.node())); | ||||
| 				BAN::RefPtr<AML::Node> element; | ||||
| 
 | ||||
| 				// Store name strings as references
 | ||||
| 				if (AML::NameString::can_parse(package_context.aml_data)) | ||||
| 				{ | ||||
| 					auto name = AML::NameString::parse(package_context.aml_data); | ||||
| 					if (!name.has_value()) | ||||
| 						return ParseResult::Failure; | ||||
| 					MUST(unresolved_references.push_back(UnresolvedReference { .name = name.value(), .index = elements.size() })); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					auto element_result = AML::parse_object(package_context); | ||||
| 					if (!element_result.success()) | ||||
| 						return ParseResult::Failure; | ||||
| 					element = element_result.node(); | ||||
| 				} | ||||
| 
 | ||||
| 				MUST(elements.push_back(element)); | ||||
| 			} | ||||
| 			while (elements.size() < num_elements) | ||||
| 				MUST(elements.push_back(BAN::RefPtr<AML::Node>())); | ||||
| 
 | ||||
| 			auto package = MUST(BAN::RefPtr<Package>::create()); | ||||
| 			package->elements = BAN::move(elements); | ||||
| 			auto package = MUST(BAN::RefPtr<Package>::create(BAN::move(elements), BAN::move(unresolved_references), context.scope)); | ||||
| 			return ParseResult(package); | ||||
| 		} | ||||
| 
 | ||||
|  | @ -74,7 +102,11 @@ namespace Kernel::ACPI::AML | |||
| 			AML_DEBUG_PRINTLN(""); | ||||
| 			for (const auto& element : elements) | ||||
| 			{ | ||||
| 				element->debug_print(indent + 1); | ||||
| 				AML_DEBUG_PRINT_INDENT(indent + 1); | ||||
| 				if (element) | ||||
| 					element->debug_print(0); | ||||
| 				else | ||||
| 					AML_DEBUG_PRINT("Uninitialized"); | ||||
| 				AML_DEBUG_PRINTLN(""); | ||||
| 			} | ||||
| 			AML_DEBUG_PRINT_INDENT(indent); | ||||
|  |  | |||
|  | @ -0,0 +1,68 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <BAN/Endianness.h> | ||||
| #include <kernel/ACPI/AML/Bytes.h> | ||||
| #include <kernel/ACPI/AML/ParseContext.h> | ||||
| #include <kernel/ACPI/AML/Pkg.h> | ||||
| #include <kernel/ACPI/AML/Scope.h> | ||||
| 
 | ||||
| namespace Kernel::ACPI::AML | ||||
| { | ||||
| 
 | ||||
| 	struct PowerResource : public AML::Scope | ||||
| 	{ | ||||
| 		uint8_t system_level; | ||||
| 		uint16_t resource_order; | ||||
| 
 | ||||
| 		PowerResource(NameSeg name, uint8_t system_level, uint16_t resource_order) | ||||
| 			: Scope(Node::Type::PowerResource, name) | ||||
| 			, system_level(system_level) | ||||
| 			, resource_order(resource_order) | ||||
| 		{} | ||||
| 
 | ||||
| 		static ParseResult parse(ParseContext& context) | ||||
| 		{ | ||||
| 			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::PowerResOp); | ||||
| 			context.aml_data = context.aml_data.slice(2); | ||||
| 
 | ||||
| 			auto opt_power_res_pkg = AML::parse_pkg(context.aml_data); | ||||
| 			if (!opt_power_res_pkg.has_value()) | ||||
| 				return ParseResult::Failure; | ||||
| 			auto power_res_pkg = opt_power_res_pkg.value(); | ||||
| 
 | ||||
| 			auto name = NameString::parse(power_res_pkg); | ||||
| 			if (!name.has_value()) | ||||
| 				return ParseResult::Failure; | ||||
| 
 | ||||
| 			if (power_res_pkg.size() < 1) | ||||
| 				return ParseResult::Failure; | ||||
| 			uint8_t system_level = power_res_pkg[0]; | ||||
| 			power_res_pkg = power_res_pkg.slice(1); | ||||
| 
 | ||||
| 			if (power_res_pkg.size() < 2) | ||||
| 				return ParseResult::Failure; | ||||
| 			uint16_t resource_order = BAN::little_endian_to_host<uint16_t>(*reinterpret_cast<const uint16_t*>(power_res_pkg.data())); | ||||
| 			power_res_pkg = power_res_pkg.slice(2); | ||||
| 
 | ||||
| 			auto power_res = MUST(BAN::RefPtr<PowerResource>::create(name->path.back(), system_level, resource_order)); | ||||
| 			if (!Namespace::root_namespace()->add_named_object(context, name.value(), power_res)) | ||||
| 				return ParseResult::Failure; | ||||
| 
 | ||||
| #if AML_DEBUG_LEVEL >= 2 | ||||
| 			power_res->debug_print(0); | ||||
| 			AML_DEBUG_PRINTLN(""); | ||||
| #endif | ||||
| 
 | ||||
| 			return power_res->enter_context_and_parse_term_list(context, name.value(), power_res_pkg); | ||||
| 		} | ||||
| 
 | ||||
| 		virtual void debug_print(int indent) const override | ||||
| 		{ | ||||
| 			AML_DEBUG_PRINT_INDENT(indent); | ||||
| 			AML_DEBUG_PRINT("PowerResource {} (SystemLevel {}, ResourceOrder {})", name, system_level, resource_order); | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  | @ -29,42 +29,46 @@ namespace Kernel::ACPI::AML | |||
| 			ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::ProcessorOp); | ||||
| 			context.aml_data = context.aml_data.slice(2); | ||||
| 
 | ||||
| 			auto processor_pkg = AML::parse_pkg(context.aml_data); | ||||
| 			if (!processor_pkg.has_value()) | ||||
| 			auto opt_processor_pkg = AML::parse_pkg(context.aml_data); | ||||
| 			if (!opt_processor_pkg.has_value()) | ||||
| 				return ParseResult::Failure; | ||||
| 			auto processor_pkg = opt_processor_pkg.value(); | ||||
| 
 | ||||
| 			auto name = NameString::parse(processor_pkg.value()); | ||||
| 			auto name = NameString::parse(processor_pkg); | ||||
| 			if (!name.has_value()) | ||||
| 				return ParseResult::Failure; | ||||
| 
 | ||||
| 			if (processor_pkg->size() < 1) | ||||
| 			if (processor_pkg.size() < 1) | ||||
| 				return ParseResult::Failure; | ||||
| 			uint8_t id = processor_pkg.value()[0]; | ||||
| 			processor_pkg = processor_pkg->slice(1); | ||||
| 			uint8_t id = processor_pkg[0]; | ||||
| 			processor_pkg = processor_pkg.slice(1); | ||||
| 
 | ||||
| 			if (processor_pkg->size() < 4) | ||||
| 			if (processor_pkg.size() < 4) | ||||
| 				return ParseResult::Failure; | ||||
| 			uint32_t pblk_addr = BAN::little_endian_to_host<uint32_t>(*reinterpret_cast<const uint32_t*>(processor_pkg->data())); | ||||
| 			processor_pkg = processor_pkg->slice(4); | ||||
| 			uint32_t pblk_addr = BAN::little_endian_to_host<uint32_t>(*reinterpret_cast<const uint32_t*>(processor_pkg.data())); | ||||
| 			processor_pkg = processor_pkg.slice(4); | ||||
| 
 | ||||
| 			if (processor_pkg->size() < 1) | ||||
| 			if (processor_pkg.size() < 1) | ||||
| 				return ParseResult::Failure; | ||||
| 			uint8_t pblk_len = processor_pkg.value()[0]; | ||||
| 			processor_pkg = processor_pkg->slice(1); | ||||
| 			uint8_t pblk_len = processor_pkg[0]; | ||||
| 			processor_pkg = processor_pkg.slice(1); | ||||
| 
 | ||||
| 			auto processor = MUST(BAN::RefPtr<Processor>::create(name->path.back(), id, pblk_addr, pblk_len)); | ||||
| 			if (!Namespace::root_namespace()->add_named_object(context, name.value(), processor)) | ||||
| 				return ParseResult::Failure; | ||||
| 
 | ||||
| 			return processor->enter_context_and_parse_term_list(context, name.value(), processor_pkg.value()); | ||||
| #if AML_DEBUG_LEVEL >= 2 | ||||
| 			processor->debug_print(0); | ||||
| 			AML_DEBUG_PRINTLN(""); | ||||
| #endif | ||||
| 
 | ||||
| 			return processor->enter_context_and_parse_term_list(context, name.value(), processor_pkg); | ||||
| 		} | ||||
| 
 | ||||
| 		virtual void debug_print(int indent) const override | ||||
| 		{ | ||||
| 			AML_DEBUG_PRINT_INDENT(indent); | ||||
| 			AML_DEBUG_PRINT("Processor "); | ||||
| 			name.debug_print(); | ||||
| 			AML_DEBUG_PRINT(" (ID: {}, PBlkAddr: 0x{H}, PBlkLen: {})", id, pblk_addr, pblk_len); | ||||
| 			AML_DEBUG_PRINT("Processor {} (ID: {}, PBlkAddr: 0x{H}, PBlkLen: {})", name, id, pblk_addr, pblk_len); | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,155 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <kernel/ACPI/AML/Bytes.h> | ||||
| #include <kernel/ACPI/AML/Integer.h> | ||||
| #include <kernel/ACPI/AML/Node.h> | ||||
| #include <kernel/ACPI/AML/Names.h> | ||||
| #include <kernel/ACPI/AML/String.h> | ||||
| #include <kernel/ACPI/AML/ParseContext.h> | ||||
| 
 | ||||
| namespace Kernel::ACPI::AML | ||||
| { | ||||
| 
 | ||||
| 	struct Reference : public AML::Node | ||||
| 	{ | ||||
| 		BAN::RefPtr<AML::Node> node; | ||||
| 
 | ||||
| 		Reference(BAN::RefPtr<AML::Node> node) | ||||
| 			: Node(AML::Node::Type::Reference) | ||||
| 			, node(node) | ||||
| 		{ | ||||
| 			ASSERT(node); | ||||
| 		} | ||||
| 
 | ||||
| 		BAN::RefPtr<AML::Node> evaluate() override | ||||
| 		{ | ||||
| 			return this; | ||||
| 		} | ||||
| 
 | ||||
| 		static ParseResult parse(ParseContext& context) | ||||
| 		{ | ||||
| 			ASSERT(context.aml_data.size() >= 1); | ||||
| 
 | ||||
| 			bool conditional = false; | ||||
| 			switch (static_cast<AML::Byte>(context.aml_data[0])) | ||||
| 			{ | ||||
| 				case AML::Byte::DerefOfOp: | ||||
| 					return parse_dereference(context); | ||||
| 				case AML::Byte::RefOfOp: | ||||
| 					context.aml_data = context.aml_data.slice(1); | ||||
| 					conditional = false; | ||||
| 					break; | ||||
| 				case AML::Byte::ExtOpPrefix: | ||||
| 					ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::CondRefOfOp); | ||||
| 					context.aml_data = context.aml_data.slice(2); | ||||
| 					conditional = true; | ||||
| 					break; | ||||
| 				default: | ||||
| 					ASSERT_NOT_REACHED(); | ||||
| 			} | ||||
| 
 | ||||
| 			BAN::RefPtr<AML::Node> object; | ||||
| 			if (NameString::can_parse(context.aml_data)) | ||||
| 			{ | ||||
| 				auto name = NameString::parse(context.aml_data); | ||||
| 				if (!name.has_value()) | ||||
| 					return ParseResult::Failure; | ||||
| 				object = Namespace::root_namespace()->find_object(context.scope, name.value()); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				auto parse_result = AML::parse_object(context); | ||||
| 				if (!parse_result.success()) | ||||
| 					return ParseResult::Failure; | ||||
| 				object = parse_result.node(); | ||||
| 			} | ||||
| 
 | ||||
| 			if (!conditional) | ||||
| 			{ | ||||
| 				if (!object) | ||||
| 				{ | ||||
| 					AML_ERROR("RefOf failed to resolve reference"); | ||||
| 					return ParseResult::Failure; | ||||
| 				} | ||||
| 				auto reference = MUST(BAN::RefPtr<Reference>::create(object)); | ||||
| #if AML_DEBUG_LEVEL >= 2 | ||||
| 				reference->debug_print(0); | ||||
| 				AML_DEBUG_PRINTLN(""); | ||||
| #endif | ||||
| 				return ParseResult(reference); | ||||
| 			} | ||||
| 
 | ||||
| 			if (context.aml_data.size() >= 1 && context.aml_data[0] != 0x00) | ||||
| 			{ | ||||
| 				auto target_result = AML::parse_object(context); | ||||
| 				if (!target_result.success()) | ||||
| 					return ParseResult::Failure; | ||||
| 				auto target_node = target_result.node(); | ||||
| 				if (!target_node) | ||||
| 				{ | ||||
| 					AML_ERROR("CondRefOf failed to resolve target"); | ||||
| 					return ParseResult::Failure; | ||||
| 				} | ||||
| 				target_node->store(MUST(BAN::RefPtr<Reference>::create(object))); | ||||
| 			} | ||||
| 
 | ||||
| #if AML_DEBUG_LEVEL >= 2 | ||||
| 			AML_DEBUG_PRINT("CondRefOf "); | ||||
| 			if (object) | ||||
| 				object->debug_print(0); | ||||
| 			else | ||||
| 				AML_DEBUG_PRINT("null"); | ||||
| 			AML_DEBUG_PRINTLN(""); | ||||
| #endif | ||||
| 
 | ||||
| 			auto return_value = MUST(BAN::RefPtr<Integer>::create(object ? Integer::Ones : 0)); | ||||
| 			return AML::ParseResult(return_value); | ||||
| 		} | ||||
| 
 | ||||
| 		static ParseResult parse_dereference(ParseContext& context) | ||||
| 		{ | ||||
| 			ASSERT(context.aml_data.size() >= 1); | ||||
| 			ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::DerefOfOp); | ||||
| 			context.aml_data = context.aml_data.slice(1); | ||||
| 
 | ||||
| 			if (context.aml_data.size() >= 1 && static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::StringPrefix) | ||||
| 			{ | ||||
| 				auto string_result = AML::String::parse(context); | ||||
| 				if (!string_result.success()) | ||||
| 					return ParseResult::Failure; | ||||
| 				ASSERT(string_result.node()); | ||||
| 				auto string = static_cast<AML::String*>(string_result.node().ptr()); | ||||
| 				AML_TODO("DerefOf String ({})", string->string); | ||||
| 				return ParseResult::Failure; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				auto parse_result = AML::parse_object(context); | ||||
| 				if (!parse_result.success()) | ||||
| 					return ParseResult::Failure; | ||||
| 				auto object = parse_result.node(); | ||||
| 				if (!object || object->type != AML::Node::Type::Reference) | ||||
| 				{ | ||||
| 					AML_TODO("DerefOf source is not a Reference, but a {}", object ? static_cast<uint8_t>(object->type) : 999); | ||||
| 					return ParseResult::Failure; | ||||
| 				} | ||||
| #if AML_DEBUG_LEVEL >= 2 | ||||
| 				AML_DEBUG_PRINT("DerefOf "); | ||||
| 				object->debug_print(0); | ||||
| 				AML_DEBUG_PRINTLN(""); | ||||
| #endif | ||||
| 				return ParseResult(static_cast<Reference*>(object.ptr())->node); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		virtual void debug_print(int indent) const override | ||||
| 		{ | ||||
| 			AML_DEBUG_PRINT_INDENT(indent); | ||||
| 			AML_DEBUG_PRINTLN("Reference {"); | ||||
| 			node->debug_print(indent + 1); | ||||
| 			AML_DEBUG_PRINT_INDENT(indent); | ||||
| 			AML_DEBUG_PRINT("}"); | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,53 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <BAN/Endianness.h> | ||||
| #include <kernel/ACPI/AML/Bytes.h> | ||||
| #include <kernel/ACPI/AML/ParseContext.h> | ||||
| #include <kernel/ACPI/AML/Pkg.h> | ||||
| #include <kernel/ACPI/AML/Scope.h> | ||||
| 
 | ||||
| namespace Kernel::ACPI::AML | ||||
| { | ||||
| 
 | ||||
| 	struct ThermalZone : public AML::Scope | ||||
| 	{ | ||||
| 		ThermalZone(NameSeg name) | ||||
| 			: Scope(Node::Type::ThermalZone, name) | ||||
| 		{} | ||||
| 
 | ||||
| 		static ParseResult parse(ParseContext& context) | ||||
| 		{ | ||||
| 			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::PowerResOp); | ||||
| 			context.aml_data = context.aml_data.slice(2); | ||||
| 
 | ||||
| 			auto opt_thermal_zone_pkg = AML::parse_pkg(context.aml_data); | ||||
| 			if (!opt_thermal_zone_pkg.has_value()) | ||||
| 				return ParseResult::Failure; | ||||
| 			auto thermal_zone_pkg = opt_thermal_zone_pkg.value(); | ||||
| 
 | ||||
| 			auto name = NameString::parse(thermal_zone_pkg); | ||||
| 			if (!name.has_value()) | ||||
| 				return ParseResult::Failure; | ||||
| 
 | ||||
| 			auto thermal_zone = MUST(BAN::RefPtr<ThermalZone>::create(name->path.back())); | ||||
| 			if (!Namespace::root_namespace()->add_named_object(context, name.value(), thermal_zone)) | ||||
| 				return ParseResult::Failure; | ||||
| 
 | ||||
| #if AML_DEBUG_LEVEL >= 2 | ||||
| 			thermal_zone->debug_print(0); | ||||
| 			AML_DEBUG_PRINTLN(""); | ||||
| #endif | ||||
| 
 | ||||
| 			return thermal_zone->enter_context_and_parse_term_list(context, name.value(), thermal_zone_pkg); | ||||
| 		} | ||||
| 
 | ||||
| 		virtual void debug_print(int indent) const override | ||||
| 		{ | ||||
| 			AML_DEBUG_PRINT_INDENT(indent); | ||||
| 			AML_DEBUG_PRINT("ThermalZone {}", name); | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  | @ -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); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue