195b482a8SLen Brown /****************************************************************************** 295b482a8SLen Brown * 395b482a8SLen Brown * Module Name: dsobject - Dispatcher object management routines 495b482a8SLen Brown * 595b482a8SLen Brown *****************************************************************************/ 695b482a8SLen Brown 795b482a8SLen Brown /* 895b482a8SLen Brown * Copyright (C) 2000 - 2008, 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> 45*e2f7a777SLen Brown #include "accommon.h" 46*e2f7a777SLen Brown #include "acparser.h" 47*e2f7a777SLen Brown #include "amlcode.h" 48*e2f7a777SLen Brown #include "acdispat.h" 49*e2f7a777SLen Brown #include "acnamesp.h" 50*e2f7a777SLen 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, 29195b482a8SLen Brown "Expecting bytelist, got AML opcode %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 48595b482a8SLen Brown * package_list. 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 48995b482a8SLen Brown * PackageList". However, for now, we just print an error message and 49095b482a8SLen Brown * no exception is returned. 49195b482a8SLen Brown */ 49295b482a8SLen Brown while (arg) { 49395b482a8SLen Brown 49495b482a8SLen Brown /* Find out how many elements there really are */ 49595b482a8SLen Brown 49695b482a8SLen Brown i++; 49795b482a8SLen Brown arg = arg->common.next; 49895b482a8SLen Brown } 49995b482a8SLen Brown 50095b482a8SLen Brown ACPI_WARNING((AE_INFO, 50195b482a8SLen Brown "Package List length (%X) larger than NumElements count (%X), truncated\n", 50295b482a8SLen Brown i, element_count)); 50395b482a8SLen Brown } else if (i < element_count) { 50495b482a8SLen Brown /* 50595b482a8SLen Brown * Arg list (elements) was exhausted, but we did not reach num_elements count. 50695b482a8SLen Brown * Note: this is not an error, the package is padded out with NULLs. 50795b482a8SLen Brown */ 50895b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 50995b482a8SLen Brown "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n", 51095b482a8SLen Brown i, element_count)); 51195b482a8SLen Brown } 51295b482a8SLen Brown 51395b482a8SLen Brown obj_desc->package.flags |= AOPOBJ_DATA_VALID; 51495b482a8SLen Brown op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); 51595b482a8SLen Brown return_ACPI_STATUS(status); 51695b482a8SLen Brown } 51795b482a8SLen Brown 51895b482a8SLen Brown /******************************************************************************* 51995b482a8SLen Brown * 52095b482a8SLen Brown * FUNCTION: acpi_ds_create_node 52195b482a8SLen Brown * 52295b482a8SLen Brown * PARAMETERS: walk_state - Current walk state 52395b482a8SLen Brown * Node - NS Node to be initialized 52495b482a8SLen Brown * Op - Parser object to be translated 52595b482a8SLen Brown * 52695b482a8SLen Brown * RETURN: Status 52795b482a8SLen Brown * 52895b482a8SLen Brown * DESCRIPTION: Create the object to be associated with a namespace node 52995b482a8SLen Brown * 53095b482a8SLen Brown ******************************************************************************/ 53195b482a8SLen Brown 53295b482a8SLen Brown acpi_status 53395b482a8SLen Brown acpi_ds_create_node(struct acpi_walk_state *walk_state, 53495b482a8SLen Brown struct acpi_namespace_node *node, 53595b482a8SLen Brown union acpi_parse_object *op) 53695b482a8SLen Brown { 53795b482a8SLen Brown acpi_status status; 53895b482a8SLen Brown union acpi_operand_object *obj_desc; 53995b482a8SLen Brown 54095b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ds_create_node, op); 54195b482a8SLen Brown 54295b482a8SLen Brown /* 54395b482a8SLen Brown * Because of the execution pass through the non-control-method 54495b482a8SLen Brown * parts of the table, we can arrive here twice. Only init 54595b482a8SLen Brown * the named object node the first time through 54695b482a8SLen Brown */ 54795b482a8SLen Brown if (acpi_ns_get_attached_object(node)) { 54895b482a8SLen Brown return_ACPI_STATUS(AE_OK); 54995b482a8SLen Brown } 55095b482a8SLen Brown 55195b482a8SLen Brown if (!op->common.value.arg) { 55295b482a8SLen Brown 55395b482a8SLen Brown /* No arguments, there is nothing to do */ 55495b482a8SLen Brown 55595b482a8SLen Brown return_ACPI_STATUS(AE_OK); 55695b482a8SLen Brown } 55795b482a8SLen Brown 55895b482a8SLen Brown /* Build an internal object for the argument(s) */ 55995b482a8SLen Brown 56095b482a8SLen Brown status = acpi_ds_build_internal_object(walk_state, op->common.value.arg, 56195b482a8SLen Brown &obj_desc); 56295b482a8SLen Brown if (ACPI_FAILURE(status)) { 56395b482a8SLen Brown return_ACPI_STATUS(status); 56495b482a8SLen Brown } 56595b482a8SLen Brown 56695b482a8SLen Brown /* Re-type the object according to its argument */ 56795b482a8SLen Brown 56895b482a8SLen Brown node->type = ACPI_GET_OBJECT_TYPE(obj_desc); 56995b482a8SLen Brown 57095b482a8SLen Brown /* Attach obj to node */ 57195b482a8SLen Brown 57295b482a8SLen Brown status = acpi_ns_attach_object(node, obj_desc, node->type); 57395b482a8SLen Brown 57495b482a8SLen Brown /* Remove local reference to the object */ 57595b482a8SLen Brown 57695b482a8SLen Brown acpi_ut_remove_reference(obj_desc); 57795b482a8SLen Brown return_ACPI_STATUS(status); 57895b482a8SLen Brown } 57995b482a8SLen Brown 58095b482a8SLen Brown #endif /* ACPI_NO_METHOD_EXECUTION */ 58195b482a8SLen Brown 58295b482a8SLen Brown /******************************************************************************* 58395b482a8SLen Brown * 58495b482a8SLen Brown * FUNCTION: acpi_ds_init_object_from_op 58595b482a8SLen Brown * 58695b482a8SLen Brown * PARAMETERS: walk_state - Current walk state 58795b482a8SLen Brown * Op - Parser op used to init the internal object 58895b482a8SLen Brown * Opcode - AML opcode associated with the object 58995b482a8SLen Brown * ret_obj_desc - Namespace object to be initialized 59095b482a8SLen Brown * 59195b482a8SLen Brown * RETURN: Status 59295b482a8SLen Brown * 59395b482a8SLen Brown * DESCRIPTION: Initialize a namespace object from a parser Op and its 59495b482a8SLen Brown * associated arguments. The namespace object is a more compact 59595b482a8SLen Brown * representation of the Op and its arguments. 59695b482a8SLen Brown * 59795b482a8SLen Brown ******************************************************************************/ 59895b482a8SLen Brown 59995b482a8SLen Brown acpi_status 60095b482a8SLen Brown acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, 60195b482a8SLen Brown union acpi_parse_object *op, 60295b482a8SLen Brown u16 opcode, 60395b482a8SLen Brown union acpi_operand_object **ret_obj_desc) 60495b482a8SLen Brown { 60595b482a8SLen Brown const struct acpi_opcode_info *op_info; 60695b482a8SLen Brown union acpi_operand_object *obj_desc; 60795b482a8SLen Brown acpi_status status = AE_OK; 60895b482a8SLen Brown 60995b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_init_object_from_op); 61095b482a8SLen Brown 61195b482a8SLen Brown obj_desc = *ret_obj_desc; 61295b482a8SLen Brown op_info = acpi_ps_get_opcode_info(opcode); 61395b482a8SLen Brown if (op_info->class == AML_CLASS_UNKNOWN) { 61495b482a8SLen Brown 61595b482a8SLen Brown /* Unknown opcode */ 61695b482a8SLen Brown 61795b482a8SLen Brown return_ACPI_STATUS(AE_TYPE); 61895b482a8SLen Brown } 61995b482a8SLen Brown 62095b482a8SLen Brown /* Perform per-object initialization */ 62195b482a8SLen Brown 62295b482a8SLen Brown switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { 62395b482a8SLen Brown case ACPI_TYPE_BUFFER: 62495b482a8SLen Brown 62595b482a8SLen Brown /* 62695b482a8SLen Brown * Defer evaluation of Buffer term_arg operand 62795b482a8SLen Brown */ 62895b482a8SLen Brown obj_desc->buffer.node = 62995b482a8SLen Brown ACPI_CAST_PTR(struct acpi_namespace_node, 63095b482a8SLen Brown walk_state->operands[0]); 63195b482a8SLen Brown obj_desc->buffer.aml_start = op->named.data; 63295b482a8SLen Brown obj_desc->buffer.aml_length = op->named.length; 63395b482a8SLen Brown break; 63495b482a8SLen Brown 63595b482a8SLen Brown case ACPI_TYPE_PACKAGE: 63695b482a8SLen Brown 63795b482a8SLen Brown /* 63895b482a8SLen Brown * Defer evaluation of Package term_arg operand 63995b482a8SLen Brown */ 64095b482a8SLen Brown obj_desc->package.node = 64195b482a8SLen Brown ACPI_CAST_PTR(struct acpi_namespace_node, 64295b482a8SLen Brown walk_state->operands[0]); 64395b482a8SLen Brown obj_desc->package.aml_start = op->named.data; 64495b482a8SLen Brown obj_desc->package.aml_length = op->named.length; 64595b482a8SLen Brown break; 64695b482a8SLen Brown 64795b482a8SLen Brown case ACPI_TYPE_INTEGER: 64895b482a8SLen Brown 64995b482a8SLen Brown switch (op_info->type) { 65095b482a8SLen Brown case AML_TYPE_CONSTANT: 65195b482a8SLen Brown /* 65295b482a8SLen Brown * Resolve AML Constants here - AND ONLY HERE! 65395b482a8SLen Brown * All constants are integers. 65495b482a8SLen Brown * We mark the integer with a flag that indicates that it started 65595b482a8SLen Brown * life as a constant -- so that stores to constants will perform 65695b482a8SLen Brown * as expected (noop). zero_op is used as a placeholder for optional 65795b482a8SLen Brown * target operands. 65895b482a8SLen Brown */ 65995b482a8SLen Brown obj_desc->common.flags = AOPOBJ_AML_CONSTANT; 66095b482a8SLen Brown 66195b482a8SLen Brown switch (opcode) { 66295b482a8SLen Brown case AML_ZERO_OP: 66395b482a8SLen Brown 66495b482a8SLen Brown obj_desc->integer.value = 0; 66595b482a8SLen Brown break; 66695b482a8SLen Brown 66795b482a8SLen Brown case AML_ONE_OP: 66895b482a8SLen Brown 66995b482a8SLen Brown obj_desc->integer.value = 1; 67095b482a8SLen Brown break; 67195b482a8SLen Brown 67295b482a8SLen Brown case AML_ONES_OP: 67395b482a8SLen Brown 67495b482a8SLen Brown obj_desc->integer.value = ACPI_INTEGER_MAX; 67595b482a8SLen Brown 67695b482a8SLen Brown /* Truncate value if we are executing from a 32-bit ACPI table */ 67795b482a8SLen Brown 67895b482a8SLen Brown #ifndef ACPI_NO_METHOD_EXECUTION 67995b482a8SLen Brown acpi_ex_truncate_for32bit_table(obj_desc); 68095b482a8SLen Brown #endif 68195b482a8SLen Brown break; 68295b482a8SLen Brown 68395b482a8SLen Brown case AML_REVISION_OP: 68495b482a8SLen Brown 68595b482a8SLen Brown obj_desc->integer.value = ACPI_CA_VERSION; 68695b482a8SLen Brown break; 68795b482a8SLen Brown 68895b482a8SLen Brown default: 68995b482a8SLen Brown 69095b482a8SLen Brown ACPI_ERROR((AE_INFO, 69195b482a8SLen Brown "Unknown constant opcode %X", 69295b482a8SLen Brown opcode)); 69395b482a8SLen Brown status = AE_AML_OPERAND_TYPE; 69495b482a8SLen Brown break; 69595b482a8SLen Brown } 69695b482a8SLen Brown break; 69795b482a8SLen Brown 69895b482a8SLen Brown case AML_TYPE_LITERAL: 69995b482a8SLen Brown 70095b482a8SLen Brown obj_desc->integer.value = op->common.value.integer; 70195b482a8SLen Brown #ifndef ACPI_NO_METHOD_EXECUTION 70295b482a8SLen Brown acpi_ex_truncate_for32bit_table(obj_desc); 70395b482a8SLen Brown #endif 70495b482a8SLen Brown break; 70595b482a8SLen Brown 70695b482a8SLen Brown default: 70795b482a8SLen Brown ACPI_ERROR((AE_INFO, "Unknown Integer type %X", 70895b482a8SLen Brown op_info->type)); 70995b482a8SLen Brown status = AE_AML_OPERAND_TYPE; 71095b482a8SLen Brown break; 71195b482a8SLen Brown } 71295b482a8SLen Brown break; 71395b482a8SLen Brown 71495b482a8SLen Brown case ACPI_TYPE_STRING: 71595b482a8SLen Brown 71695b482a8SLen Brown obj_desc->string.pointer = op->common.value.string; 71795b482a8SLen Brown obj_desc->string.length = 71895b482a8SLen Brown (u32) ACPI_STRLEN(op->common.value.string); 71995b482a8SLen Brown 72095b482a8SLen Brown /* 72195b482a8SLen Brown * The string is contained in the ACPI table, don't ever try 72295b482a8SLen Brown * to delete it 72395b482a8SLen Brown */ 72495b482a8SLen Brown obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; 72595b482a8SLen Brown break; 72695b482a8SLen Brown 72795b482a8SLen Brown case ACPI_TYPE_METHOD: 72895b482a8SLen Brown break; 72995b482a8SLen Brown 73095b482a8SLen Brown case ACPI_TYPE_LOCAL_REFERENCE: 73195b482a8SLen Brown 73295b482a8SLen Brown switch (op_info->type) { 73395b482a8SLen Brown case AML_TYPE_LOCAL_VARIABLE: 73495b482a8SLen Brown 73595b482a8SLen Brown /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */ 73695b482a8SLen Brown 73795b482a8SLen Brown obj_desc->reference.value = opcode - AML_LOCAL_OP; 73895b482a8SLen Brown obj_desc->reference.class = ACPI_REFCLASS_LOCAL; 73995b482a8SLen Brown 74095b482a8SLen Brown #ifndef ACPI_NO_METHOD_EXECUTION 74195b482a8SLen Brown status = 74295b482a8SLen Brown acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL, 74395b482a8SLen Brown obj_desc->reference. 74495b482a8SLen Brown value, walk_state, 74595b482a8SLen Brown ACPI_CAST_INDIRECT_PTR 74695b482a8SLen Brown (struct 74795b482a8SLen Brown acpi_namespace_node, 74895b482a8SLen Brown &obj_desc->reference. 74995b482a8SLen Brown object)); 75095b482a8SLen Brown #endif 75195b482a8SLen Brown break; 75295b482a8SLen Brown 75395b482a8SLen Brown case AML_TYPE_METHOD_ARGUMENT: 75495b482a8SLen Brown 75595b482a8SLen Brown /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */ 75695b482a8SLen Brown 75795b482a8SLen Brown obj_desc->reference.value = opcode - AML_ARG_OP; 75895b482a8SLen Brown obj_desc->reference.class = ACPI_REFCLASS_ARG; 75995b482a8SLen Brown 76095b482a8SLen Brown #ifndef ACPI_NO_METHOD_EXECUTION 76195b482a8SLen Brown status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG, 76295b482a8SLen Brown obj_desc-> 76395b482a8SLen Brown reference.value, 76495b482a8SLen Brown walk_state, 76595b482a8SLen Brown ACPI_CAST_INDIRECT_PTR 76695b482a8SLen Brown (struct 76795b482a8SLen Brown acpi_namespace_node, 76895b482a8SLen Brown &obj_desc-> 76995b482a8SLen Brown reference. 77095b482a8SLen Brown object)); 77195b482a8SLen Brown #endif 77295b482a8SLen Brown break; 77395b482a8SLen Brown 77495b482a8SLen Brown default: /* Object name or Debug object */ 77595b482a8SLen Brown 77695b482a8SLen Brown switch (op->common.aml_opcode) { 77795b482a8SLen Brown case AML_INT_NAMEPATH_OP: 77895b482a8SLen Brown 77995b482a8SLen Brown /* Node was saved in Op */ 78095b482a8SLen Brown 78195b482a8SLen Brown obj_desc->reference.node = op->common.node; 78295b482a8SLen Brown obj_desc->reference.object = 78395b482a8SLen Brown op->common.node->object; 78495b482a8SLen Brown obj_desc->reference.class = ACPI_REFCLASS_NAME; 78595b482a8SLen Brown break; 78695b482a8SLen Brown 78795b482a8SLen Brown case AML_DEBUG_OP: 78895b482a8SLen Brown 78995b482a8SLen Brown obj_desc->reference.class = ACPI_REFCLASS_DEBUG; 79095b482a8SLen Brown break; 79195b482a8SLen Brown 79295b482a8SLen Brown default: 79395b482a8SLen Brown 79495b482a8SLen Brown ACPI_ERROR((AE_INFO, 79595b482a8SLen Brown "Unimplemented reference type for AML opcode: %4.4X", 79695b482a8SLen Brown opcode)); 79795b482a8SLen Brown return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 79895b482a8SLen Brown } 79995b482a8SLen Brown break; 80095b482a8SLen Brown } 80195b482a8SLen Brown break; 80295b482a8SLen Brown 80395b482a8SLen Brown default: 80495b482a8SLen Brown 80595b482a8SLen Brown ACPI_ERROR((AE_INFO, "Unimplemented data type: %X", 80695b482a8SLen Brown ACPI_GET_OBJECT_TYPE(obj_desc))); 80795b482a8SLen Brown 80895b482a8SLen Brown status = AE_AML_OPERAND_TYPE; 80995b482a8SLen Brown break; 81095b482a8SLen Brown } 81195b482a8SLen Brown 81295b482a8SLen Brown return_ACPI_STATUS(status); 81395b482a8SLen Brown } 814