162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: exstore - AML Interpreter object store support 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <acpi/acpi.h> 1162306a36Sopenharmony_ci#include "accommon.h" 1262306a36Sopenharmony_ci#include "acdispat.h" 1362306a36Sopenharmony_ci#include "acinterp.h" 1462306a36Sopenharmony_ci#include "amlcode.h" 1562306a36Sopenharmony_ci#include "acnamesp.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define _COMPONENT ACPI_EXECUTER 1862306a36Sopenharmony_ciACPI_MODULE_NAME("exstore") 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* Local prototypes */ 2162306a36Sopenharmony_cistatic acpi_status 2262306a36Sopenharmony_ciacpi_ex_store_object_to_index(union acpi_operand_object *val_desc, 2362306a36Sopenharmony_ci union acpi_operand_object *dest_desc, 2462306a36Sopenharmony_ci struct acpi_walk_state *walk_state); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic acpi_status 2762306a36Sopenharmony_ciacpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, 2862306a36Sopenharmony_ci struct acpi_namespace_node *node, 2962306a36Sopenharmony_ci struct acpi_walk_state *walk_state); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/******************************************************************************* 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * FUNCTION: acpi_ex_store 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * PARAMETERS: *source_desc - Value to be stored 3662306a36Sopenharmony_ci * *dest_desc - Where to store it. Must be an NS node 3762306a36Sopenharmony_ci * or union acpi_operand_object of type 3862306a36Sopenharmony_ci * Reference; 3962306a36Sopenharmony_ci * walk_state - Current walk state 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * RETURN: Status 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * DESCRIPTION: Store the value described by source_desc into the location 4462306a36Sopenharmony_ci * described by dest_desc. Called by various interpreter 4562306a36Sopenharmony_ci * functions to store the result of an operation into 4662306a36Sopenharmony_ci * the destination operand -- not just simply the actual "Store" 4762306a36Sopenharmony_ci * ASL operator. 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci ******************************************************************************/ 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciacpi_status 5262306a36Sopenharmony_ciacpi_ex_store(union acpi_operand_object *source_desc, 5362306a36Sopenharmony_ci union acpi_operand_object *dest_desc, 5462306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci acpi_status status = AE_OK; 5762306a36Sopenharmony_ci union acpi_operand_object *ref_desc = dest_desc; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci /* Validate parameters */ 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (!source_desc || !dest_desc) { 6462306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, "Null parameter")); 6562306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_NO_OPERAND); 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci /* dest_desc can be either a namespace node or an ACPI object */ 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) { 7162306a36Sopenharmony_ci /* 7262306a36Sopenharmony_ci * Dest is a namespace node, 7362306a36Sopenharmony_ci * Storing an object into a Named node. 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci status = acpi_ex_store_object_to_node(source_desc, 7662306a36Sopenharmony_ci (struct 7762306a36Sopenharmony_ci acpi_namespace_node *) 7862306a36Sopenharmony_ci dest_desc, walk_state, 7962306a36Sopenharmony_ci ACPI_IMPLICIT_CONVERSION); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci return_ACPI_STATUS(status); 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci /* Destination object must be a Reference or a Constant object */ 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci switch (dest_desc->common.type) { 8762306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_REFERENCE: 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci break; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci /* Allow stores to Constants -- a Noop as per ACPI spec */ 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) { 9662306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci ACPI_FALLTHROUGH; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci default: 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* Destination is not a Reference object */ 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 10662306a36Sopenharmony_ci "Target is not a Reference or Constant object - [%s] %p", 10762306a36Sopenharmony_ci acpi_ut_get_object_type_name(dest_desc), 10862306a36Sopenharmony_ci dest_desc)); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* 11462306a36Sopenharmony_ci * Examine the Reference class. These cases are handled: 11562306a36Sopenharmony_ci * 11662306a36Sopenharmony_ci * 1) Store to Name (Change the object associated with a name) 11762306a36Sopenharmony_ci * 2) Store to an indexed area of a Buffer or Package 11862306a36Sopenharmony_ci * 3) Store to a Method Local or Arg 11962306a36Sopenharmony_ci * 4) Store to the debug object 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ci switch (ref_desc->reference.class) { 12262306a36Sopenharmony_ci case ACPI_REFCLASS_REFOF: 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci /* Storing an object into a Name "container" */ 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci status = acpi_ex_store_object_to_node(source_desc, 12762306a36Sopenharmony_ci ref_desc->reference. 12862306a36Sopenharmony_ci object, walk_state, 12962306a36Sopenharmony_ci ACPI_IMPLICIT_CONVERSION); 13062306a36Sopenharmony_ci break; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci case ACPI_REFCLASS_INDEX: 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci /* Storing to an Index (pointer into a packager or buffer) */ 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci status = 13762306a36Sopenharmony_ci acpi_ex_store_object_to_index(source_desc, ref_desc, 13862306a36Sopenharmony_ci walk_state); 13962306a36Sopenharmony_ci break; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci case ACPI_REFCLASS_LOCAL: 14262306a36Sopenharmony_ci case ACPI_REFCLASS_ARG: 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci /* Store to a method local/arg */ 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci status = 14762306a36Sopenharmony_ci acpi_ds_store_object_to_local(ref_desc->reference.class, 14862306a36Sopenharmony_ci ref_desc->reference.value, 14962306a36Sopenharmony_ci source_desc, walk_state); 15062306a36Sopenharmony_ci break; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci case ACPI_REFCLASS_DEBUG: 15362306a36Sopenharmony_ci /* 15462306a36Sopenharmony_ci * Storing to the Debug object causes the value stored to be 15562306a36Sopenharmony_ci * displayed and otherwise has no effect -- see ACPI Specification 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 15862306a36Sopenharmony_ci "**** Write to Debug Object: Object %p [%s] ****:\n\n", 15962306a36Sopenharmony_ci source_desc, 16062306a36Sopenharmony_ci acpi_ut_get_object_type_name(source_desc))); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci ACPI_DEBUG_OBJECT(source_desc, 0, 0); 16362306a36Sopenharmony_ci break; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci default: 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, "Unknown Reference Class 0x%2.2X", 16862306a36Sopenharmony_ci ref_desc->reference.class)); 16962306a36Sopenharmony_ci ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci status = AE_AML_INTERNAL; 17262306a36Sopenharmony_ci break; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci return_ACPI_STATUS(status); 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci/******************************************************************************* 17962306a36Sopenharmony_ci * 18062306a36Sopenharmony_ci * FUNCTION: acpi_ex_store_object_to_index 18162306a36Sopenharmony_ci * 18262306a36Sopenharmony_ci * PARAMETERS: *source_desc - Value to be stored 18362306a36Sopenharmony_ci * *dest_desc - Named object to receive the value 18462306a36Sopenharmony_ci * walk_state - Current walk state 18562306a36Sopenharmony_ci * 18662306a36Sopenharmony_ci * RETURN: Status 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * DESCRIPTION: Store the object to indexed Buffer or Package element 18962306a36Sopenharmony_ci * 19062306a36Sopenharmony_ci ******************************************************************************/ 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic acpi_status 19362306a36Sopenharmony_ciacpi_ex_store_object_to_index(union acpi_operand_object *source_desc, 19462306a36Sopenharmony_ci union acpi_operand_object *index_desc, 19562306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci acpi_status status = AE_OK; 19862306a36Sopenharmony_ci union acpi_operand_object *obj_desc; 19962306a36Sopenharmony_ci union acpi_operand_object *new_desc; 20062306a36Sopenharmony_ci u8 value = 0; 20162306a36Sopenharmony_ci u32 i; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ex_store_object_to_index); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci /* 20662306a36Sopenharmony_ci * Destination must be a reference pointer, and 20762306a36Sopenharmony_ci * must point to either a buffer or a package 20862306a36Sopenharmony_ci */ 20962306a36Sopenharmony_ci switch (index_desc->reference.target_type) { 21062306a36Sopenharmony_ci case ACPI_TYPE_PACKAGE: 21162306a36Sopenharmony_ci /* 21262306a36Sopenharmony_ci * Storing to a package element. Copy the object and replace 21362306a36Sopenharmony_ci * any existing object with the new object. No implicit 21462306a36Sopenharmony_ci * conversion is performed. 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * The object at *(index_desc->Reference.Where) is the 21762306a36Sopenharmony_ci * element within the package that is to be modified. 21862306a36Sopenharmony_ci * The parent package object is at index_desc->Reference.Object 21962306a36Sopenharmony_ci */ 22062306a36Sopenharmony_ci obj_desc = *(index_desc->reference.where); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE && 22362306a36Sopenharmony_ci source_desc->reference.class == ACPI_REFCLASS_TABLE) { 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* This is a DDBHandle, just add a reference to it */ 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci acpi_ut_add_reference(source_desc); 22862306a36Sopenharmony_ci new_desc = source_desc; 22962306a36Sopenharmony_ci } else { 23062306a36Sopenharmony_ci /* Normal object, copy it */ 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci status = 23362306a36Sopenharmony_ci acpi_ut_copy_iobject_to_iobject(source_desc, 23462306a36Sopenharmony_ci &new_desc, 23562306a36Sopenharmony_ci walk_state); 23662306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 23762306a36Sopenharmony_ci return_ACPI_STATUS(status); 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci if (obj_desc) { 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* Decrement reference count by the ref count of the parent package */ 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci for (i = 0; i < ((union acpi_operand_object *) 24662306a36Sopenharmony_ci index_desc->reference.object)->common. 24762306a36Sopenharmony_ci reference_count; i++) { 24862306a36Sopenharmony_ci acpi_ut_remove_reference(obj_desc); 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci *(index_desc->reference.where) = new_desc; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* Increment ref count by the ref count of the parent package-1 */ 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci for (i = 1; i < ((union acpi_operand_object *) 25762306a36Sopenharmony_ci index_desc->reference.object)->common. 25862306a36Sopenharmony_ci reference_count; i++) { 25962306a36Sopenharmony_ci acpi_ut_add_reference(new_desc); 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci break; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci case ACPI_TYPE_BUFFER_FIELD: 26562306a36Sopenharmony_ci /* 26662306a36Sopenharmony_ci * Store into a Buffer or String (not actually a real buffer_field) 26762306a36Sopenharmony_ci * at a location defined by an Index. 26862306a36Sopenharmony_ci * 26962306a36Sopenharmony_ci * The first 8-bit element of the source object is written to the 27062306a36Sopenharmony_ci * 8-bit Buffer location defined by the Index destination object, 27162306a36Sopenharmony_ci * according to the ACPI 2.0 specification. 27262306a36Sopenharmony_ci */ 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* 27562306a36Sopenharmony_ci * Make sure the target is a Buffer or String. An error should 27662306a36Sopenharmony_ci * not happen here, since the reference_object was constructed 27762306a36Sopenharmony_ci * by the INDEX_OP code. 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_ci obj_desc = index_desc->reference.object; 28062306a36Sopenharmony_ci if ((obj_desc->common.type != ACPI_TYPE_BUFFER) && 28162306a36Sopenharmony_ci (obj_desc->common.type != ACPI_TYPE_STRING)) { 28262306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci /* 28662306a36Sopenharmony_ci * The assignment of the individual elements will be slightly 28762306a36Sopenharmony_ci * different for each source type. 28862306a36Sopenharmony_ci */ 28962306a36Sopenharmony_ci switch (source_desc->common.type) { 29062306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* Use the least-significant byte of the integer */ 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci value = (u8) (source_desc->integer.value); 29562306a36Sopenharmony_ci break; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 29862306a36Sopenharmony_ci case ACPI_TYPE_STRING: 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* Note: Takes advantage of common string/buffer fields */ 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci value = source_desc->buffer.pointer[0]; 30362306a36Sopenharmony_ci break; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci default: 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci /* All other types are invalid */ 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 31062306a36Sopenharmony_ci "Source must be type [Integer/Buffer/String], found [%s]", 31162306a36Sopenharmony_ci acpi_ut_get_object_type_name(source_desc))); 31262306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* Store the source value into the target buffer byte */ 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci obj_desc->buffer.pointer[index_desc->reference.value] = value; 31862306a36Sopenharmony_ci break; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci default: 32162306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 32262306a36Sopenharmony_ci "Target is not of type [Package/BufferField]")); 32362306a36Sopenharmony_ci status = AE_AML_TARGET_TYPE; 32462306a36Sopenharmony_ci break; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci return_ACPI_STATUS(status); 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci/******************************************************************************* 33162306a36Sopenharmony_ci * 33262306a36Sopenharmony_ci * FUNCTION: acpi_ex_store_object_to_node 33362306a36Sopenharmony_ci * 33462306a36Sopenharmony_ci * PARAMETERS: source_desc - Value to be stored 33562306a36Sopenharmony_ci * node - Named object to receive the value 33662306a36Sopenharmony_ci * walk_state - Current walk state 33762306a36Sopenharmony_ci * implicit_conversion - Perform implicit conversion (yes/no) 33862306a36Sopenharmony_ci * 33962306a36Sopenharmony_ci * RETURN: Status 34062306a36Sopenharmony_ci * 34162306a36Sopenharmony_ci * DESCRIPTION: Store the object to the named object. 34262306a36Sopenharmony_ci * 34362306a36Sopenharmony_ci * The assignment of an object to a named object is handled here. 34462306a36Sopenharmony_ci * The value passed in will replace the current value (if any) 34562306a36Sopenharmony_ci * with the input value. 34662306a36Sopenharmony_ci * 34762306a36Sopenharmony_ci * When storing into an object the data is converted to the 34862306a36Sopenharmony_ci * target object type then stored in the object. This means 34962306a36Sopenharmony_ci * that the target object type (for an initialized target) will 35062306a36Sopenharmony_ci * not be changed by a store operation. A copy_object can change 35162306a36Sopenharmony_ci * the target type, however. 35262306a36Sopenharmony_ci * 35362306a36Sopenharmony_ci * The implicit_conversion flag is set to NO/FALSE only when 35462306a36Sopenharmony_ci * storing to an arg_x -- as per the rules of the ACPI spec. 35562306a36Sopenharmony_ci * 35662306a36Sopenharmony_ci * Assumes parameters are already validated. 35762306a36Sopenharmony_ci * 35862306a36Sopenharmony_ci ******************************************************************************/ 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ciacpi_status 36162306a36Sopenharmony_ciacpi_ex_store_object_to_node(union acpi_operand_object *source_desc, 36262306a36Sopenharmony_ci struct acpi_namespace_node *node, 36362306a36Sopenharmony_ci struct acpi_walk_state *walk_state, 36462306a36Sopenharmony_ci u8 implicit_conversion) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci acpi_status status = AE_OK; 36762306a36Sopenharmony_ci union acpi_operand_object *target_desc; 36862306a36Sopenharmony_ci union acpi_operand_object *new_desc; 36962306a36Sopenharmony_ci acpi_object_type target_type; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /* Get current type of the node, and object attached to Node */ 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci target_type = acpi_ns_get_type(node); 37662306a36Sopenharmony_ci target_desc = acpi_ns_get_attached_object(node); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p [%s] to node %p [%s]\n", 37962306a36Sopenharmony_ci source_desc, 38062306a36Sopenharmony_ci acpi_ut_get_object_type_name(source_desc), node, 38162306a36Sopenharmony_ci acpi_ut_get_type_name(target_type))); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* Only limited target types possible for everything except copy_object */ 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci if (walk_state->opcode != AML_COPY_OBJECT_OP) { 38662306a36Sopenharmony_ci /* 38762306a36Sopenharmony_ci * Only copy_object allows all object types to be overwritten. For 38862306a36Sopenharmony_ci * target_ref(s), there are restrictions on the object types that 38962306a36Sopenharmony_ci * are allowed. 39062306a36Sopenharmony_ci * 39162306a36Sopenharmony_ci * Allowable operations/typing for Store: 39262306a36Sopenharmony_ci * 39362306a36Sopenharmony_ci * 1) Simple Store 39462306a36Sopenharmony_ci * Integer --> Integer (Named/Local/Arg) 39562306a36Sopenharmony_ci * String --> String (Named/Local/Arg) 39662306a36Sopenharmony_ci * Buffer --> Buffer (Named/Local/Arg) 39762306a36Sopenharmony_ci * Package --> Package (Named/Local/Arg) 39862306a36Sopenharmony_ci * 39962306a36Sopenharmony_ci * 2) Store with implicit conversion 40062306a36Sopenharmony_ci * Integer --> String or Buffer (Named) 40162306a36Sopenharmony_ci * String --> Integer or Buffer (Named) 40262306a36Sopenharmony_ci * Buffer --> Integer or String (Named) 40362306a36Sopenharmony_ci */ 40462306a36Sopenharmony_ci switch (target_type) { 40562306a36Sopenharmony_ci case ACPI_TYPE_PACKAGE: 40662306a36Sopenharmony_ci /* 40762306a36Sopenharmony_ci * Here, can only store a package to an existing package. 40862306a36Sopenharmony_ci * Storing a package to a Local/Arg is OK, and handled 40962306a36Sopenharmony_ci * elsewhere. 41062306a36Sopenharmony_ci */ 41162306a36Sopenharmony_ci if (walk_state->opcode == AML_STORE_OP) { 41262306a36Sopenharmony_ci if (source_desc->common.type != 41362306a36Sopenharmony_ci ACPI_TYPE_PACKAGE) { 41462306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 41562306a36Sopenharmony_ci "Cannot assign type [%s] to [Package] " 41662306a36Sopenharmony_ci "(source must be type Pkg)", 41762306a36Sopenharmony_ci acpi_ut_get_object_type_name 41862306a36Sopenharmony_ci (source_desc))); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_TARGET_TYPE); 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci break; 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci ACPI_FALLTHROUGH; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci case ACPI_TYPE_DEVICE: 42862306a36Sopenharmony_ci case ACPI_TYPE_EVENT: 42962306a36Sopenharmony_ci case ACPI_TYPE_MUTEX: 43062306a36Sopenharmony_ci case ACPI_TYPE_REGION: 43162306a36Sopenharmony_ci case ACPI_TYPE_POWER: 43262306a36Sopenharmony_ci case ACPI_TYPE_PROCESSOR: 43362306a36Sopenharmony_ci case ACPI_TYPE_THERMAL: 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 43662306a36Sopenharmony_ci "Target must be [Buffer/Integer/String/Reference]" 43762306a36Sopenharmony_ci ", found [%s] (%4.4s)", 43862306a36Sopenharmony_ci acpi_ut_get_type_name(node->type), 43962306a36Sopenharmony_ci node->name.ascii)); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_TARGET_TYPE); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci default: 44462306a36Sopenharmony_ci break; 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* 44962306a36Sopenharmony_ci * Resolve the source object to an actual value 45062306a36Sopenharmony_ci * (If it is a reference object) 45162306a36Sopenharmony_ci */ 45262306a36Sopenharmony_ci status = acpi_ex_resolve_object(&source_desc, target_type, walk_state); 45362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 45462306a36Sopenharmony_ci return_ACPI_STATUS(status); 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* Do the actual store operation */ 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci switch (target_type) { 46062306a36Sopenharmony_ci /* 46162306a36Sopenharmony_ci * The simple data types all support implicit source operand 46262306a36Sopenharmony_ci * conversion before the store. 46362306a36Sopenharmony_ci */ 46462306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 46562306a36Sopenharmony_ci case ACPI_TYPE_STRING: 46662306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci if ((walk_state->opcode == AML_COPY_OBJECT_OP) || 46962306a36Sopenharmony_ci !implicit_conversion) { 47062306a36Sopenharmony_ci /* 47162306a36Sopenharmony_ci * However, copy_object and Stores to arg_x do not perform 47262306a36Sopenharmony_ci * an implicit conversion, as per the ACPI specification. 47362306a36Sopenharmony_ci * A direct store is performed instead. 47462306a36Sopenharmony_ci */ 47562306a36Sopenharmony_ci status = 47662306a36Sopenharmony_ci acpi_ex_store_direct_to_node(source_desc, node, 47762306a36Sopenharmony_ci walk_state); 47862306a36Sopenharmony_ci break; 47962306a36Sopenharmony_ci } 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci /* Store with implicit source operand conversion support */ 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci status = 48462306a36Sopenharmony_ci acpi_ex_store_object_to_object(source_desc, target_desc, 48562306a36Sopenharmony_ci &new_desc, walk_state); 48662306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 48762306a36Sopenharmony_ci return_ACPI_STATUS(status); 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (new_desc != target_desc) { 49162306a36Sopenharmony_ci /* 49262306a36Sopenharmony_ci * Store the new new_desc as the new value of the Name, and set 49362306a36Sopenharmony_ci * the Name's type to that of the value being stored in it. 49462306a36Sopenharmony_ci * source_desc reference count is incremented by attach_object. 49562306a36Sopenharmony_ci * 49662306a36Sopenharmony_ci * Note: This may change the type of the node if an explicit 49762306a36Sopenharmony_ci * store has been performed such that the node/object type 49862306a36Sopenharmony_ci * has been changed. 49962306a36Sopenharmony_ci */ 50062306a36Sopenharmony_ci status = 50162306a36Sopenharmony_ci acpi_ns_attach_object(node, new_desc, 50262306a36Sopenharmony_ci new_desc->common.type); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 50562306a36Sopenharmony_ci "Store type [%s] into [%s] via Convert/Attach\n", 50662306a36Sopenharmony_ci acpi_ut_get_object_type_name 50762306a36Sopenharmony_ci (source_desc), 50862306a36Sopenharmony_ci acpi_ut_get_object_type_name 50962306a36Sopenharmony_ci (new_desc))); 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci break; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci case ACPI_TYPE_BUFFER_FIELD: 51462306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_REGION_FIELD: 51562306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_BANK_FIELD: 51662306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_INDEX_FIELD: 51762306a36Sopenharmony_ci /* 51862306a36Sopenharmony_ci * For all fields, always write the source data to the target 51962306a36Sopenharmony_ci * field. Any required implicit source operand conversion is 52062306a36Sopenharmony_ci * performed in the function below as necessary. Note, field 52162306a36Sopenharmony_ci * objects must retain their original type permanently. 52262306a36Sopenharmony_ci */ 52362306a36Sopenharmony_ci status = acpi_ex_write_data_to_field(source_desc, target_desc, 52462306a36Sopenharmony_ci &walk_state->result_obj); 52562306a36Sopenharmony_ci break; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci default: 52862306a36Sopenharmony_ci /* 52962306a36Sopenharmony_ci * copy_object operator: No conversions for all other types. 53062306a36Sopenharmony_ci * Instead, directly store a copy of the source object. 53162306a36Sopenharmony_ci * 53262306a36Sopenharmony_ci * This is the ACPI spec-defined behavior for the copy_object 53362306a36Sopenharmony_ci * operator. (Note, for this default case, all normal 53462306a36Sopenharmony_ci * Store/Target operations exited above with an error). 53562306a36Sopenharmony_ci */ 53662306a36Sopenharmony_ci status = 53762306a36Sopenharmony_ci acpi_ex_store_direct_to_node(source_desc, node, walk_state); 53862306a36Sopenharmony_ci break; 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci return_ACPI_STATUS(status); 54262306a36Sopenharmony_ci} 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci/******************************************************************************* 54562306a36Sopenharmony_ci * 54662306a36Sopenharmony_ci * FUNCTION: acpi_ex_store_direct_to_node 54762306a36Sopenharmony_ci * 54862306a36Sopenharmony_ci * PARAMETERS: source_desc - Value to be stored 54962306a36Sopenharmony_ci * node - Named object to receive the value 55062306a36Sopenharmony_ci * walk_state - Current walk state 55162306a36Sopenharmony_ci * 55262306a36Sopenharmony_ci * RETURN: Status 55362306a36Sopenharmony_ci * 55462306a36Sopenharmony_ci * DESCRIPTION: "Store" an object directly to a node. This involves a copy 55562306a36Sopenharmony_ci * and an attach. 55662306a36Sopenharmony_ci * 55762306a36Sopenharmony_ci ******************************************************************************/ 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_cistatic acpi_status 56062306a36Sopenharmony_ciacpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, 56162306a36Sopenharmony_ci struct acpi_namespace_node *node, 56262306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci acpi_status status; 56562306a36Sopenharmony_ci union acpi_operand_object *new_desc; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ex_store_direct_to_node); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 57062306a36Sopenharmony_ci "Storing [%s] (%p) directly into node [%s] (%p)" 57162306a36Sopenharmony_ci " with no implicit conversion\n", 57262306a36Sopenharmony_ci acpi_ut_get_object_type_name(source_desc), 57362306a36Sopenharmony_ci source_desc, acpi_ut_get_type_name(node->type), 57462306a36Sopenharmony_ci node)); 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci /* Copy the source object to a new object */ 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci status = 57962306a36Sopenharmony_ci acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state); 58062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 58162306a36Sopenharmony_ci return_ACPI_STATUS(status); 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci /* Attach the new object to the node */ 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci status = acpi_ns_attach_object(node, new_desc, new_desc->common.type); 58762306a36Sopenharmony_ci acpi_ut_remove_reference(new_desc); 58862306a36Sopenharmony_ci return_ACPI_STATUS(status); 58962306a36Sopenharmony_ci} 590