162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: exstoren - AML Interpreter object store support, 562306a36Sopenharmony_ci * Store to Node (namespace object) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci *****************************************************************************/ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <acpi/acpi.h> 1262306a36Sopenharmony_ci#include "accommon.h" 1362306a36Sopenharmony_ci#include "acinterp.h" 1462306a36Sopenharmony_ci#include "amlcode.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define _COMPONENT ACPI_EXECUTER 1762306a36Sopenharmony_ciACPI_MODULE_NAME("exstoren") 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/******************************************************************************* 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * FUNCTION: acpi_ex_resolve_object 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * PARAMETERS: source_desc_ptr - Pointer to the source object 2462306a36Sopenharmony_ci * target_type - Current type of the target 2562306a36Sopenharmony_ci * walk_state - Current walk state 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * RETURN: Status, resolved object in source_desc_ptr. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * DESCRIPTION: Resolve an object. If the object is a reference, dereference 3062306a36Sopenharmony_ci * it and return the actual object in the source_desc_ptr. 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci ******************************************************************************/ 3362306a36Sopenharmony_ciacpi_status 3462306a36Sopenharmony_ciacpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, 3562306a36Sopenharmony_ci acpi_object_type target_type, 3662306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci union acpi_operand_object *source_desc = *source_desc_ptr; 3962306a36Sopenharmony_ci acpi_status status = AE_OK; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ex_resolve_object); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci /* Ensure we have a Target that can be stored to */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci switch (target_type) { 4662306a36Sopenharmony_ci case ACPI_TYPE_BUFFER_FIELD: 4762306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_REGION_FIELD: 4862306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_BANK_FIELD: 4962306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_INDEX_FIELD: 5062306a36Sopenharmony_ci /* 5162306a36Sopenharmony_ci * These cases all require only Integers or values that 5262306a36Sopenharmony_ci * can be converted to Integers (Strings or Buffers) 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 5562306a36Sopenharmony_ci case ACPI_TYPE_STRING: 5662306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 5762306a36Sopenharmony_ci /* 5862306a36Sopenharmony_ci * Stores into a Field/Region or into a Integer/Buffer/String 5962306a36Sopenharmony_ci * are all essentially the same. This case handles the 6062306a36Sopenharmony_ci * "interchangeable" types Integer, String, and Buffer. 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_ci if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) { 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /* Resolve a reference object first */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci status = 6762306a36Sopenharmony_ci acpi_ex_resolve_to_value(source_desc_ptr, 6862306a36Sopenharmony_ci walk_state); 6962306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 7062306a36Sopenharmony_ci break; 7162306a36Sopenharmony_ci } 7262306a36Sopenharmony_ci } 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci /* For copy_object, no further validation necessary */ 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (walk_state->opcode == AML_COPY_OBJECT_OP) { 7762306a36Sopenharmony_ci break; 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* Must have a Integer, Buffer, or String */ 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if ((source_desc->common.type != ACPI_TYPE_INTEGER) && 8362306a36Sopenharmony_ci (source_desc->common.type != ACPI_TYPE_BUFFER) && 8462306a36Sopenharmony_ci (source_desc->common.type != ACPI_TYPE_STRING) && 8562306a36Sopenharmony_ci !((source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) && 8662306a36Sopenharmony_ci (source_desc->reference.class == ACPI_REFCLASS_TABLE))) { 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* Conversion successful but still not a valid type */ 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 9162306a36Sopenharmony_ci "Cannot assign type [%s] to [%s] (must be type Int/Str/Buf)", 9262306a36Sopenharmony_ci acpi_ut_get_object_type_name(source_desc), 9362306a36Sopenharmony_ci acpi_ut_get_type_name(target_type))); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci status = AE_AML_OPERAND_TYPE; 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci break; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_ALIAS: 10062306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_METHOD_ALIAS: 10162306a36Sopenharmony_ci /* 10262306a36Sopenharmony_ci * All aliases should have been resolved earlier, during the 10362306a36Sopenharmony_ci * operand resolution phase. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, "Store into an unresolved Alias object")); 10662306a36Sopenharmony_ci status = AE_AML_INTERNAL; 10762306a36Sopenharmony_ci break; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci case ACPI_TYPE_PACKAGE: 11062306a36Sopenharmony_ci default: 11162306a36Sopenharmony_ci /* 11262306a36Sopenharmony_ci * All other types than Alias and the various Fields come here, 11362306a36Sopenharmony_ci * including the untyped case - ACPI_TYPE_ANY. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_ci break; 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci return_ACPI_STATUS(status); 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci/******************************************************************************* 12262306a36Sopenharmony_ci * 12362306a36Sopenharmony_ci * FUNCTION: acpi_ex_store_object_to_object 12462306a36Sopenharmony_ci * 12562306a36Sopenharmony_ci * PARAMETERS: source_desc - Object to store 12662306a36Sopenharmony_ci * dest_desc - Object to receive a copy of the source 12762306a36Sopenharmony_ci * new_desc - New object if dest_desc is obsoleted 12862306a36Sopenharmony_ci * walk_state - Current walk state 12962306a36Sopenharmony_ci * 13062306a36Sopenharmony_ci * RETURN: Status 13162306a36Sopenharmony_ci * 13262306a36Sopenharmony_ci * DESCRIPTION: "Store" an object to another object. This may include 13362306a36Sopenharmony_ci * converting the source type to the target type (implicit 13462306a36Sopenharmony_ci * conversion), and a copy of the value of the source to 13562306a36Sopenharmony_ci * the target. 13662306a36Sopenharmony_ci * 13762306a36Sopenharmony_ci * The Assignment of an object to another (not named) object 13862306a36Sopenharmony_ci * is handled here. 13962306a36Sopenharmony_ci * The Source passed in will replace the current value (if any) 14062306a36Sopenharmony_ci * with the input value. 14162306a36Sopenharmony_ci * 14262306a36Sopenharmony_ci * When storing into an object the data is converted to the 14362306a36Sopenharmony_ci * target object type then stored in the object. This means 14462306a36Sopenharmony_ci * that the target object type (for an initialized target) will 14562306a36Sopenharmony_ci * not be changed by a store operation. 14662306a36Sopenharmony_ci * 14762306a36Sopenharmony_ci * This module allows destination types of Number, String, 14862306a36Sopenharmony_ci * Buffer, and Package. 14962306a36Sopenharmony_ci * 15062306a36Sopenharmony_ci * Assumes parameters are already validated. NOTE: source_desc 15162306a36Sopenharmony_ci * resolution (from a reference object) must be performed by 15262306a36Sopenharmony_ci * the caller if necessary. 15362306a36Sopenharmony_ci * 15462306a36Sopenharmony_ci ******************************************************************************/ 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ciacpi_status 15762306a36Sopenharmony_ciacpi_ex_store_object_to_object(union acpi_operand_object *source_desc, 15862306a36Sopenharmony_ci union acpi_operand_object *dest_desc, 15962306a36Sopenharmony_ci union acpi_operand_object **new_desc, 16062306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci union acpi_operand_object *actual_src_desc; 16362306a36Sopenharmony_ci acpi_status status = AE_OK; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_object, source_desc); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci actual_src_desc = source_desc; 16862306a36Sopenharmony_ci if (!dest_desc) { 16962306a36Sopenharmony_ci /* 17062306a36Sopenharmony_ci * There is no destination object (An uninitialized node or 17162306a36Sopenharmony_ci * package element), so we can simply copy the source object 17262306a36Sopenharmony_ci * creating a new destination object 17362306a36Sopenharmony_ci */ 17462306a36Sopenharmony_ci status = 17562306a36Sopenharmony_ci acpi_ut_copy_iobject_to_iobject(actual_src_desc, new_desc, 17662306a36Sopenharmony_ci walk_state); 17762306a36Sopenharmony_ci return_ACPI_STATUS(status); 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci if (source_desc->common.type != dest_desc->common.type) { 18162306a36Sopenharmony_ci /* 18262306a36Sopenharmony_ci * The source type does not match the type of the destination. 18362306a36Sopenharmony_ci * Perform the "implicit conversion" of the source to the current type 18462306a36Sopenharmony_ci * of the target as per the ACPI specification. 18562306a36Sopenharmony_ci * 18662306a36Sopenharmony_ci * If no conversion performed, actual_src_desc = source_desc. 18762306a36Sopenharmony_ci * Otherwise, actual_src_desc is a temporary object to hold the 18862306a36Sopenharmony_ci * converted object. 18962306a36Sopenharmony_ci */ 19062306a36Sopenharmony_ci status = acpi_ex_convert_to_target_type(dest_desc->common.type, 19162306a36Sopenharmony_ci source_desc, 19262306a36Sopenharmony_ci &actual_src_desc, 19362306a36Sopenharmony_ci walk_state); 19462306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 19562306a36Sopenharmony_ci return_ACPI_STATUS(status); 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci if (source_desc == actual_src_desc) { 19962306a36Sopenharmony_ci /* 20062306a36Sopenharmony_ci * No conversion was performed. Return the source_desc as the 20162306a36Sopenharmony_ci * new object. 20262306a36Sopenharmony_ci */ 20362306a36Sopenharmony_ci *new_desc = source_desc; 20462306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* 20962306a36Sopenharmony_ci * We now have two objects of identical types, and we can perform a 21062306a36Sopenharmony_ci * copy of the *value* of the source object. 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_ci switch (dest_desc->common.type) { 21362306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci dest_desc->integer.value = actual_src_desc->integer.value; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Truncate value if we are executing from a 32-bit ACPI table */ 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci (void)acpi_ex_truncate_for32bit_table(dest_desc); 22062306a36Sopenharmony_ci break; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci case ACPI_TYPE_STRING: 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci status = 22562306a36Sopenharmony_ci acpi_ex_store_string_to_string(actual_src_desc, dest_desc); 22662306a36Sopenharmony_ci break; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci status = 23162306a36Sopenharmony_ci acpi_ex_store_buffer_to_buffer(actual_src_desc, dest_desc); 23262306a36Sopenharmony_ci break; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci case ACPI_TYPE_PACKAGE: 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci status = 23762306a36Sopenharmony_ci acpi_ut_copy_iobject_to_iobject(actual_src_desc, &dest_desc, 23862306a36Sopenharmony_ci walk_state); 23962306a36Sopenharmony_ci break; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci default: 24262306a36Sopenharmony_ci /* 24362306a36Sopenharmony_ci * All other types come here. 24462306a36Sopenharmony_ci */ 24562306a36Sopenharmony_ci ACPI_WARNING((AE_INFO, "Store into type [%s] not implemented", 24662306a36Sopenharmony_ci acpi_ut_get_object_type_name(dest_desc))); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci status = AE_NOT_IMPLEMENTED; 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if (actual_src_desc != source_desc) { 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* Delete the intermediate (temporary) source object */ 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci acpi_ut_remove_reference(actual_src_desc); 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci *new_desc = dest_desc; 26062306a36Sopenharmony_ci return_ACPI_STATUS(status); 26162306a36Sopenharmony_ci} 262