brintos

brintos / linux-shallow public Read only

0
0
Text · 16.6 KiB · 575c7a3 Raw
590 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: exstore - AML Interpreter object store support5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acdispat.h"13#include "acinterp.h"14#include "amlcode.h"15#include "acnamesp.h"16 17#define _COMPONENT          ACPI_EXECUTER18ACPI_MODULE_NAME("exstore")19 20/* Local prototypes */21static acpi_status22acpi_ex_store_object_to_index(union acpi_operand_object *val_desc,23			      union acpi_operand_object *dest_desc,24			      struct acpi_walk_state *walk_state);25 26static acpi_status27acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc,28			     struct acpi_namespace_node *node,29			     struct acpi_walk_state *walk_state);30 31/*******************************************************************************32 *33 * FUNCTION:    acpi_ex_store34 *35 * PARAMETERS:  *source_desc        - Value to be stored36 *              *dest_desc          - Where to store it. Must be an NS node37 *                                    or union acpi_operand_object of type38 *                                    Reference;39 *              walk_state          - Current walk state40 *41 * RETURN:      Status42 *43 * DESCRIPTION: Store the value described by source_desc into the location44 *              described by dest_desc. Called by various interpreter45 *              functions to store the result of an operation into46 *              the destination operand -- not just simply the actual "Store"47 *              ASL operator.48 *49 ******************************************************************************/50 51acpi_status52acpi_ex_store(union acpi_operand_object *source_desc,53	      union acpi_operand_object *dest_desc,54	      struct acpi_walk_state *walk_state)55{56	acpi_status status = AE_OK;57	union acpi_operand_object *ref_desc = dest_desc;58 59	ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc);60 61	/* Validate parameters */62 63	if (!source_desc || !dest_desc) {64		ACPI_ERROR((AE_INFO, "Null parameter"));65		return_ACPI_STATUS(AE_AML_NO_OPERAND);66	}67 68	/* dest_desc can be either a namespace node or an ACPI object */69 70	if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) {71		/*72		 * Dest is a namespace node,73		 * Storing an object into a Named node.74		 */75		status = acpi_ex_store_object_to_node(source_desc,76						      (struct77						       acpi_namespace_node *)78						      dest_desc, walk_state,79						      ACPI_IMPLICIT_CONVERSION);80 81		return_ACPI_STATUS(status);82	}83 84	/* Destination object must be a Reference or a Constant object */85 86	switch (dest_desc->common.type) {87	case ACPI_TYPE_LOCAL_REFERENCE:88 89		break;90 91	case ACPI_TYPE_INTEGER:92 93		/* Allow stores to Constants -- a Noop as per ACPI spec */94 95		if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) {96			return_ACPI_STATUS(AE_OK);97		}98 99		ACPI_FALLTHROUGH;100 101	default:102 103		/* Destination is not a Reference object */104 105		ACPI_ERROR((AE_INFO,106			    "Target is not a Reference or Constant object - [%s] %p",107			    acpi_ut_get_object_type_name(dest_desc),108			    dest_desc));109 110		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);111	}112 113	/*114	 * Examine the Reference class. These cases are handled:115	 *116	 * 1) Store to Name (Change the object associated with a name)117	 * 2) Store to an indexed area of a Buffer or Package118	 * 3) Store to a Method Local or Arg119	 * 4) Store to the debug object120	 */121	switch (ref_desc->reference.class) {122	case ACPI_REFCLASS_REFOF:123 124		/* Storing an object into a Name "container" */125 126		status = acpi_ex_store_object_to_node(source_desc,127						      ref_desc->reference.128						      object, walk_state,129						      ACPI_IMPLICIT_CONVERSION);130		break;131 132	case ACPI_REFCLASS_INDEX:133 134		/* Storing to an Index (pointer into a packager or buffer) */135 136		status =137		    acpi_ex_store_object_to_index(source_desc, ref_desc,138						  walk_state);139		break;140 141	case ACPI_REFCLASS_LOCAL:142	case ACPI_REFCLASS_ARG:143 144		/* Store to a method local/arg  */145 146		status =147		    acpi_ds_store_object_to_local(ref_desc->reference.class,148						  ref_desc->reference.value,149						  source_desc, walk_state);150		break;151 152	case ACPI_REFCLASS_DEBUG:153		/*154		 * Storing to the Debug object causes the value stored to be155		 * displayed and otherwise has no effect -- see ACPI Specification156		 */157		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,158				  "**** Write to Debug Object: Object %p [%s] ****:\n\n",159				  source_desc,160				  acpi_ut_get_object_type_name(source_desc)));161 162		ACPI_DEBUG_OBJECT(source_desc, 0, 0);163		break;164 165	default:166 167		ACPI_ERROR((AE_INFO, "Unknown Reference Class 0x%2.2X",168			    ref_desc->reference.class));169		ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO);170 171		status = AE_AML_INTERNAL;172		break;173	}174 175	return_ACPI_STATUS(status);176}177 178/*******************************************************************************179 *180 * FUNCTION:    acpi_ex_store_object_to_index181 *182 * PARAMETERS:  *source_desc            - Value to be stored183 *              *dest_desc              - Named object to receive the value184 *              walk_state              - Current walk state185 *186 * RETURN:      Status187 *188 * DESCRIPTION: Store the object to indexed Buffer or Package element189 *190 ******************************************************************************/191 192static acpi_status193acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,194			      union acpi_operand_object *index_desc,195			      struct acpi_walk_state *walk_state)196{197	acpi_status status = AE_OK;198	union acpi_operand_object *obj_desc;199	union acpi_operand_object *new_desc;200	u8 value = 0;201	u32 i;202 203	ACPI_FUNCTION_TRACE(ex_store_object_to_index);204 205	/*206	 * Destination must be a reference pointer, and207	 * must point to either a buffer or a package208	 */209	switch (index_desc->reference.target_type) {210	case ACPI_TYPE_PACKAGE:211		/*212		 * Storing to a package element. Copy the object and replace213		 * any existing object with the new object. No implicit214		 * conversion is performed.215		 *216		 * The object at *(index_desc->Reference.Where) is the217		 * element within the package that is to be modified.218		 * The parent package object is at index_desc->Reference.Object219		 */220		obj_desc = *(index_desc->reference.where);221 222		if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE &&223		    source_desc->reference.class == ACPI_REFCLASS_TABLE) {224 225			/* This is a DDBHandle, just add a reference to it */226 227			acpi_ut_add_reference(source_desc);228			new_desc = source_desc;229		} else {230			/* Normal object, copy it */231 232			status =233			    acpi_ut_copy_iobject_to_iobject(source_desc,234							    &new_desc,235							    walk_state);236			if (ACPI_FAILURE(status)) {237				return_ACPI_STATUS(status);238			}239		}240 241		if (obj_desc) {242 243			/* Decrement reference count by the ref count of the parent package */244 245			for (i = 0; i < ((union acpi_operand_object *)246					 index_desc->reference.object)->common.247			     reference_count; i++) {248				acpi_ut_remove_reference(obj_desc);249			}250		}251 252		*(index_desc->reference.where) = new_desc;253 254		/* Increment ref count by the ref count of the parent package-1 */255 256		for (i = 1; i < ((union acpi_operand_object *)257				 index_desc->reference.object)->common.258		     reference_count; i++) {259			acpi_ut_add_reference(new_desc);260		}261 262		break;263 264	case ACPI_TYPE_BUFFER_FIELD:265		/*266		 * Store into a Buffer or String (not actually a real buffer_field)267		 * at a location defined by an Index.268		 *269		 * The first 8-bit element of the source object is written to the270		 * 8-bit Buffer location defined by the Index destination object,271		 * according to the ACPI 2.0 specification.272		 */273 274		/*275		 * Make sure the target is a Buffer or String. An error should276		 * not happen here, since the reference_object was constructed277		 * by the INDEX_OP code.278		 */279		obj_desc = index_desc->reference.object;280		if ((obj_desc->common.type != ACPI_TYPE_BUFFER) &&281		    (obj_desc->common.type != ACPI_TYPE_STRING)) {282			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);283		}284 285		/*286		 * The assignment of the individual elements will be slightly287		 * different for each source type.288		 */289		switch (source_desc->common.type) {290		case ACPI_TYPE_INTEGER:291 292			/* Use the least-significant byte of the integer */293 294			value = (u8) (source_desc->integer.value);295			break;296 297		case ACPI_TYPE_BUFFER:298		case ACPI_TYPE_STRING:299 300			/* Note: Takes advantage of common string/buffer fields */301 302			value = source_desc->buffer.pointer[0];303			break;304 305		default:306 307			/* All other types are invalid */308 309			ACPI_ERROR((AE_INFO,310				    "Source must be type [Integer/Buffer/String], found [%s]",311				    acpi_ut_get_object_type_name(source_desc)));312			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);313		}314 315		/* Store the source value into the target buffer byte */316 317		obj_desc->buffer.pointer[index_desc->reference.value] = value;318		break;319 320	default:321		ACPI_ERROR((AE_INFO,322			    "Target is not of type [Package/BufferField]"));323		status = AE_AML_TARGET_TYPE;324		break;325	}326 327	return_ACPI_STATUS(status);328}329 330/*******************************************************************************331 *332 * FUNCTION:    acpi_ex_store_object_to_node333 *334 * PARAMETERS:  source_desc             - Value to be stored335 *              node                    - Named object to receive the value336 *              walk_state              - Current walk state337 *              implicit_conversion     - Perform implicit conversion (yes/no)338 *339 * RETURN:      Status340 *341 * DESCRIPTION: Store the object to the named object.342 *343 * The assignment of an object to a named object is handled here.344 * The value passed in will replace the current value (if any)345 * with the input value.346 *347 * When storing into an object the data is converted to the348 * target object type then stored in the object. This means349 * that the target object type (for an initialized target) will350 * not be changed by a store operation. A copy_object can change351 * the target type, however.352 *353 * The implicit_conversion flag is set to NO/FALSE only when354 * storing to an arg_x -- as per the rules of the ACPI spec.355 *356 * Assumes parameters are already validated.357 *358 ******************************************************************************/359 360acpi_status361acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,362			     struct acpi_namespace_node *node,363			     struct acpi_walk_state *walk_state,364			     u8 implicit_conversion)365{366	acpi_status status = AE_OK;367	union acpi_operand_object *target_desc;368	union acpi_operand_object *new_desc;369	acpi_object_type target_type;370 371	ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc);372 373	/* Get current type of the node, and object attached to Node */374 375	target_type = acpi_ns_get_type(node);376	target_desc = acpi_ns_get_attached_object(node);377 378	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p [%s] to node %p [%s]\n",379			  source_desc,380			  acpi_ut_get_object_type_name(source_desc), node,381			  acpi_ut_get_type_name(target_type)));382 383	/* Only limited target types possible for everything except copy_object */384 385	if (walk_state->opcode != AML_COPY_OBJECT_OP) {386		/*387		 * Only copy_object allows all object types to be overwritten. For388		 * target_ref(s), there are restrictions on the object types that389		 * are allowed.390		 *391		 * Allowable operations/typing for Store:392		 *393		 * 1) Simple Store394		 *      Integer     --> Integer (Named/Local/Arg)395		 *      String      --> String  (Named/Local/Arg)396		 *      Buffer      --> Buffer  (Named/Local/Arg)397		 *      Package     --> Package (Named/Local/Arg)398		 *399		 * 2) Store with implicit conversion400		 *      Integer     --> String or Buffer  (Named)401		 *      String      --> Integer or Buffer (Named)402		 *      Buffer      --> Integer or String (Named)403		 */404		switch (target_type) {405		case ACPI_TYPE_PACKAGE:406			/*407			 * Here, can only store a package to an existing package.408			 * Storing a package to a Local/Arg is OK, and handled409			 * elsewhere.410			 */411			if (walk_state->opcode == AML_STORE_OP) {412				if (source_desc->common.type !=413				    ACPI_TYPE_PACKAGE) {414					ACPI_ERROR((AE_INFO,415						    "Cannot assign type [%s] to [Package] "416						    "(source must be type Pkg)",417						    acpi_ut_get_object_type_name418						    (source_desc)));419 420					return_ACPI_STATUS(AE_AML_TARGET_TYPE);421				}422				break;423			}424 425			ACPI_FALLTHROUGH;426 427		case ACPI_TYPE_DEVICE:428		case ACPI_TYPE_EVENT:429		case ACPI_TYPE_MUTEX:430		case ACPI_TYPE_REGION:431		case ACPI_TYPE_POWER:432		case ACPI_TYPE_PROCESSOR:433		case ACPI_TYPE_THERMAL:434 435			ACPI_ERROR((AE_INFO,436				    "Target must be [Buffer/Integer/String/Reference]"437				    ", found [%s] (%4.4s)",438				    acpi_ut_get_type_name(node->type),439				    node->name.ascii));440 441			return_ACPI_STATUS(AE_AML_TARGET_TYPE);442 443		default:444			break;445		}446	}447 448	/*449	 * Resolve the source object to an actual value450	 * (If it is a reference object)451	 */452	status = acpi_ex_resolve_object(&source_desc, target_type, walk_state);453	if (ACPI_FAILURE(status)) {454		return_ACPI_STATUS(status);455	}456 457	/* Do the actual store operation */458 459	switch (target_type) {460		/*461		 * The simple data types all support implicit source operand462		 * conversion before the store.463		 */464	case ACPI_TYPE_INTEGER:465	case ACPI_TYPE_STRING:466	case ACPI_TYPE_BUFFER:467 468		if ((walk_state->opcode == AML_COPY_OBJECT_OP) ||469		    !implicit_conversion) {470			/*471			 * However, copy_object and Stores to arg_x do not perform472			 * an implicit conversion, as per the ACPI specification.473			 * A direct store is performed instead.474			 */475			status =476			    acpi_ex_store_direct_to_node(source_desc, node,477							 walk_state);478			break;479		}480 481		/* Store with implicit source operand conversion support */482 483		status =484		    acpi_ex_store_object_to_object(source_desc, target_desc,485						   &new_desc, walk_state);486		if (ACPI_FAILURE(status)) {487			return_ACPI_STATUS(status);488		}489 490		if (new_desc != target_desc) {491			/*492			 * Store the new new_desc as the new value of the Name, and set493			 * the Name's type to that of the value being stored in it.494			 * source_desc reference count is incremented by attach_object.495			 *496			 * Note: This may change the type of the node if an explicit497			 * store has been performed such that the node/object type498			 * has been changed.499			 */500			status =501			    acpi_ns_attach_object(node, new_desc,502						  new_desc->common.type);503 504			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,505					  "Store type [%s] into [%s] via Convert/Attach\n",506					  acpi_ut_get_object_type_name507					  (source_desc),508					  acpi_ut_get_object_type_name509					  (new_desc)));510		}511		break;512 513	case ACPI_TYPE_BUFFER_FIELD:514	case ACPI_TYPE_LOCAL_REGION_FIELD:515	case ACPI_TYPE_LOCAL_BANK_FIELD:516	case ACPI_TYPE_LOCAL_INDEX_FIELD:517		/*518		 * For all fields, always write the source data to the target519		 * field. Any required implicit source operand conversion is520		 * performed in the function below as necessary. Note, field521		 * objects must retain their original type permanently.522		 */523		status = acpi_ex_write_data_to_field(source_desc, target_desc,524						     &walk_state->result_obj);525		break;526 527	default:528		/*529		 * copy_object operator: No conversions for all other types.530		 * Instead, directly store a copy of the source object.531		 *532		 * This is the ACPI spec-defined behavior for the copy_object533		 * operator. (Note, for this default case, all normal534		 * Store/Target operations exited above with an error).535		 */536		status =537		    acpi_ex_store_direct_to_node(source_desc, node, walk_state);538		break;539	}540 541	return_ACPI_STATUS(status);542}543 544/*******************************************************************************545 *546 * FUNCTION:    acpi_ex_store_direct_to_node547 *548 * PARAMETERS:  source_desc             - Value to be stored549 *              node                    - Named object to receive the value550 *              walk_state              - Current walk state551 *552 * RETURN:      Status553 *554 * DESCRIPTION: "Store" an object directly to a node. This involves a copy555 *              and an attach.556 *557 ******************************************************************************/558 559static acpi_status560acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc,561			     struct acpi_namespace_node *node,562			     struct acpi_walk_state *walk_state)563{564	acpi_status status;565	union acpi_operand_object *new_desc;566 567	ACPI_FUNCTION_TRACE(ex_store_direct_to_node);568 569	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,570			  "Storing [%s] (%p) directly into node [%s] (%p)"571			  " with no implicit conversion\n",572			  acpi_ut_get_object_type_name(source_desc),573			  source_desc, acpi_ut_get_type_name(node->type),574			  node));575 576	/* Copy the source object to a new object */577 578	status =579	    acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state);580	if (ACPI_FAILURE(status)) {581		return_ACPI_STATUS(status);582	}583 584	/* Attach the new object to the node */585 586	status = acpi_ns_attach_object(node, new_desc, new_desc->common.type);587	acpi_ut_remove_reference(new_desc);588	return_ACPI_STATUS(status);589}590