1 /******************************************************************************
3 * Module Name: dsobject - Dispatcher object management routines
6 *****************************************************************************/
9 * Copyright (C) 2000, 2001 R. Byron Moore
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define _COMPONENT ACPI_DISPATCHER
30 MODULE_NAME ("dsobject")
33 /*******************************************************************************
35 * FUNCTION: Acpi_ds_init_one_object
37 * PARAMETERS: Obj_handle - Node
38 * Level - Current nesting level
39 * Context - Points to a init info struct
40 * Return_value - Not used
44 * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object
45 * within the namespace.
47 * Currently, the only objects that require initialization are:
51 ******************************************************************************/
54 acpi_ds_init_one_object (
55 ACPI_HANDLE obj_handle
,
60 OBJECT_TYPE_INTERNAL type
;
62 ACPI_INIT_WALK_INFO
*info
= (ACPI_INIT_WALK_INFO
*) context
;
67 table_revision
= info
->table_desc
->pointer
->revision
;
70 * We are only interested in objects owned by the table that
74 if (((ACPI_NAMESPACE_NODE
*) obj_handle
)->owner_id
!=
75 info
->table_desc
->table_id
) {
80 /* And even then, we are only interested in a few object types */
82 type
= acpi_ns_get_type (obj_handle
);
86 case ACPI_TYPE_REGION
:
88 acpi_ds_initialize_region (obj_handle
);
90 info
->op_region_count
++;
94 case ACPI_TYPE_METHOD
:
100 * Set the execution data width (32 or 64) based upon the
101 * revision number of the parent ACPI table.
104 if (table_revision
== 1) {
105 ((ACPI_NAMESPACE_NODE
*)obj_handle
)->flags
|= ANOBJ_DATA_WIDTH_32
;
109 * Always parse methods to detect errors, we may delete
110 * the parse tree below
113 status
= acpi_ds_parse_method (obj_handle
);
115 /* TBD: [Errors] what do we do with an error? */
117 if (ACPI_FAILURE (status
)) {
122 * Delete the parse tree. We simple re-parse the method
123 * for every execution since there isn't much overhead
125 acpi_ns_delete_namespace_subtree (obj_handle
);
133 * We ignore errors from above, and always return OK, since
134 * we don't want to abort the walk on a single error.
140 /*******************************************************************************
142 * FUNCTION: Acpi_ds_initialize_objects
148 * DESCRIPTION: Walk the entire namespace and perform any necessary
149 * initialization on the objects found therein
151 ******************************************************************************/
154 acpi_ds_initialize_objects (
155 ACPI_TABLE_DESC
*table_desc
,
156 ACPI_NAMESPACE_NODE
*start_node
)
159 ACPI_INIT_WALK_INFO info
;
162 info
.method_count
= 0;
163 info
.op_region_count
= 0;
164 info
.object_count
= 0;
165 info
.table_desc
= table_desc
;
168 /* Walk entire namespace from the supplied root */
170 status
= acpi_walk_namespace (ACPI_TYPE_ANY
, start_node
,
171 ACPI_UINT32_MAX
, acpi_ds_init_one_object
,
178 /*****************************************************************************
180 * FUNCTION: Acpi_ds_init_object_from_op
182 * PARAMETERS: Op - Parser op used to init the internal object
183 * Opcode - AML opcode associated with the object
184 * Obj_desc - Namespace object to be initialized
188 * DESCRIPTION: Initialize a namespace object from a parser Op and its
189 * associated arguments. The namespace object is a more compact
190 * representation of the Op and its arguments.
192 ****************************************************************************/
195 acpi_ds_init_object_from_op (
196 ACPI_WALK_STATE
*walk_state
,
197 ACPI_PARSE_OBJECT
*op
,
199 ACPI_OPERAND_OBJECT
**obj_desc
)
202 ACPI_PARSE_OBJECT
*arg
;
203 ACPI_PARSE2_OBJECT
*byte_list
;
204 ACPI_OPERAND_OBJECT
*arg_desc
;
205 ACPI_OPCODE_INFO
*op_info
;
208 op_info
= acpi_ps_get_opcode_info (opcode
);
209 if (ACPI_GET_OP_TYPE (op_info
) != ACPI_OP_TYPE_OPCODE
) {
216 /* Get and prepare the first argument */
218 switch ((*obj_desc
)->common
.type
) {
219 case ACPI_TYPE_BUFFER
:
221 /* First arg is a number */
223 acpi_ds_create_operand (walk_state
, op
->value
.arg
, 0);
224 arg_desc
= walk_state
->operands
[walk_state
->num_operands
- 1];
225 acpi_ds_obj_stack_pop (1, walk_state
);
227 /* Resolve the object (could be an arg or local) */
229 status
= acpi_aml_resolve_to_value (&arg_desc
, walk_state
);
230 if (ACPI_FAILURE (status
)) {
231 acpi_cm_remove_reference (arg_desc
);
235 /* We are expecting a number */
237 if (arg_desc
->common
.type
!= ACPI_TYPE_INTEGER
) {
238 acpi_cm_remove_reference (arg_desc
);
242 /* Get the value, delete the internal object */
244 (*obj_desc
)->buffer
.length
= (u32
) arg_desc
->integer
.value
;
245 acpi_cm_remove_reference (arg_desc
);
247 /* Allocate the buffer */
249 if ((*obj_desc
)->buffer
.length
== 0) {
250 (*obj_desc
)->buffer
.pointer
= NULL
;
251 REPORT_WARNING (("Buffer created with zero length in AML\n"));
256 (*obj_desc
)->buffer
.pointer
=
257 acpi_cm_callocate ((*obj_desc
)->buffer
.length
);
259 if (!(*obj_desc
)->buffer
.pointer
) {
260 return (AE_NO_MEMORY
);
265 * Second arg is the buffer data (optional)
266 * Byte_list can be either individual bytes or a
267 * string initializer!
272 byte_list
= (ACPI_PARSE2_OBJECT
*) arg
->next
;
274 if (byte_list
->opcode
!= AML_BYTELIST_OP
) {
278 MEMCPY ((*obj_desc
)->buffer
.pointer
, byte_list
->data
,
279 (*obj_desc
)->buffer
.length
);
285 case ACPI_TYPE_PACKAGE
:
288 * When called, an internal package object has already
289 * been built and is pointed to by *Obj_desc.
290 * Acpi_ds_build_internal_object build another internal
291 * package object, so remove reference to the original
292 * so that it is deleted. Error checking is done
293 * within the remove reference function.
295 acpi_cm_remove_reference(*obj_desc
);
297 status
= acpi_ds_build_internal_object (walk_state
, op
, obj_desc
);
300 case ACPI_TYPE_INTEGER
:
301 (*obj_desc
)->integer
.value
= op
->value
.integer
;
305 case ACPI_TYPE_STRING
:
306 (*obj_desc
)->string
.pointer
= op
->value
.string
;
307 (*obj_desc
)->string
.length
= STRLEN (op
->value
.string
);
311 case ACPI_TYPE_METHOD
:
315 case INTERNAL_TYPE_REFERENCE
:
317 switch (ACPI_GET_OP_CLASS (op_info
)) {
318 case OPTYPE_LOCAL_VARIABLE
:
320 /* Split the opcode into a base opcode + offset */
322 (*obj_desc
)->reference
.opcode
= AML_LOCAL_OP
;
323 (*obj_desc
)->reference
.offset
= opcode
- AML_LOCAL_OP
;
326 case OPTYPE_METHOD_ARGUMENT
:
328 /* Split the opcode into a base opcode + offset */
330 (*obj_desc
)->reference
.opcode
= AML_ARG_OP
;
331 (*obj_desc
)->reference
.offset
= opcode
- AML_ARG_OP
;
334 default: /* Constants, Literals, etc.. */
336 if (op
->opcode
== AML_NAMEPATH_OP
) {
337 /* Node was saved in Op */
339 (*obj_desc
)->reference
.node
= op
->node
;
342 (*obj_desc
)->reference
.opcode
= opcode
;
358 /*****************************************************************************
360 * FUNCTION: Acpi_ds_build_internal_simple_obj
362 * PARAMETERS: Op - Parser object to be translated
363 * Obj_desc_ptr - Where the ACPI internal object is returned
367 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
368 * Simple objects are any objects other than a package object!
370 ****************************************************************************/
373 acpi_ds_build_internal_simple_obj (
374 ACPI_WALK_STATE
*walk_state
,
375 ACPI_PARSE_OBJECT
*op
,
376 ACPI_OPERAND_OBJECT
**obj_desc_ptr
)
378 ACPI_OPERAND_OBJECT
*obj_desc
;
379 OBJECT_TYPE_INTERNAL type
;
385 if (op
->opcode
== AML_NAMEPATH_OP
) {
387 * This is an object reference. If The name was
388 * previously looked up in the NS, it is stored in this op.
389 * Otherwise, go ahead and look it up now
393 status
= acpi_ns_lookup (walk_state
->scope_info
,
394 op
->value
.string
, ACPI_TYPE_ANY
,
396 NS_SEARCH_PARENT
| NS_DONT_OPEN_SCOPE
,
398 (ACPI_NAMESPACE_NODE
**)&(op
->node
));
400 if (ACPI_FAILURE (status
)) {
401 if (status
== AE_NOT_FOUND
) {
403 acpi_ns_externalize_name (ACPI_UINT32_MAX
, op
->value
.string
, &length
, &name
);
406 REPORT_WARNING (("Reference %s at AML %X not found\n",
407 name
, op
->aml_offset
));
411 REPORT_WARNING (("Reference %s at AML %X not found\n",
412 op
->value
.string
, op
->aml_offset
));
414 *obj_desc_ptr
= NULL
;
424 * The reference will be a Reference
425 * TBD: [Restructure] unless we really need a separate
426 * type of INTERNAL_TYPE_REFERENCE change
427 * Acpi_ds_map_opcode_to_data_type to handle this case
429 type
= INTERNAL_TYPE_REFERENCE
;
432 type
= acpi_ds_map_opcode_to_data_type (op
->opcode
, NULL
);
436 /* Create and init the internal ACPI object */
438 obj_desc
= acpi_cm_create_internal_object (type
);
440 return (AE_NO_MEMORY
);
443 status
= acpi_ds_init_object_from_op (walk_state
, op
,
444 op
->opcode
, &obj_desc
);
446 if (ACPI_FAILURE (status
)) {
447 acpi_cm_remove_reference (obj_desc
);
451 *obj_desc_ptr
= obj_desc
;
457 /*****************************************************************************
459 * FUNCTION: Acpi_ds_build_internal_package_obj
461 * PARAMETERS: Op - Parser object to be translated
462 * Obj_desc_ptr - Where the ACPI internal object is returned
466 * DESCRIPTION: Translate a parser Op package object to the equivalent
469 ****************************************************************************/
472 acpi_ds_build_internal_package_obj (
473 ACPI_WALK_STATE
*walk_state
,
474 ACPI_PARSE_OBJECT
*op
,
475 ACPI_OPERAND_OBJECT
**obj_desc_ptr
)
477 ACPI_PARSE_OBJECT
*arg
;
478 ACPI_OPERAND_OBJECT
*obj_desc
;
479 ACPI_STATUS status
= AE_OK
;
482 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE
);
484 return (AE_NO_MEMORY
);
487 /* The first argument must be the package length */
490 obj_desc
->package
.count
= arg
->value
.integer
;
493 * Allocate the array of pointers (ptrs to the
494 * individual objects) Add an extra pointer slot so
495 * that the list is always null terminated.
498 obj_desc
->package
.elements
=
499 acpi_cm_callocate ((obj_desc
->package
.count
+ 1) *
502 if (!obj_desc
->package
.elements
) {
503 /* Package vector allocation failure */
505 REPORT_ERROR (("Ds_build_internal_package_obj: Package vector allocation failure\n"));
507 acpi_cm_delete_object_desc (obj_desc
);
508 return (AE_NO_MEMORY
);
511 obj_desc
->package
.next_element
= obj_desc
->package
.elements
;
514 * Now init the elements of the package
519 if (arg
->opcode
== AML_PACKAGE_OP
) {
520 status
= acpi_ds_build_internal_package_obj (walk_state
, arg
,
521 obj_desc
->package
.next_element
);
525 status
= acpi_ds_build_internal_simple_obj (walk_state
, arg
,
526 obj_desc
->package
.next_element
);
529 obj_desc
->package
.next_element
++;
533 *obj_desc_ptr
= obj_desc
;
538 /*****************************************************************************
540 * FUNCTION: Acpi_ds_build_internal_object
542 * PARAMETERS: Op - Parser object to be translated
543 * Obj_desc_ptr - Where the ACPI internal object is returned
547 * DESCRIPTION: Translate a parser Op object to the equivalent namespace
550 ****************************************************************************/
553 acpi_ds_build_internal_object (
554 ACPI_WALK_STATE
*walk_state
,
555 ACPI_PARSE_OBJECT
*op
,
556 ACPI_OPERAND_OBJECT
**obj_desc_ptr
)
561 if (op
->opcode
== AML_PACKAGE_OP
) {
562 status
= acpi_ds_build_internal_package_obj (walk_state
, op
,
567 status
= acpi_ds_build_internal_simple_obj (walk_state
, op
,
575 /*****************************************************************************
577 * FUNCTION: Acpi_ds_create_node
579 * PARAMETERS: Op - Parser object to be translated
580 * Obj_desc_ptr - Where the ACPI internal object is returned
586 ****************************************************************************/
589 acpi_ds_create_node (
590 ACPI_WALK_STATE
*walk_state
,
591 ACPI_NAMESPACE_NODE
*node
,
592 ACPI_PARSE_OBJECT
*op
)
595 ACPI_OPERAND_OBJECT
*obj_desc
;
598 if (!op
->value
.arg
) {
599 /* No arguments, there is nothing to do */
605 /* Build an internal object for the argument(s) */
607 status
= acpi_ds_build_internal_object (walk_state
,
608 op
->value
.arg
, &obj_desc
);
609 if (ACPI_FAILURE (status
)) {
614 /* Re-type the object according to it's argument */
616 node
->type
= obj_desc
->common
.type
;
620 status
= acpi_ns_attach_object ((ACPI_HANDLE
) node
, obj_desc
,
622 if (ACPI_FAILURE (status
)) {
631 acpi_cm_remove_reference (obj_desc
);