brintos

brintos / linux-shallow public Read only

0
0
Text · 15.9 KiB · f7b8496 Raw
597 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: dswload - Dispatcher first pass namespace load callbacks5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acparser.h"13#include "amlcode.h"14#include "acdispat.h"15#include "acinterp.h"16#include "acnamesp.h"17#ifdef ACPI_ASL_COMPILER18#include "acdisasm.h"19#endif20 21#define _COMPONENT          ACPI_DISPATCHER22ACPI_MODULE_NAME("dswload")23 24/*******************************************************************************25 *26 * FUNCTION:    acpi_ds_init_callbacks27 *28 * PARAMETERS:  walk_state      - Current state of the parse tree walk29 *              pass_number     - 1, 2, or 330 *31 * RETURN:      Status32 *33 * DESCRIPTION: Init walk state callbacks34 *35 ******************************************************************************/36acpi_status37acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)38{39 40	switch (pass_number) {41	case 0:42 43		/* Parse only - caller will setup callbacks */44 45		walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |46		    ACPI_PARSE_DELETE_TREE | ACPI_PARSE_DISASSEMBLE;47		walk_state->descending_callback = NULL;48		walk_state->ascending_callback = NULL;49		break;50 51	case 1:52 53		/* Load pass 1 */54 55		walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |56		    ACPI_PARSE_DELETE_TREE;57		walk_state->descending_callback = acpi_ds_load1_begin_op;58		walk_state->ascending_callback = acpi_ds_load1_end_op;59		break;60 61	case 2:62 63		/* Load pass 2 */64 65		walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |66		    ACPI_PARSE_DELETE_TREE;67		walk_state->descending_callback = acpi_ds_load2_begin_op;68		walk_state->ascending_callback = acpi_ds_load2_end_op;69		break;70 71	case 3:72 73		/* Execution pass */74 75		walk_state->parse_flags |= ACPI_PARSE_EXECUTE |76		    ACPI_PARSE_DELETE_TREE;77		walk_state->descending_callback = acpi_ds_exec_begin_op;78		walk_state->ascending_callback = acpi_ds_exec_end_op;79		break;80 81	default:82 83		return (AE_BAD_PARAMETER);84	}85 86	return (AE_OK);87}88 89/*******************************************************************************90 *91 * FUNCTION:    acpi_ds_load1_begin_op92 *93 * PARAMETERS:  walk_state      - Current state of the parse tree walk94 *              out_op          - Where to return op if a new one is created95 *96 * RETURN:      Status97 *98 * DESCRIPTION: Descending callback used during the loading of ACPI tables.99 *100 ******************************************************************************/101 102acpi_status103acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,104		       union acpi_parse_object **out_op)105{106	union acpi_parse_object *op;107	struct acpi_namespace_node *node;108	acpi_status status;109	acpi_object_type object_type;110	char *path;111	u32 flags;112 113	ACPI_FUNCTION_TRACE_PTR(ds_load1_begin_op, walk_state->op);114 115	op = walk_state->op;116	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,117			  walk_state));118 119	/* We are only interested in opcodes that have an associated name */120 121	if (op) {122		if (!(walk_state->op_info->flags & AML_NAMED)) {123			*out_op = op;124			return_ACPI_STATUS(AE_OK);125		}126 127		/* Check if this object has already been installed in the namespace */128 129		if (op->common.node) {130			*out_op = op;131			return_ACPI_STATUS(AE_OK);132		}133	}134 135	path = acpi_ps_get_next_namestring(&walk_state->parser_state);136 137	/* Map the raw opcode into an internal object type */138 139	object_type = walk_state->op_info->object_type;140 141	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,142			  "State=%p Op=%p [%s]\n", walk_state, op,143			  acpi_ut_get_type_name(object_type)));144 145	switch (walk_state->opcode) {146	case AML_SCOPE_OP:147		/*148		 * The target name of the Scope() operator must exist at this point so149		 * that we can actually open the scope to enter new names underneath it.150		 * Allow search-to-root for single namesegs.151		 */152		status =153		    acpi_ns_lookup(walk_state->scope_info, path, object_type,154				   ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,155				   walk_state, &(node));156#ifdef ACPI_ASL_COMPILER157		if (status == AE_NOT_FOUND) {158			/*159			 * Table disassembly:160			 * Target of Scope() not found. Generate an External for it, and161			 * insert the name into the namespace.162			 */163			acpi_dm_add_op_to_external_list(op, path,164							ACPI_TYPE_DEVICE, 0, 0);165			status =166			    acpi_ns_lookup(walk_state->scope_info, path,167					   object_type, ACPI_IMODE_LOAD_PASS1,168					   ACPI_NS_SEARCH_PARENT, walk_state,169					   &node);170		}171#endif172		if (ACPI_FAILURE(status)) {173			ACPI_ERROR_NAMESPACE(walk_state->scope_info, path,174					     status);175			return_ACPI_STATUS(status);176		}177 178		/*179		 * Check to make sure that the target is180		 * one of the opcodes that actually opens a scope181		 */182		switch (node->type) {183		case ACPI_TYPE_ANY:184		case ACPI_TYPE_LOCAL_SCOPE:	/* Scope  */185		case ACPI_TYPE_DEVICE:186		case ACPI_TYPE_POWER:187		case ACPI_TYPE_PROCESSOR:188		case ACPI_TYPE_THERMAL:189 190			/* These are acceptable types */191			break;192 193		case ACPI_TYPE_INTEGER:194		case ACPI_TYPE_STRING:195		case ACPI_TYPE_BUFFER:196			/*197			 * These types we will allow, but we will change the type.198			 * This enables some existing code of the form:199			 *200			 *  Name (DEB, 0)201			 *  Scope (DEB) { ... }202			 *203			 * Note: silently change the type here. On the second pass,204			 * we will report a warning205			 */206			ACPI_DEBUG_PRINT((ACPI_DB_INFO,207					  "Type override - [%4.4s] had invalid type (%s) "208					  "for Scope operator, changed to type ANY\n",209					  acpi_ut_get_node_name(node),210					  acpi_ut_get_type_name(node->type)));211 212			node->type = ACPI_TYPE_ANY;213			walk_state->scope_info->common.value = ACPI_TYPE_ANY;214			break;215 216		case ACPI_TYPE_METHOD:217			/*218			 * Allow scope change to root during execution of module-level219			 * code. Root is typed METHOD during this time.220			 */221			if ((node == acpi_gbl_root_node) &&222			    (walk_state->223			     parse_flags & ACPI_PARSE_MODULE_LEVEL)) {224				break;225			}226 227			ACPI_FALLTHROUGH;228 229		default:230 231			/* All other types are an error */232 233			ACPI_ERROR((AE_INFO,234				    "Invalid type (%s) for target of "235				    "Scope operator [%4.4s] (Cannot override)",236				    acpi_ut_get_type_name(node->type),237				    acpi_ut_get_node_name(node)));238 239			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);240		}241		break;242 243	default:244		/*245		 * For all other named opcodes, we will enter the name into246		 * the namespace.247		 *248		 * Setup the search flags.249		 * Since we are entering a name into the namespace, we do not want to250		 * enable the search-to-root upsearch.251		 *252		 * There are only two conditions where it is acceptable that the name253		 * already exists:254		 *    1) the Scope() operator can reopen a scoping object that was255		 *       previously defined (Scope, Method, Device, etc.)256		 *    2) Whenever we are parsing a deferred opcode (op_region, Buffer,257		 *       buffer_field, or Package), the name of the object is already258		 *       in the namespace.259		 */260		if (walk_state->deferred_node) {261 262			/* This name is already in the namespace, get the node */263 264			node = walk_state->deferred_node;265			status = AE_OK;266			break;267		}268 269		/*270		 * If we are executing a method, do not create any namespace objects271		 * during the load phase, only during execution.272		 */273		if (walk_state->method_node) {274			node = NULL;275			status = AE_OK;276			break;277		}278 279		flags = ACPI_NS_NO_UPSEARCH;280		if ((walk_state->opcode != AML_SCOPE_OP) &&281		    (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {282			if (walk_state->namespace_override) {283				flags |= ACPI_NS_OVERRIDE_IF_FOUND;284				ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,285						  "[%s] Override allowed\n",286						  acpi_ut_get_type_name287						  (object_type)));288			} else {289				flags |= ACPI_NS_ERROR_IF_FOUND;290				ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,291						  "[%s] Cannot already exist\n",292						  acpi_ut_get_type_name293						  (object_type)));294			}295		} else {296			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,297					  "[%s] Both Find or Create allowed\n",298					  acpi_ut_get_type_name(object_type)));299		}300 301		/*302		 * Enter the named type into the internal namespace. We enter the name303		 * as we go downward in the parse tree. Any necessary subobjects that304		 * involve arguments to the opcode must be created as we go back up the305		 * parse tree later.306		 */307		status =308		    acpi_ns_lookup(walk_state->scope_info, path, object_type,309				   ACPI_IMODE_LOAD_PASS1, flags, walk_state,310				   &node);311		if (ACPI_FAILURE(status)) {312			if (status == AE_ALREADY_EXISTS) {313 314				/* The name already exists in this scope */315 316				if (node->flags & ANOBJ_IS_EXTERNAL) {317					/*318					 * Allow one create on an object or segment that was319					 * previously declared External320					 */321					node->flags &= ~ANOBJ_IS_EXTERNAL;322					node->type = (u8) object_type;323 324					/* Just retyped a node, probably will need to open a scope */325 326					if (acpi_ns_opens_scope(object_type)) {327						status =328						    acpi_ds_scope_stack_push329						    (node, object_type,330						     walk_state);331						if (ACPI_FAILURE(status)) {332							return_ACPI_STATUS333							    (status);334						}335					}336 337					status = AE_OK;338				}339			}340 341			if (ACPI_FAILURE(status)) {342				ACPI_ERROR_NAMESPACE(walk_state->scope_info,343						     path, status);344				return_ACPI_STATUS(status);345			}346		}347		break;348	}349 350	/* Common exit */351 352	if (!op) {353 354		/* Create a new op */355 356		op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml);357		if (!op) {358			return_ACPI_STATUS(AE_NO_MEMORY);359		}360	}361 362	/* Initialize the op */363 364#ifdef ACPI_CONSTANT_EVAL_ONLY365	op->named.path = path;366#endif367 368	if (node) {369		/*370		 * Put the Node in the "op" object that the parser uses, so we371		 * can get it again quickly when this scope is closed372		 */373		op->common.node = node;374		op->named.name = node->name.integer;375	}376 377	acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),378			   op);379	*out_op = op;380	return_ACPI_STATUS(status);381}382 383/*******************************************************************************384 *385 * FUNCTION:    acpi_ds_load1_end_op386 *387 * PARAMETERS:  walk_state      - Current state of the parse tree walk388 *389 * RETURN:      Status390 *391 * DESCRIPTION: Ascending callback used during the loading of the namespace,392 *              both control methods and everything else.393 *394 ******************************************************************************/395 396acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)397{398	union acpi_parse_object *op;399	acpi_object_type object_type;400	acpi_status status = AE_OK;401#ifdef ACPI_ASL_COMPILER402	u8 param_count;403#endif404 405	ACPI_FUNCTION_TRACE(ds_load1_end_op);406 407	op = walk_state->op;408	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,409			  walk_state));410 411	/*412	 * Disassembler: handle create field operators here.413	 *414	 * create_buffer_field is a deferred op that is typically processed in load415	 * pass 2. However, disassembly of control method contents walk the parse416	 * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed417	 * in a later walk. This is a problem when there is a control method that418	 * has the same name as the AML_CREATE object. In this case, any use of the419	 * name segment will be detected as a method call rather than a reference420	 * to a buffer field.421	 *422	 * This earlier creation during disassembly solves this issue by inserting423	 * the named object in the ACPI namespace so that references to this name424	 * would be a name string rather than a method call.425	 */426	if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) &&427	    (walk_state->op_info->flags & AML_CREATE)) {428		status = acpi_ds_create_buffer_field(op, walk_state);429		return_ACPI_STATUS(status);430	}431 432	/* We are only interested in opcodes that have an associated name */433 434	if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {435		return_ACPI_STATUS(AE_OK);436	}437 438	/* Get the object type to determine if we should pop the scope */439 440	object_type = walk_state->op_info->object_type;441 442	if (walk_state->op_info->flags & AML_FIELD) {443		/*444		 * If we are executing a method, do not create any namespace objects445		 * during the load phase, only during execution.446		 */447		if (!walk_state->method_node) {448			if (walk_state->opcode == AML_FIELD_OP ||449			    walk_state->opcode == AML_BANK_FIELD_OP ||450			    walk_state->opcode == AML_INDEX_FIELD_OP) {451				status =452				    acpi_ds_init_field_objects(op, walk_state);453			}454		}455		return_ACPI_STATUS(status);456	}457 458	/*459	 * If we are executing a method, do not create any namespace objects460	 * during the load phase, only during execution.461	 */462	if (!walk_state->method_node) {463		if (op->common.aml_opcode == AML_REGION_OP) {464			status =465			    acpi_ex_create_region(op->named.data,466						  op->named.length,467						  (acpi_adr_space_type)468						  ((op->common.value.arg)->469						   common.value.integer),470						  walk_state);471			if (ACPI_FAILURE(status)) {472				return_ACPI_STATUS(status);473			}474		} else if (op->common.aml_opcode == AML_DATA_REGION_OP) {475			status =476			    acpi_ex_create_region(op->named.data,477						  op->named.length,478						  ACPI_ADR_SPACE_DATA_TABLE,479						  walk_state);480			if (ACPI_FAILURE(status)) {481				return_ACPI_STATUS(status);482			}483		}484	}485 486	if (op->common.aml_opcode == AML_NAME_OP) {487 488		/* For Name opcode, get the object type from the argument */489 490		if (op->common.value.arg) {491			object_type = (acpi_ps_get_opcode_info((op->common.492								value.arg)->493							       common.494							       aml_opcode))->495			    object_type;496 497			/* Set node type if we have a namespace node */498 499			if (op->common.node) {500				op->common.node->type = (u8) object_type;501			}502		}503	}504#ifdef ACPI_ASL_COMPILER505	/*506	 * For external opcode, get the object type from the argument and507	 * get the parameter count from the argument's next.508	 */509	if (acpi_gbl_disasm_flag &&510	    op->common.node && op->common.aml_opcode == AML_EXTERNAL_OP) {511		/*512		 * Note, if this external is not a method513		 * Op->Common.Value.Arg->Common.Next->Common.Value.Integer == 0514		 * Therefore, param_count will be 0.515		 */516		param_count =517		    (u8)op->common.value.arg->common.next->common.value.integer;518		object_type = (u8)op->common.value.arg->common.value.integer;519		op->common.node->flags |= ANOBJ_IS_EXTERNAL;520		op->common.node->type = (u8)object_type;521 522		acpi_dm_create_subobject_for_external((u8)object_type,523						      &op->common.node,524						      param_count);525 526		/*527		 * Add the external to the external list because we may be528		 * emitting code based off of the items within the external list.529		 */530		acpi_dm_add_op_to_external_list(op, op->named.path,531						(u8)object_type, param_count,532						ACPI_EXT_ORIGIN_FROM_OPCODE |533						ACPI_EXT_RESOLVED_REFERENCE);534	}535#endif536 537	/*538	 * If we are executing a method, do not create any namespace objects539	 * during the load phase, only during execution.540	 */541	if (!walk_state->method_node) {542		if (op->common.aml_opcode == AML_METHOD_OP) {543			/*544			 * method_op pkg_length name_string method_flags term_list545			 *546			 * Note: We must create the method node/object pair as soon as we547			 * see the method declaration. This allows later pass1 parsing548			 * of invocations of the method (need to know the number of549			 * arguments.)550			 */551			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,552					  "LOADING-Method: State=%p Op=%p NamedObj=%p\n",553					  walk_state, op, op->named.node));554 555			if (!acpi_ns_get_attached_object(op->named.node)) {556				walk_state->operands[0] =557				    ACPI_CAST_PTR(void, op->named.node);558				walk_state->num_operands = 1;559 560				status =561				    acpi_ds_create_operands(walk_state,562							    op->common.value.563							    arg);564				if (ACPI_SUCCESS(status)) {565					status =566					    acpi_ex_create_method(op->named.567								  data,568								  op->named.569								  length,570								  walk_state);571				}572 573				walk_state->operands[0] = NULL;574				walk_state->num_operands = 0;575 576				if (ACPI_FAILURE(status)) {577					return_ACPI_STATUS(status);578				}579			}580		}581	}582 583	/* Pop the scope stack (only if loading a table) */584 585	if (!walk_state->method_node &&586	    op->common.aml_opcode != AML_EXTERNAL_OP &&587	    acpi_ns_opens_scope(object_type)) {588		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,589				  "(%s): Popping scope for Op %p\n",590				  acpi_ut_get_type_name(object_type), op));591 592		status = acpi_ds_scope_stack_pop(walk_state);593	}594 595	return_ACPI_STATUS(status);596}597