1 /******************************************************************************
3 * Module Name: dsobject - Dispatcher object management routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2005, R. Byron Moore
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
45 #include <acpi/acpi.h>
46 #include <acpi/acparser.h>
47 #include <acpi/amlcode.h>
48 #include <acpi/acdispat.h>
49 #include <acpi/acnamesp.h>
50 #include <acpi/acinterp.h>
52 #define _COMPONENT ACPI_DISPATCHER
53 ACPI_MODULE_NAME ("dsobject")
56 acpi_ds_build_internal_object (
57 struct acpi_walk_state *walk_state,
58 union acpi_parse_object *op,
59 union acpi_operand_object **obj_desc_ptr);
62 #ifndef ACPI_NO_METHOD_EXECUTION
63 /*******************************************************************************
65 * FUNCTION: acpi_ds_build_internal_object
67 * PARAMETERS: walk_state - Current walk state
68 * Op - Parser object to be translated
69 * obj_desc_ptr - Where the ACPI internal object is returned
73 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
74 * Simple objects are any objects other than a package object!
76 ******************************************************************************/
79 acpi_ds_build_internal_object (
80 struct acpi_walk_state *walk_state,
81 union acpi_parse_object *op,
82 union acpi_operand_object **obj_desc_ptr)
84 union acpi_operand_object *obj_desc;
88 ACPI_FUNCTION_TRACE ("ds_build_internal_object");
92 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
94 * This is an named object reference. If this name was
95 * previously looked up in the namespace, it was stored in this op.
96 * Otherwise, go ahead and look it up now
98 if (!op->common.node) {
99 status = acpi_ns_lookup (walk_state->scope_info,
100 op->common.value.string,
101 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
102 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
104 (struct acpi_namespace_node **) &(op->common.node));
106 if (ACPI_FAILURE (status)) {
107 ACPI_REPORT_NSERROR (op->common.value.string, status);
108 return_ACPI_STATUS (status);
113 /* Create and init the internal ACPI object */
115 obj_desc = acpi_ut_create_internal_object (
116 (acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type);
118 return_ACPI_STATUS (AE_NO_MEMORY);
121 status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode,
123 if (ACPI_FAILURE (status)) {
124 acpi_ut_remove_reference (obj_desc);
125 return_ACPI_STATUS (status);
128 *obj_desc_ptr = obj_desc;
129 return_ACPI_STATUS (AE_OK);
133 /*******************************************************************************
135 * FUNCTION: acpi_ds_build_internal_buffer_obj
137 * PARAMETERS: walk_state - Current walk state
138 * Op - Parser object to be translated
139 * buffer_length - Length of the buffer
140 * obj_desc_ptr - Where the ACPI internal object is returned
144 * DESCRIPTION: Translate a parser Op package object to the equivalent
147 ******************************************************************************/
150 acpi_ds_build_internal_buffer_obj (
151 struct acpi_walk_state *walk_state,
152 union acpi_parse_object *op,
154 union acpi_operand_object **obj_desc_ptr)
156 union acpi_parse_object *arg;
157 union acpi_operand_object *obj_desc;
158 union acpi_parse_object *byte_list;
159 u32 byte_list_length = 0;
162 ACPI_FUNCTION_TRACE ("ds_build_internal_buffer_obj");
165 obj_desc = *obj_desc_ptr;
168 * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
169 * The buffer object already exists (from the NS node)
173 /* Create a new buffer object */
175 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
176 *obj_desc_ptr = obj_desc;
178 return_ACPI_STATUS (AE_NO_MEMORY);
183 * Second arg is the buffer data (optional) byte_list can be either
184 * individual bytes or a string initializer. In either case, a
185 * byte_list appears in the AML.
187 arg = op->common.value.arg; /* skip first arg */
189 byte_list = arg->named.next;
191 if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
192 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
193 "Expecting bytelist, got AML opcode %X in op %p\n",
194 byte_list->common.aml_opcode, byte_list));
196 acpi_ut_remove_reference (obj_desc);
200 byte_list_length = (u32) byte_list->common.value.integer;
204 * The buffer length (number of bytes) will be the larger of:
205 * 1) The specified buffer length and
206 * 2) The length of the initializer byte list
208 obj_desc->buffer.length = buffer_length;
209 if (byte_list_length > buffer_length) {
210 obj_desc->buffer.length = byte_list_length;
213 /* Allocate the buffer */
215 if (obj_desc->buffer.length == 0) {
216 obj_desc->buffer.pointer = NULL;
217 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
218 "Buffer defined with zero length in AML, creating\n"));
221 obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
222 obj_desc->buffer.length);
223 if (!obj_desc->buffer.pointer) {
224 acpi_ut_delete_object_desc (obj_desc);
225 return_ACPI_STATUS (AE_NO_MEMORY);
228 /* Initialize buffer from the byte_list (if present) */
231 ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->named.data,
236 obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
237 op->common.node = (struct acpi_namespace_node *) obj_desc;
238 return_ACPI_STATUS (AE_OK);
242 /*******************************************************************************
244 * FUNCTION: acpi_ds_build_internal_package_obj
246 * PARAMETERS: walk_state - Current walk state
247 * Op - Parser object to be translated
248 * package_length - Number of elements in the package
249 * obj_desc_ptr - Where the ACPI internal object is returned
253 * DESCRIPTION: Translate a parser Op package object to the equivalent
256 ******************************************************************************/
259 acpi_ds_build_internal_package_obj (
260 struct acpi_walk_state *walk_state,
261 union acpi_parse_object *op,
263 union acpi_operand_object **obj_desc_ptr)
265 union acpi_parse_object *arg;
266 union acpi_parse_object *parent;
267 union acpi_operand_object *obj_desc = NULL;
268 u32 package_list_length;
269 acpi_status status = AE_OK;
273 ACPI_FUNCTION_TRACE ("ds_build_internal_package_obj");
276 /* Find the parent of a possibly nested package */
278 parent = op->common.parent;
279 while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
280 (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
281 parent = parent->common.parent;
284 obj_desc = *obj_desc_ptr;
287 * We are evaluating a Named package object "Name (xxxx, Package)".
288 * Get the existing package object from the NS node
292 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
293 *obj_desc_ptr = obj_desc;
295 return_ACPI_STATUS (AE_NO_MEMORY);
298 obj_desc->package.node = parent->common.node;
301 obj_desc->package.count = package_length;
303 /* Count the number of items in the package list */
305 package_list_length = 0;
306 arg = op->common.value.arg;
307 arg = arg->common.next;
309 package_list_length++;
310 arg = arg->common.next;
314 * The package length (number of elements) will be the greater
315 * of the specified length and the length of the initializer list
317 if (package_list_length > package_length) {
318 obj_desc->package.count = package_list_length;
322 * Allocate the pointer array (array of pointers to the
323 * individual objects). Add an extra pointer slot so
324 * that the list is always null terminated.
326 obj_desc->package.elements = ACPI_MEM_CALLOCATE (
327 ((acpi_size) obj_desc->package.count + 1) * sizeof (void *));
329 if (!obj_desc->package.elements) {
330 acpi_ut_delete_object_desc (obj_desc);
331 return_ACPI_STATUS (AE_NO_MEMORY);
335 * Now init the elements of the package
338 arg = op->common.value.arg;
339 arg = arg->common.next;
341 if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
342 /* Object (package or buffer) is already built */
344 obj_desc->package.elements[i] =
345 ACPI_CAST_PTR (union acpi_operand_object, arg->common.node);
348 status = acpi_ds_build_internal_object (walk_state, arg,
349 &obj_desc->package.elements[i]);
353 arg = arg->common.next;
356 obj_desc->package.flags |= AOPOBJ_DATA_VALID;
357 op->common.node = (struct acpi_namespace_node *) obj_desc;
358 return_ACPI_STATUS (status);
362 /*******************************************************************************
364 * FUNCTION: acpi_ds_create_node
366 * PARAMETERS: walk_state - Current walk state
367 * Node - NS Node to be initialized
368 * Op - Parser object to be translated
372 * DESCRIPTION: Create the object to be associated with a namespace node
374 ******************************************************************************/
377 acpi_ds_create_node (
378 struct acpi_walk_state *walk_state,
379 struct acpi_namespace_node *node,
380 union acpi_parse_object *op)
383 union acpi_operand_object *obj_desc;
386 ACPI_FUNCTION_TRACE_PTR ("ds_create_node", op);
390 * Because of the execution pass through the non-control-method
391 * parts of the table, we can arrive here twice. Only init
392 * the named object node the first time through
394 if (acpi_ns_get_attached_object (node)) {
395 return_ACPI_STATUS (AE_OK);
398 if (!op->common.value.arg) {
399 /* No arguments, there is nothing to do */
401 return_ACPI_STATUS (AE_OK);
404 /* Build an internal object for the argument(s) */
406 status = acpi_ds_build_internal_object (walk_state, op->common.value.arg,
408 if (ACPI_FAILURE (status)) {
409 return_ACPI_STATUS (status);
412 /* Re-type the object according to its argument */
414 node->type = ACPI_GET_OBJECT_TYPE (obj_desc);
416 /* Attach obj to node */
418 status = acpi_ns_attach_object (node, obj_desc, node->type);
420 /* Remove local reference to the object */
422 acpi_ut_remove_reference (obj_desc);
423 return_ACPI_STATUS (status);
426 #endif /* ACPI_NO_METHOD_EXECUTION */
429 /*******************************************************************************
431 * FUNCTION: acpi_ds_init_object_from_op
433 * PARAMETERS: walk_state - Current walk state
434 * Op - Parser op used to init the internal object
435 * Opcode - AML opcode associated with the object
436 * ret_obj_desc - Namespace object to be initialized
440 * DESCRIPTION: Initialize a namespace object from a parser Op and its
441 * associated arguments. The namespace object is a more compact
442 * representation of the Op and its arguments.
444 ******************************************************************************/
447 acpi_ds_init_object_from_op (
448 struct acpi_walk_state *walk_state,
449 union acpi_parse_object *op,
451 union acpi_operand_object **ret_obj_desc)
453 const struct acpi_opcode_info *op_info;
454 union acpi_operand_object *obj_desc;
455 acpi_status status = AE_OK;
458 ACPI_FUNCTION_TRACE ("ds_init_object_from_op");
461 obj_desc = *ret_obj_desc;
462 op_info = acpi_ps_get_opcode_info (opcode);
463 if (op_info->class == AML_CLASS_UNKNOWN) {
466 return_ACPI_STATUS (AE_TYPE);
469 /* Perform per-object initialization */
471 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
472 case ACPI_TYPE_BUFFER:
475 * Defer evaluation of Buffer term_arg operand
477 obj_desc->buffer.node = (struct acpi_namespace_node *)
478 walk_state->operands[0];
479 obj_desc->buffer.aml_start = op->named.data;
480 obj_desc->buffer.aml_length = op->named.length;
484 case ACPI_TYPE_PACKAGE:
487 * Defer evaluation of Package term_arg operand
489 obj_desc->package.node = (struct acpi_namespace_node *)
490 walk_state->operands[0];
491 obj_desc->package.aml_start = op->named.data;
492 obj_desc->package.aml_length = op->named.length;
496 case ACPI_TYPE_INTEGER:
498 switch (op_info->type) {
499 case AML_TYPE_CONSTANT:
501 * Resolve AML Constants here - AND ONLY HERE!
502 * All constants are integers.
503 * We mark the integer with a flag that indicates that it started
504 * life as a constant -- so that stores to constants will perform
505 * as expected (noop). zero_op is used as a placeholder for optional
508 obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
513 obj_desc->integer.value = 0;
518 obj_desc->integer.value = 1;
523 obj_desc->integer.value = ACPI_INTEGER_MAX;
525 /* Truncate value if we are executing from a 32-bit ACPI table */
527 #ifndef ACPI_NO_METHOD_EXECUTION
528 acpi_ex_truncate_for32bit_table (obj_desc);
532 case AML_REVISION_OP:
534 obj_desc->integer.value = ACPI_CA_VERSION;
539 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
540 "Unknown constant opcode %X\n", opcode));
541 status = AE_AML_OPERAND_TYPE;
547 case AML_TYPE_LITERAL:
549 obj_desc->integer.value = op->common.value.integer;
554 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n",
556 status = AE_AML_OPERAND_TYPE;
562 case ACPI_TYPE_STRING:
564 obj_desc->string.pointer = op->common.value.string;
565 obj_desc->string.length = (u32) ACPI_STRLEN (op->common.value.string);
568 * The string is contained in the ACPI table, don't ever try
571 obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
575 case ACPI_TYPE_METHOD:
579 case ACPI_TYPE_LOCAL_REFERENCE:
581 switch (op_info->type) {
582 case AML_TYPE_LOCAL_VARIABLE:
584 /* Split the opcode into a base opcode + offset */
586 obj_desc->reference.opcode = AML_LOCAL_OP;
587 obj_desc->reference.offset = opcode - AML_LOCAL_OP;
589 #ifndef ACPI_NO_METHOD_EXECUTION
590 status = acpi_ds_method_data_get_node (AML_LOCAL_OP,
591 obj_desc->reference.offset,
593 (struct acpi_namespace_node **) &obj_desc->reference.object);
598 case AML_TYPE_METHOD_ARGUMENT:
600 /* Split the opcode into a base opcode + offset */
602 obj_desc->reference.opcode = AML_ARG_OP;
603 obj_desc->reference.offset = opcode - AML_ARG_OP;
605 #ifndef ACPI_NO_METHOD_EXECUTION
606 status = acpi_ds_method_data_get_node (AML_ARG_OP,
607 obj_desc->reference.offset,
609 (struct acpi_namespace_node **) &obj_desc->reference.object);
613 default: /* Other literals, etc.. */
615 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
616 /* Node was saved in Op */
618 obj_desc->reference.node = op->common.node;
621 obj_desc->reference.opcode = opcode;
629 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n",
630 ACPI_GET_OBJECT_TYPE (obj_desc)));
632 status = AE_AML_OPERAND_TYPE;
636 return_ACPI_STATUS (status);