195b482a8SLen Brown /****************************************************************************** 295b482a8SLen Brown * 395b482a8SLen Brown * Module Name: dsobject - Dispatcher object management routines 495b482a8SLen Brown * 595b482a8SLen Brown *****************************************************************************/ 695b482a8SLen Brown 795b482a8SLen Brown /* 8a8357b0cSBob Moore * Copyright (C) 2000 - 2010, Intel Corp. 995b482a8SLen Brown * All rights reserved. 1095b482a8SLen Brown * 1195b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 1295b482a8SLen Brown * modification, are permitted provided that the following conditions 1395b482a8SLen Brown * are met: 1495b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 1595b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 1695b482a8SLen Brown * without modification. 1795b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1895b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 1995b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 2095b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 2195b482a8SLen Brown * binary redistribution. 2295b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 2395b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 2495b482a8SLen Brown * from this software without specific prior written permission. 2595b482a8SLen Brown * 2695b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 2795b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 2895b482a8SLen Brown * Software Foundation. 2995b482a8SLen Brown * 3095b482a8SLen Brown * NO WARRANTY 3195b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3295b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3395b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3495b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3595b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3695b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3795b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3895b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3995b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4095b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4195b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 4295b482a8SLen Brown */ 4395b482a8SLen Brown 4495b482a8SLen Brown #include <acpi/acpi.h> 45e2f7a777SLen Brown #include "accommon.h" 46e2f7a777SLen Brown #include "acparser.h" 47e2f7a777SLen Brown #include "amlcode.h" 48e2f7a777SLen Brown #include "acdispat.h" 49e2f7a777SLen Brown #include "acnamesp.h" 50e2f7a777SLen Brown #include "acinterp.h" 5195b482a8SLen Brown 5295b482a8SLen Brown #define _COMPONENT ACPI_DISPATCHER 5395b482a8SLen Brown ACPI_MODULE_NAME("dsobject") 5495b482a8SLen Brown 5595b482a8SLen Brown /* Local prototypes */ 5695b482a8SLen Brown static acpi_status 5795b482a8SLen Brown acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, 5895b482a8SLen Brown union acpi_parse_object *op, 5995b482a8SLen Brown union acpi_operand_object **obj_desc_ptr); 6095b482a8SLen Brown 6195b482a8SLen Brown #ifndef ACPI_NO_METHOD_EXECUTION 6295b482a8SLen Brown /******************************************************************************* 6395b482a8SLen Brown * 6495b482a8SLen Brown * FUNCTION: acpi_ds_build_internal_object 6595b482a8SLen Brown * 6695b482a8SLen Brown * PARAMETERS: walk_state - Current walk state 6795b482a8SLen Brown * Op - Parser object to be translated 6895b482a8SLen Brown * obj_desc_ptr - Where the ACPI internal object is returned 6995b482a8SLen Brown * 7095b482a8SLen Brown * RETURN: Status 7195b482a8SLen Brown * 7295b482a8SLen Brown * DESCRIPTION: Translate a parser Op object to the equivalent namespace object 7395b482a8SLen Brown * Simple objects are any objects other than a package object! 7495b482a8SLen Brown * 7595b482a8SLen Brown ******************************************************************************/ 7695b482a8SLen Brown 7795b482a8SLen Brown static acpi_status 7895b482a8SLen Brown acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, 7995b482a8SLen Brown union acpi_parse_object *op, 8095b482a8SLen Brown union acpi_operand_object **obj_desc_ptr) 8195b482a8SLen Brown { 8295b482a8SLen Brown union acpi_operand_object *obj_desc; 8395b482a8SLen Brown acpi_status status; 8495b482a8SLen Brown 8595b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_build_internal_object); 8695b482a8SLen Brown 8795b482a8SLen Brown *obj_desc_ptr = NULL; 8895b482a8SLen Brown if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { 8995b482a8SLen Brown /* 9095b482a8SLen Brown * This is a named object reference. If this name was 9195b482a8SLen Brown * previously looked up in the namespace, it was stored in this op. 9295b482a8SLen Brown * Otherwise, go ahead and look it up now 9395b482a8SLen Brown */ 9495b482a8SLen Brown if (!op->common.node) { 9595b482a8SLen Brown status = acpi_ns_lookup(walk_state->scope_info, 9695b482a8SLen Brown op->common.value.string, 9795b482a8SLen Brown ACPI_TYPE_ANY, 9895b482a8SLen Brown ACPI_IMODE_EXECUTE, 9995b482a8SLen Brown ACPI_NS_SEARCH_PARENT | 10095b482a8SLen Brown ACPI_NS_DONT_OPEN_SCOPE, NULL, 10195b482a8SLen Brown ACPI_CAST_INDIRECT_PTR(struct 10295b482a8SLen Brown acpi_namespace_node, 10395b482a8SLen Brown &(op-> 10495b482a8SLen Brown common. 10595b482a8SLen Brown node))); 10695b482a8SLen Brown if (ACPI_FAILURE(status)) { 10795b482a8SLen Brown 10895b482a8SLen Brown /* Check if we are resolving a named reference within a package */ 10995b482a8SLen Brown 11095b482a8SLen Brown if ((status == AE_NOT_FOUND) 11195b482a8SLen Brown && (acpi_gbl_enable_interpreter_slack) 11295b482a8SLen Brown && 11395b482a8SLen Brown ((op->common.parent->common.aml_opcode == 11495b482a8SLen Brown AML_PACKAGE_OP) 11595b482a8SLen Brown || (op->common.parent->common.aml_opcode == 11695b482a8SLen Brown AML_VAR_PACKAGE_OP))) { 11795b482a8SLen Brown /* 11895b482a8SLen Brown * We didn't find the target and we are populating elements 11995b482a8SLen Brown * of a package - ignore if slack enabled. Some ASL code 12095b482a8SLen Brown * contains dangling invalid references in packages and 12195b482a8SLen Brown * expects that no exception will be issued. Leave the 12295b482a8SLen Brown * element as a null element. It cannot be used, but it 12395b482a8SLen Brown * can be overwritten by subsequent ASL code - this is 12495b482a8SLen Brown * typically the case. 12595b482a8SLen Brown */ 12695b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 12795b482a8SLen Brown "Ignoring unresolved reference in package [%4.4s]\n", 12895b482a8SLen Brown walk_state-> 12995b482a8SLen Brown scope_info->scope. 13095b482a8SLen Brown node->name.ascii)); 13195b482a8SLen Brown 13295b482a8SLen Brown return_ACPI_STATUS(AE_OK); 13395b482a8SLen Brown } else { 13495b482a8SLen Brown ACPI_ERROR_NAMESPACE(op->common.value. 13595b482a8SLen Brown string, status); 13695b482a8SLen Brown } 13795b482a8SLen Brown 13895b482a8SLen Brown return_ACPI_STATUS(status); 13995b482a8SLen Brown } 14095b482a8SLen Brown } 14195b482a8SLen Brown 14295b482a8SLen Brown /* Special object resolution for elements of a package */ 14395b482a8SLen Brown 14495b482a8SLen Brown if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || 14595b482a8SLen Brown (op->common.parent->common.aml_opcode == 14695b482a8SLen Brown AML_VAR_PACKAGE_OP)) { 14795b482a8SLen Brown /* 14895b482a8SLen Brown * Attempt to resolve the node to a value before we insert it into 14995b482a8SLen Brown * the package. If this is a reference to a common data type, 15095b482a8SLen Brown * resolve it immediately. According to the ACPI spec, package 15195b482a8SLen Brown * elements can only be "data objects" or method references. 15295b482a8SLen Brown * Attempt to resolve to an Integer, Buffer, String or Package. 15395b482a8SLen Brown * If cannot, return the named reference (for things like Devices, 15495b482a8SLen Brown * Methods, etc.) Buffer Fields and Fields will resolve to simple 15595b482a8SLen Brown * objects (int/buf/str/pkg). 15695b482a8SLen Brown * 15795b482a8SLen Brown * NOTE: References to things like Devices, Methods, Mutexes, etc. 15895b482a8SLen Brown * will remain as named references. This behavior is not described 15995b482a8SLen Brown * in the ACPI spec, but it appears to be an oversight. 16095b482a8SLen Brown */ 16195b482a8SLen Brown obj_desc = 16295b482a8SLen Brown ACPI_CAST_PTR(union acpi_operand_object, 16395b482a8SLen Brown op->common.node); 16495b482a8SLen Brown 16595b482a8SLen Brown status = 16695b482a8SLen Brown acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR 16795b482a8SLen Brown (struct 16895b482a8SLen Brown acpi_namespace_node, 16995b482a8SLen Brown &obj_desc), 17095b482a8SLen Brown walk_state); 17195b482a8SLen Brown if (ACPI_FAILURE(status)) { 17295b482a8SLen Brown return_ACPI_STATUS(status); 17395b482a8SLen Brown } 17495b482a8SLen Brown 17595b482a8SLen Brown switch (op->common.node->type) { 17695b482a8SLen Brown /* 17795b482a8SLen Brown * For these types, we need the actual node, not the subobject. 17895b482a8SLen Brown * However, the subobject did not get an extra reference count above. 17995b482a8SLen Brown * 18095b482a8SLen Brown * TBD: should ex_resolve_node_to_value be changed to fix this? 18195b482a8SLen Brown */ 18295b482a8SLen Brown case ACPI_TYPE_DEVICE: 18395b482a8SLen Brown case ACPI_TYPE_THERMAL: 18495b482a8SLen Brown 18595b482a8SLen Brown acpi_ut_add_reference(op->common.node->object); 18695b482a8SLen Brown 18795b482a8SLen Brown /*lint -fallthrough */ 18895b482a8SLen Brown /* 18995b482a8SLen Brown * For these types, we need the actual node, not the subobject. 19095b482a8SLen Brown * The subobject got an extra reference count in ex_resolve_node_to_value. 19195b482a8SLen Brown */ 19295b482a8SLen Brown case ACPI_TYPE_MUTEX: 19395b482a8SLen Brown case ACPI_TYPE_METHOD: 19495b482a8SLen Brown case ACPI_TYPE_POWER: 19595b482a8SLen Brown case ACPI_TYPE_PROCESSOR: 19695b482a8SLen Brown case ACPI_TYPE_EVENT: 19795b482a8SLen Brown case ACPI_TYPE_REGION: 19895b482a8SLen Brown 19995b482a8SLen Brown /* We will create a reference object for these types below */ 20095b482a8SLen Brown break; 20195b482a8SLen Brown 20295b482a8SLen Brown default: 20395b482a8SLen Brown /* 20495b482a8SLen Brown * All other types - the node was resolved to an actual 20595b482a8SLen Brown * object, we are done. 20695b482a8SLen Brown */ 20795b482a8SLen Brown goto exit; 20895b482a8SLen Brown } 20995b482a8SLen Brown } 21095b482a8SLen Brown } 21195b482a8SLen Brown 21295b482a8SLen Brown /* Create and init a new internal ACPI object */ 21395b482a8SLen Brown 21495b482a8SLen Brown obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info 21595b482a8SLen Brown (op->common.aml_opcode))-> 21695b482a8SLen Brown object_type); 21795b482a8SLen Brown if (!obj_desc) { 21895b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 21995b482a8SLen Brown } 22095b482a8SLen Brown 22195b482a8SLen Brown status = 22295b482a8SLen Brown acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode, 22395b482a8SLen Brown &obj_desc); 22495b482a8SLen Brown if (ACPI_FAILURE(status)) { 22595b482a8SLen Brown acpi_ut_remove_reference(obj_desc); 22695b482a8SLen Brown return_ACPI_STATUS(status); 22795b482a8SLen Brown } 22895b482a8SLen Brown 22995b482a8SLen Brown exit: 23095b482a8SLen Brown *obj_desc_ptr = obj_desc; 23195b482a8SLen Brown return_ACPI_STATUS(status); 23295b482a8SLen Brown } 23395b482a8SLen Brown 23495b482a8SLen Brown /******************************************************************************* 23595b482a8SLen Brown * 23695b482a8SLen Brown * FUNCTION: acpi_ds_build_internal_buffer_obj 23795b482a8SLen Brown * 23895b482a8SLen Brown * PARAMETERS: walk_state - Current walk state 23995b482a8SLen Brown * Op - Parser object to be translated 24095b482a8SLen Brown * buffer_length - Length of the buffer 24195b482a8SLen Brown * obj_desc_ptr - Where the ACPI internal object is returned 24295b482a8SLen Brown * 24395b482a8SLen Brown * RETURN: Status 24495b482a8SLen Brown * 24595b482a8SLen Brown * DESCRIPTION: Translate a parser Op package object to the equivalent 24695b482a8SLen Brown * namespace object 24795b482a8SLen Brown * 24895b482a8SLen Brown ******************************************************************************/ 24995b482a8SLen Brown 25095b482a8SLen Brown acpi_status 25195b482a8SLen Brown acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, 25295b482a8SLen Brown union acpi_parse_object *op, 25395b482a8SLen Brown u32 buffer_length, 25495b482a8SLen Brown union acpi_operand_object **obj_desc_ptr) 25595b482a8SLen Brown { 25695b482a8SLen Brown union acpi_parse_object *arg; 25795b482a8SLen Brown union acpi_operand_object *obj_desc; 25895b482a8SLen Brown union acpi_parse_object *byte_list; 25995b482a8SLen Brown u32 byte_list_length = 0; 26095b482a8SLen Brown 26195b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj); 26295b482a8SLen Brown 26395b482a8SLen Brown /* 26495b482a8SLen Brown * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". 26595b482a8SLen Brown * The buffer object already exists (from the NS node), otherwise it must 26695b482a8SLen Brown * be created. 26795b482a8SLen Brown */ 26895b482a8SLen Brown obj_desc = *obj_desc_ptr; 26995b482a8SLen Brown if (!obj_desc) { 27095b482a8SLen Brown 27195b482a8SLen Brown /* Create a new buffer object */ 27295b482a8SLen Brown 27395b482a8SLen Brown obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); 27495b482a8SLen Brown *obj_desc_ptr = obj_desc; 27595b482a8SLen Brown if (!obj_desc) { 27695b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 27795b482a8SLen Brown } 27895b482a8SLen Brown } 27995b482a8SLen Brown 28095b482a8SLen Brown /* 28195b482a8SLen Brown * Second arg is the buffer data (optional) byte_list can be either 28295b482a8SLen Brown * individual bytes or a string initializer. In either case, a 28395b482a8SLen Brown * byte_list appears in the AML. 28495b482a8SLen Brown */ 28595b482a8SLen Brown arg = op->common.value.arg; /* skip first arg */ 28695b482a8SLen Brown 28795b482a8SLen Brown byte_list = arg->named.next; 28895b482a8SLen Brown if (byte_list) { 28995b482a8SLen Brown if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) { 29095b482a8SLen Brown ACPI_ERROR((AE_INFO, 291*f6a22b0bSBob Moore "Expecting bytelist, found AML opcode 0x%X in op %p", 29295b482a8SLen Brown byte_list->common.aml_opcode, byte_list)); 29395b482a8SLen Brown 29495b482a8SLen Brown acpi_ut_remove_reference(obj_desc); 29595b482a8SLen Brown return (AE_TYPE); 29695b482a8SLen Brown } 29795b482a8SLen Brown 29895b482a8SLen Brown byte_list_length = (u32) byte_list->common.value.integer; 29995b482a8SLen Brown } 30095b482a8SLen Brown 30195b482a8SLen Brown /* 30295b482a8SLen Brown * The buffer length (number of bytes) will be the larger of: 30395b482a8SLen Brown * 1) The specified buffer length and 30495b482a8SLen Brown * 2) The length of the initializer byte list 30595b482a8SLen Brown */ 30695b482a8SLen Brown obj_desc->buffer.length = buffer_length; 30795b482a8SLen Brown if (byte_list_length > buffer_length) { 30895b482a8SLen Brown obj_desc->buffer.length = byte_list_length; 30995b482a8SLen Brown } 31095b482a8SLen Brown 31195b482a8SLen Brown /* Allocate the buffer */ 31295b482a8SLen Brown 31395b482a8SLen Brown if (obj_desc->buffer.length == 0) { 31495b482a8SLen Brown obj_desc->buffer.pointer = NULL; 31595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 31695b482a8SLen Brown "Buffer defined with zero length in AML, creating\n")); 31795b482a8SLen Brown } else { 31895b482a8SLen Brown obj_desc->buffer.pointer = 31995b482a8SLen Brown ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length); 32095b482a8SLen Brown if (!obj_desc->buffer.pointer) { 32195b482a8SLen Brown acpi_ut_delete_object_desc(obj_desc); 32295b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 32395b482a8SLen Brown } 32495b482a8SLen Brown 32595b482a8SLen Brown /* Initialize buffer from the byte_list (if present) */ 32695b482a8SLen Brown 32795b482a8SLen Brown if (byte_list) { 32895b482a8SLen Brown ACPI_MEMCPY(obj_desc->buffer.pointer, 32995b482a8SLen Brown byte_list->named.data, byte_list_length); 33095b482a8SLen Brown } 33195b482a8SLen Brown } 33295b482a8SLen Brown 33395b482a8SLen Brown obj_desc->buffer.flags |= AOPOBJ_DATA_VALID; 33495b482a8SLen Brown op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); 33595b482a8SLen Brown return_ACPI_STATUS(AE_OK); 33695b482a8SLen Brown } 33795b482a8SLen Brown 33895b482a8SLen Brown /******************************************************************************* 33995b482a8SLen Brown * 34095b482a8SLen Brown * FUNCTION: acpi_ds_build_internal_package_obj 34195b482a8SLen Brown * 34295b482a8SLen Brown * PARAMETERS: walk_state - Current walk state 34395b482a8SLen Brown * Op - Parser object to be translated 34495b482a8SLen Brown * element_count - Number of elements in the package - this is 34595b482a8SLen Brown * the num_elements argument to Package() 34695b482a8SLen Brown * obj_desc_ptr - Where the ACPI internal object is returned 34795b482a8SLen Brown * 34895b482a8SLen Brown * RETURN: Status 34995b482a8SLen Brown * 35095b482a8SLen Brown * DESCRIPTION: Translate a parser Op package object to the equivalent 35195b482a8SLen Brown * namespace object 35295b482a8SLen Brown * 35395b482a8SLen Brown * NOTE: The number of elements in the package will be always be the num_elements 35495b482a8SLen Brown * count, regardless of the number of elements in the package list. If 35595b482a8SLen Brown * num_elements is smaller, only that many package list elements are used. 35695b482a8SLen Brown * if num_elements is larger, the Package object is padded out with 35795b482a8SLen Brown * objects of type Uninitialized (as per ACPI spec.) 35895b482a8SLen Brown * 35995b482a8SLen Brown * Even though the ASL compilers do not allow num_elements to be smaller 36095b482a8SLen Brown * than the Package list length (for the fixed length package opcode), some 36195b482a8SLen Brown * BIOS code modifies the AML on the fly to adjust the num_elements, and 36295b482a8SLen Brown * this code compensates for that. This also provides compatibility with 36395b482a8SLen Brown * other AML interpreters. 36495b482a8SLen Brown * 36595b482a8SLen Brown ******************************************************************************/ 36695b482a8SLen Brown 36795b482a8SLen Brown acpi_status 36895b482a8SLen Brown acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, 36995b482a8SLen Brown union acpi_parse_object *op, 37095b482a8SLen Brown u32 element_count, 37195b482a8SLen Brown union acpi_operand_object **obj_desc_ptr) 37295b482a8SLen Brown { 37395b482a8SLen Brown union acpi_parse_object *arg; 37495b482a8SLen Brown union acpi_parse_object *parent; 37595b482a8SLen Brown union acpi_operand_object *obj_desc = NULL; 37695b482a8SLen Brown acpi_status status = AE_OK; 37795b482a8SLen Brown unsigned i; 37895b482a8SLen Brown u16 index; 37995b482a8SLen Brown u16 reference_count; 38095b482a8SLen Brown 38195b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); 38295b482a8SLen Brown 38395b482a8SLen Brown /* Find the parent of a possibly nested package */ 38495b482a8SLen Brown 38595b482a8SLen Brown parent = op->common.parent; 38695b482a8SLen Brown while ((parent->common.aml_opcode == AML_PACKAGE_OP) || 38795b482a8SLen Brown (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { 38895b482a8SLen Brown parent = parent->common.parent; 38995b482a8SLen Brown } 39095b482a8SLen Brown 39195b482a8SLen Brown /* 39295b482a8SLen Brown * If we are evaluating a Named package object "Name (xxxx, Package)", 39395b482a8SLen Brown * the package object already exists, otherwise it must be created. 39495b482a8SLen Brown */ 39595b482a8SLen Brown obj_desc = *obj_desc_ptr; 39695b482a8SLen Brown if (!obj_desc) { 39795b482a8SLen Brown obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE); 39895b482a8SLen Brown *obj_desc_ptr = obj_desc; 39995b482a8SLen Brown if (!obj_desc) { 40095b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 40195b482a8SLen Brown } 40295b482a8SLen Brown 40395b482a8SLen Brown obj_desc->package.node = parent->common.node; 40495b482a8SLen Brown } 40595b482a8SLen Brown 40695b482a8SLen Brown /* 40795b482a8SLen Brown * Allocate the element array (array of pointers to the individual 40895b482a8SLen Brown * objects) based on the num_elements parameter. Add an extra pointer slot 40995b482a8SLen Brown * so that the list is always null terminated. 41095b482a8SLen Brown */ 41195b482a8SLen Brown obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) 41295b482a8SLen Brown element_count + 41395b482a8SLen Brown 1) * sizeof(void *)); 41495b482a8SLen Brown 41595b482a8SLen Brown if (!obj_desc->package.elements) { 41695b482a8SLen Brown acpi_ut_delete_object_desc(obj_desc); 41795b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 41895b482a8SLen Brown } 41995b482a8SLen Brown 42095b482a8SLen Brown obj_desc->package.count = element_count; 42195b482a8SLen Brown 42295b482a8SLen Brown /* 42395b482a8SLen Brown * Initialize the elements of the package, up to the num_elements count. 42495b482a8SLen Brown * Package is automatically padded with uninitialized (NULL) elements 42595b482a8SLen Brown * if num_elements is greater than the package list length. Likewise, 42695b482a8SLen Brown * Package is truncated if num_elements is less than the list length. 42795b482a8SLen Brown */ 42895b482a8SLen Brown arg = op->common.value.arg; 42995b482a8SLen Brown arg = arg->common.next; 43095b482a8SLen Brown for (i = 0; arg && (i < element_count); i++) { 43195b482a8SLen Brown if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { 43295b482a8SLen Brown if (arg->common.node->type == ACPI_TYPE_METHOD) { 43395b482a8SLen Brown /* 43495b482a8SLen Brown * A method reference "looks" to the parser to be a method 43595b482a8SLen Brown * invocation, so we special case it here 43695b482a8SLen Brown */ 43795b482a8SLen Brown arg->common.aml_opcode = AML_INT_NAMEPATH_OP; 43895b482a8SLen Brown status = 43995b482a8SLen Brown acpi_ds_build_internal_object(walk_state, 44095b482a8SLen Brown arg, 44195b482a8SLen Brown &obj_desc-> 44295b482a8SLen Brown package. 44395b482a8SLen Brown elements[i]); 44495b482a8SLen Brown } else { 44595b482a8SLen Brown /* This package element is already built, just get it */ 44695b482a8SLen Brown 44795b482a8SLen Brown obj_desc->package.elements[i] = 44895b482a8SLen Brown ACPI_CAST_PTR(union acpi_operand_object, 44995b482a8SLen Brown arg->common.node); 45095b482a8SLen Brown } 45195b482a8SLen Brown } else { 45295b482a8SLen Brown status = acpi_ds_build_internal_object(walk_state, arg, 45395b482a8SLen Brown &obj_desc-> 45495b482a8SLen Brown package. 45595b482a8SLen Brown elements[i]); 45695b482a8SLen Brown } 45795b482a8SLen Brown 45895b482a8SLen Brown if (*obj_desc_ptr) { 45995b482a8SLen Brown 46095b482a8SLen Brown /* Existing package, get existing reference count */ 46195b482a8SLen Brown 46295b482a8SLen Brown reference_count = 46395b482a8SLen Brown (*obj_desc_ptr)->common.reference_count; 46495b482a8SLen Brown if (reference_count > 1) { 46595b482a8SLen Brown 46695b482a8SLen Brown /* Make new element ref count match original ref count */ 46795b482a8SLen Brown 46895b482a8SLen Brown for (index = 0; index < (reference_count - 1); 46995b482a8SLen Brown index++) { 47095b482a8SLen Brown acpi_ut_add_reference((obj_desc-> 47195b482a8SLen Brown package. 47295b482a8SLen Brown elements[i])); 47395b482a8SLen Brown } 47495b482a8SLen Brown } 47595b482a8SLen Brown } 47695b482a8SLen Brown 47795b482a8SLen Brown arg = arg->common.next; 47895b482a8SLen Brown } 47995b482a8SLen Brown 48095b482a8SLen Brown /* Check for match between num_elements and actual length of package_list */ 48195b482a8SLen Brown 48295b482a8SLen Brown if (arg) { 48395b482a8SLen Brown /* 48495b482a8SLen Brown * num_elements was exhausted, but there are remaining elements in the 485e3fe0913SBob Moore * package_list. Truncate the package to num_elements. 48695b482a8SLen Brown * 48795b482a8SLen Brown * Note: technically, this is an error, from ACPI spec: "It is an error 48895b482a8SLen Brown * for NumElements to be less than the number of elements in the 4897d5d05d0SBob Moore * PackageList". However, we just print a message and 490e3fe0913SBob Moore * no exception is returned. This provides Windows compatibility. Some 491e3fe0913SBob Moore * BIOSs will alter the num_elements on the fly, creating this type 492e3fe0913SBob Moore * of ill-formed package object. 49395b482a8SLen Brown */ 49495b482a8SLen Brown while (arg) { 495e3fe0913SBob Moore /* 496e3fe0913SBob Moore * We must delete any package elements that were created earlier 497e3fe0913SBob Moore * and are not going to be used because of the package truncation. 498e3fe0913SBob Moore */ 499e3fe0913SBob Moore if (arg->common.node) { 500e3fe0913SBob Moore acpi_ut_remove_reference(ACPI_CAST_PTR 501e3fe0913SBob Moore (union 502e3fe0913SBob Moore acpi_operand_object, 503e3fe0913SBob Moore arg->common.node)); 504e3fe0913SBob Moore arg->common.node = NULL; 505e3fe0913SBob Moore } 50695b482a8SLen Brown 50795b482a8SLen Brown /* Find out how many elements there really are */ 50895b482a8SLen Brown 50995b482a8SLen Brown i++; 51095b482a8SLen Brown arg = arg->common.next; 51195b482a8SLen Brown } 51295b482a8SLen Brown 5137d5d05d0SBob Moore ACPI_INFO((AE_INFO, 514*f6a22b0bSBob Moore "Actual Package length (%u) is larger than NumElements field (%u), truncated\n", 51595b482a8SLen Brown i, element_count)); 51695b482a8SLen Brown } else if (i < element_count) { 51795b482a8SLen Brown /* 51895b482a8SLen Brown * Arg list (elements) was exhausted, but we did not reach num_elements count. 51995b482a8SLen Brown * Note: this is not an error, the package is padded out with NULLs. 52095b482a8SLen Brown */ 52195b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 522*f6a22b0bSBob Moore "Package List length (%u) smaller than NumElements count (%u), padded with null elements\n", 52395b482a8SLen Brown i, element_count)); 52495b482a8SLen Brown } 52595b482a8SLen Brown 52695b482a8SLen Brown obj_desc->package.flags |= AOPOBJ_DATA_VALID; 52795b482a8SLen Brown op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); 52895b482a8SLen Brown return_ACPI_STATUS(status); 52995b482a8SLen Brown } 53095b482a8SLen Brown 53195b482a8SLen Brown /******************************************************************************* 53295b482a8SLen Brown * 53395b482a8SLen Brown * FUNCTION: acpi_ds_create_node 53495b482a8SLen Brown * 53595b482a8SLen Brown * PARAMETERS: walk_state - Current walk state 53695b482a8SLen Brown * Node - NS Node to be initialized 53795b482a8SLen Brown * Op - Parser object to be translated 53895b482a8SLen Brown * 53995b482a8SLen Brown * RETURN: Status 54095b482a8SLen Brown * 54195b482a8SLen Brown * DESCRIPTION: Create the object to be associated with a namespace node 54295b482a8SLen Brown * 54395b482a8SLen Brown ******************************************************************************/ 54495b482a8SLen Brown 54595b482a8SLen Brown acpi_status 54695b482a8SLen Brown acpi_ds_create_node(struct acpi_walk_state *walk_state, 54795b482a8SLen Brown struct acpi_namespace_node *node, 54895b482a8SLen Brown union acpi_parse_object *op) 54995b482a8SLen Brown { 55095b482a8SLen Brown acpi_status status; 55195b482a8SLen Brown union acpi_operand_object *obj_desc; 55295b482a8SLen Brown 55395b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ds_create_node, op); 55495b482a8SLen Brown 55595b482a8SLen Brown /* 55695b482a8SLen Brown * Because of the execution pass through the non-control-method 55795b482a8SLen Brown * parts of the table, we can arrive here twice. Only init 55895b482a8SLen Brown * the named object node the first time through 55995b482a8SLen Brown */ 56095b482a8SLen Brown if (acpi_ns_get_attached_object(node)) { 56195b482a8SLen Brown return_ACPI_STATUS(AE_OK); 56295b482a8SLen Brown } 56395b482a8SLen Brown 56495b482a8SLen Brown if (!op->common.value.arg) { 56595b482a8SLen Brown 56695b482a8SLen Brown /* No arguments, there is nothing to do */ 56795b482a8SLen Brown 56895b482a8SLen Brown return_ACPI_STATUS(AE_OK); 56995b482a8SLen Brown } 57095b482a8SLen Brown 57195b482a8SLen Brown /* Build an internal object for the argument(s) */ 57295b482a8SLen Brown 57395b482a8SLen Brown status = acpi_ds_build_internal_object(walk_state, op->common.value.arg, 57495b482a8SLen Brown &obj_desc); 57595b482a8SLen Brown if (ACPI_FAILURE(status)) { 57695b482a8SLen Brown return_ACPI_STATUS(status); 57795b482a8SLen Brown } 57895b482a8SLen Brown 57995b482a8SLen Brown /* Re-type the object according to its argument */ 58095b482a8SLen Brown 5813371c19cSBob Moore node->type = obj_desc->common.type; 58295b482a8SLen Brown 58395b482a8SLen Brown /* Attach obj to node */ 58495b482a8SLen Brown 58595b482a8SLen Brown status = acpi_ns_attach_object(node, obj_desc, node->type); 58695b482a8SLen Brown 58795b482a8SLen Brown /* Remove local reference to the object */ 58895b482a8SLen Brown 58995b482a8SLen Brown acpi_ut_remove_reference(obj_desc); 59095b482a8SLen Brown return_ACPI_STATUS(status); 59195b482a8SLen Brown } 59295b482a8SLen Brown 59395b482a8SLen Brown #endif /* ACPI_NO_METHOD_EXECUTION */ 59495b482a8SLen Brown 59595b482a8SLen Brown /******************************************************************************* 59695b482a8SLen Brown * 59795b482a8SLen Brown * FUNCTION: acpi_ds_init_object_from_op 59895b482a8SLen Brown * 59995b482a8SLen Brown * PARAMETERS: walk_state - Current walk state 60095b482a8SLen Brown * Op - Parser op used to init the internal object 60195b482a8SLen Brown * Opcode - AML opcode associated with the object 60295b482a8SLen Brown * ret_obj_desc - Namespace object to be initialized 60395b482a8SLen Brown * 60495b482a8SLen Brown * RETURN: Status 60595b482a8SLen Brown * 60695b482a8SLen Brown * DESCRIPTION: Initialize a namespace object from a parser Op and its 60795b482a8SLen Brown * associated arguments. The namespace object is a more compact 60895b482a8SLen Brown * representation of the Op and its arguments. 60995b482a8SLen Brown * 61095b482a8SLen Brown ******************************************************************************/ 61195b482a8SLen Brown 61295b482a8SLen Brown acpi_status 61395b482a8SLen Brown acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, 61495b482a8SLen Brown union acpi_parse_object *op, 61595b482a8SLen Brown u16 opcode, 61695b482a8SLen Brown union acpi_operand_object **ret_obj_desc) 61795b482a8SLen Brown { 61895b482a8SLen Brown const struct acpi_opcode_info *op_info; 61995b482a8SLen Brown union acpi_operand_object *obj_desc; 62095b482a8SLen Brown acpi_status status = AE_OK; 62195b482a8SLen Brown 62295b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_init_object_from_op); 62395b482a8SLen Brown 62495b482a8SLen Brown obj_desc = *ret_obj_desc; 62595b482a8SLen Brown op_info = acpi_ps_get_opcode_info(opcode); 62695b482a8SLen Brown if (op_info->class == AML_CLASS_UNKNOWN) { 62795b482a8SLen Brown 62895b482a8SLen Brown /* Unknown opcode */ 62995b482a8SLen Brown 63095b482a8SLen Brown return_ACPI_STATUS(AE_TYPE); 63195b482a8SLen Brown } 63295b482a8SLen Brown 63395b482a8SLen Brown /* Perform per-object initialization */ 63495b482a8SLen Brown 6353371c19cSBob Moore switch (obj_desc->common.type) { 63695b482a8SLen Brown case ACPI_TYPE_BUFFER: 63795b482a8SLen Brown 63895b482a8SLen Brown /* 63995b482a8SLen Brown * Defer evaluation of Buffer term_arg operand 64095b482a8SLen Brown */ 64195b482a8SLen Brown obj_desc->buffer.node = 64295b482a8SLen Brown ACPI_CAST_PTR(struct acpi_namespace_node, 64395b482a8SLen Brown walk_state->operands[0]); 64495b482a8SLen Brown obj_desc->buffer.aml_start = op->named.data; 64595b482a8SLen Brown obj_desc->buffer.aml_length = op->named.length; 64695b482a8SLen Brown break; 64795b482a8SLen Brown 64895b482a8SLen Brown case ACPI_TYPE_PACKAGE: 64995b482a8SLen Brown 65095b482a8SLen Brown /* 65195b482a8SLen Brown * Defer evaluation of Package term_arg operand 65295b482a8SLen Brown */ 65395b482a8SLen Brown obj_desc->package.node = 65495b482a8SLen Brown ACPI_CAST_PTR(struct acpi_namespace_node, 65595b482a8SLen Brown walk_state->operands[0]); 65695b482a8SLen Brown obj_desc->package.aml_start = op->named.data; 65795b482a8SLen Brown obj_desc->package.aml_length = op->named.length; 65895b482a8SLen Brown break; 65995b482a8SLen Brown 66095b482a8SLen Brown case ACPI_TYPE_INTEGER: 66195b482a8SLen Brown 66295b482a8SLen Brown switch (op_info->type) { 66395b482a8SLen Brown case AML_TYPE_CONSTANT: 66495b482a8SLen Brown /* 66595b482a8SLen Brown * Resolve AML Constants here - AND ONLY HERE! 66695b482a8SLen Brown * All constants are integers. 66795b482a8SLen Brown * We mark the integer with a flag that indicates that it started 66895b482a8SLen Brown * life as a constant -- so that stores to constants will perform 66995b482a8SLen Brown * as expected (noop). zero_op is used as a placeholder for optional 67095b482a8SLen Brown * target operands. 67195b482a8SLen Brown */ 67295b482a8SLen Brown obj_desc->common.flags = AOPOBJ_AML_CONSTANT; 67395b482a8SLen Brown 67495b482a8SLen Brown switch (opcode) { 67595b482a8SLen Brown case AML_ZERO_OP: 67695b482a8SLen Brown 67795b482a8SLen Brown obj_desc->integer.value = 0; 67895b482a8SLen Brown break; 67995b482a8SLen Brown 68095b482a8SLen Brown case AML_ONE_OP: 68195b482a8SLen Brown 68295b482a8SLen Brown obj_desc->integer.value = 1; 68395b482a8SLen Brown break; 68495b482a8SLen Brown 68595b482a8SLen Brown case AML_ONES_OP: 68695b482a8SLen Brown 6875df7e6cbSBob Moore obj_desc->integer.value = ACPI_UINT64_MAX; 68895b482a8SLen Brown 68995b482a8SLen Brown /* Truncate value if we are executing from a 32-bit ACPI table */ 69095b482a8SLen Brown 69195b482a8SLen Brown #ifndef ACPI_NO_METHOD_EXECUTION 69295b482a8SLen Brown acpi_ex_truncate_for32bit_table(obj_desc); 69395b482a8SLen Brown #endif 69495b482a8SLen Brown break; 69595b482a8SLen Brown 69695b482a8SLen Brown case AML_REVISION_OP: 69795b482a8SLen Brown 69895b482a8SLen Brown obj_desc->integer.value = ACPI_CA_VERSION; 69995b482a8SLen Brown break; 70095b482a8SLen Brown 70195b482a8SLen Brown default: 70295b482a8SLen Brown 70395b482a8SLen Brown ACPI_ERROR((AE_INFO, 704*f6a22b0bSBob Moore "Unknown constant opcode 0x%X", 70595b482a8SLen Brown opcode)); 70695b482a8SLen Brown status = AE_AML_OPERAND_TYPE; 70795b482a8SLen Brown break; 70895b482a8SLen Brown } 70995b482a8SLen Brown break; 71095b482a8SLen Brown 71195b482a8SLen Brown case AML_TYPE_LITERAL: 71295b482a8SLen Brown 71395b482a8SLen Brown obj_desc->integer.value = op->common.value.integer; 71495b482a8SLen Brown #ifndef ACPI_NO_METHOD_EXECUTION 71595b482a8SLen Brown acpi_ex_truncate_for32bit_table(obj_desc); 71695b482a8SLen Brown #endif 71795b482a8SLen Brown break; 71895b482a8SLen Brown 71995b482a8SLen Brown default: 720*f6a22b0bSBob Moore ACPI_ERROR((AE_INFO, "Unknown Integer type 0x%X", 72195b482a8SLen Brown op_info->type)); 72295b482a8SLen Brown status = AE_AML_OPERAND_TYPE; 72395b482a8SLen Brown break; 72495b482a8SLen Brown } 72595b482a8SLen Brown break; 72695b482a8SLen Brown 72795b482a8SLen Brown case ACPI_TYPE_STRING: 72895b482a8SLen Brown 72995b482a8SLen Brown obj_desc->string.pointer = op->common.value.string; 73095b482a8SLen Brown obj_desc->string.length = 73195b482a8SLen Brown (u32) ACPI_STRLEN(op->common.value.string); 73295b482a8SLen Brown 73395b482a8SLen Brown /* 73495b482a8SLen Brown * The string is contained in the ACPI table, don't ever try 73595b482a8SLen Brown * to delete it 73695b482a8SLen Brown */ 73795b482a8SLen Brown obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; 73895b482a8SLen Brown break; 73995b482a8SLen Brown 74095b482a8SLen Brown case ACPI_TYPE_METHOD: 74195b482a8SLen Brown break; 74295b482a8SLen Brown 74395b482a8SLen Brown case ACPI_TYPE_LOCAL_REFERENCE: 74495b482a8SLen Brown 74595b482a8SLen Brown switch (op_info->type) { 74695b482a8SLen Brown case AML_TYPE_LOCAL_VARIABLE: 74795b482a8SLen Brown 74895b482a8SLen Brown /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */ 74995b482a8SLen Brown 750ba9c3f55SBob Moore obj_desc->reference.value = 751ba9c3f55SBob Moore ((u32)opcode) - AML_LOCAL_OP; 75295b482a8SLen Brown obj_desc->reference.class = ACPI_REFCLASS_LOCAL; 75395b482a8SLen Brown 75495b482a8SLen Brown #ifndef ACPI_NO_METHOD_EXECUTION 75595b482a8SLen Brown status = 75695b482a8SLen Brown acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL, 75795b482a8SLen Brown obj_desc->reference. 75895b482a8SLen Brown value, walk_state, 75995b482a8SLen Brown ACPI_CAST_INDIRECT_PTR 76095b482a8SLen Brown (struct 76195b482a8SLen Brown acpi_namespace_node, 76295b482a8SLen Brown &obj_desc->reference. 76395b482a8SLen Brown object)); 76495b482a8SLen Brown #endif 76595b482a8SLen Brown break; 76695b482a8SLen Brown 76795b482a8SLen Brown case AML_TYPE_METHOD_ARGUMENT: 76895b482a8SLen Brown 76995b482a8SLen Brown /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */ 77095b482a8SLen Brown 771ba9c3f55SBob Moore obj_desc->reference.value = ((u32)opcode) - AML_ARG_OP; 77295b482a8SLen Brown obj_desc->reference.class = ACPI_REFCLASS_ARG; 77395b482a8SLen Brown 77495b482a8SLen Brown #ifndef ACPI_NO_METHOD_EXECUTION 77595b482a8SLen Brown status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG, 77695b482a8SLen Brown obj_desc-> 77795b482a8SLen Brown reference.value, 77895b482a8SLen Brown walk_state, 77995b482a8SLen Brown ACPI_CAST_INDIRECT_PTR 78095b482a8SLen Brown (struct 78195b482a8SLen Brown acpi_namespace_node, 78295b482a8SLen Brown &obj_desc-> 78395b482a8SLen Brown reference. 78495b482a8SLen Brown object)); 78595b482a8SLen Brown #endif 78695b482a8SLen Brown break; 78795b482a8SLen Brown 78895b482a8SLen Brown default: /* Object name or Debug object */ 78995b482a8SLen Brown 79095b482a8SLen Brown switch (op->common.aml_opcode) { 79195b482a8SLen Brown case AML_INT_NAMEPATH_OP: 79295b482a8SLen Brown 79395b482a8SLen Brown /* Node was saved in Op */ 79495b482a8SLen Brown 79595b482a8SLen Brown obj_desc->reference.node = op->common.node; 79695b482a8SLen Brown obj_desc->reference.object = 79795b482a8SLen Brown op->common.node->object; 79895b482a8SLen Brown obj_desc->reference.class = ACPI_REFCLASS_NAME; 79995b482a8SLen Brown break; 80095b482a8SLen Brown 80195b482a8SLen Brown case AML_DEBUG_OP: 80295b482a8SLen Brown 80395b482a8SLen Brown obj_desc->reference.class = ACPI_REFCLASS_DEBUG; 80495b482a8SLen Brown break; 80595b482a8SLen Brown 80695b482a8SLen Brown default: 80795b482a8SLen Brown 80895b482a8SLen Brown ACPI_ERROR((AE_INFO, 809*f6a22b0bSBob Moore "Unimplemented reference type for AML opcode: 0x%4.4X", 81095b482a8SLen Brown opcode)); 81195b482a8SLen Brown return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 81295b482a8SLen Brown } 81395b482a8SLen Brown break; 81495b482a8SLen Brown } 81595b482a8SLen Brown break; 81695b482a8SLen Brown 81795b482a8SLen Brown default: 81895b482a8SLen Brown 819*f6a22b0bSBob Moore ACPI_ERROR((AE_INFO, "Unimplemented data type: 0x%X", 8203371c19cSBob Moore obj_desc->common.type)); 82195b482a8SLen Brown 82295b482a8SLen Brown status = AE_AML_OPERAND_TYPE; 82395b482a8SLen Brown break; 82495b482a8SLen Brown } 82595b482a8SLen Brown 82695b482a8SLen Brown return_ACPI_STATUS(status); 82795b482a8SLen Brown } 828