1 /******************************************************************************
3 * Module Name: dsobject - Dispatcher object management routines
6 *****************************************************************************/
9 * Copyright (C) 2000 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
34 #define _COMPONENT DISPATCHER
35 MODULE_NAME ("dsobject")
38 /*******************************************************************************
40 * FUNCTION: Acpi_ds_init_one_object
42 * PARAMETERS: Obj_handle - Node
43 * Level - Current nesting level
44 * Context - Points to a init info struct
45 * Return_value - Not used
49 * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object
50 * within the namespace.
52 * Currently, the only objects that require initialization are:
56 ******************************************************************************/
59 acpi_ds_init_one_object (
60 ACPI_HANDLE obj_handle
,
65 OBJECT_TYPE_INTERNAL type
;
67 ACPI_INIT_WALK_INFO
*info
= (ACPI_INIT_WALK_INFO
*) context
;
72 table_revision
= info
->table_desc
->pointer
->revision
;
75 * We are only interested in objects owned by the table that
79 if (((ACPI_NAMESPACE_NODE
*) obj_handle
)->owner_id
!=
80 info
->table_desc
->table_id
)
86 /* And even then, we are only interested in a few object types */
88 type
= acpi_ns_get_type (obj_handle
);
93 case ACPI_TYPE_REGION
:
95 acpi_ds_initialize_region (obj_handle
);
97 info
->op_region_count
++;
101 case ACPI_TYPE_METHOD
:
103 info
->method_count
++;
106 * Set the execution data width (32 or 64) based upon the
107 * revision number of the parent ACPI table.
110 if (table_revision
== 1) {
111 ((ACPI_NAMESPACE_NODE
*)obj_handle
)->flags
|= ANOBJ_DATA_WIDTH_32
;
115 * Always parse methods to detect errors, we may delete
116 * the parse tree below
119 status
= acpi_ds_parse_method (obj_handle
);
121 /* TBD: [Errors] what do we do with an error? */
123 if (ACPI_FAILURE (status
)) {
128 * Delete the parse tree. We simple re-parse the method
129 * for every execution since there isn't much overhead
131 acpi_ns_delete_namespace_subtree (obj_handle
);
139 * We ignore errors from above, and always return OK, since
140 * we don't want to abort the walk on a single error.
146 /*******************************************************************************
148 * FUNCTION: Acpi_ds_initialize_objects
154 * DESCRIPTION: Walk the entire namespace and perform any necessary
155 * initialization on the objects found therein
157 ******************************************************************************/
160 acpi_ds_initialize_objects (
161 ACPI_TABLE_DESC
*table_desc
,
162 ACPI_NAMESPACE_NODE
*start_node
)
165 ACPI_INIT_WALK_INFO info
;
168 info
.method_count
= 0;
169 info
.op_region_count
= 0;
170 info
.object_count
= 0;
171 info
.table_desc
= table_desc
;
174 /* Walk entire namespace from the supplied root */
176 status
= acpi_walk_namespace (ACPI_TYPE_ANY
, start_node
,
177 ACPI_UINT32_MAX
, acpi_ds_init_one_object
,
184 /*****************************************************************************
186 * FUNCTION: Acpi_ds_init_object_from_op
188 * PARAMETERS: Op - Parser op used to init the internal object
189 * Opcode - AML opcode associated with the object
190 * Obj_desc - Namespace object to be initialized
194 * DESCRIPTION: Initialize a namespace object from a parser Op and its
195 * associated arguments. The namespace object is a more compact
196 * representation of the Op and its arguments.
198 ****************************************************************************/
201 acpi_ds_init_object_from_op (
202 ACPI_WALK_STATE
*walk_state
,
203 ACPI_PARSE_OBJECT
*op
,
205 ACPI_OPERAND_OBJECT
**obj_desc
)
208 ACPI_PARSE_OBJECT
*arg
;
209 ACPI_PARSE2_OBJECT
*byte_list
;
210 ACPI_OPERAND_OBJECT
*arg_desc
;
211 ACPI_OPCODE_INFO
*op_info
;
214 op_info
= acpi_ps_get_opcode_info (opcode
);
215 if (ACPI_GET_OP_TYPE (op_info
) != ACPI_OP_TYPE_OPCODE
) {
222 /* Get and prepare the first argument */
224 switch ((*obj_desc
)->common
.type
)
226 case ACPI_TYPE_BUFFER
:
228 /* First arg is a number */
230 acpi_ds_create_operand (walk_state
, op
->value
.arg
, 0);
231 arg_desc
= walk_state
->operands
[walk_state
->num_operands
- 1];
232 acpi_ds_obj_stack_pop (1, walk_state
);
234 /* Resolve the object (could be an arg or local) */
236 status
= acpi_aml_resolve_to_value (&arg_desc
, walk_state
);
237 if (ACPI_FAILURE (status
)) {
238 acpi_cm_remove_reference (arg_desc
);
242 /* We are expecting a number */
244 if (arg_desc
->common
.type
!= ACPI_TYPE_NUMBER
) {
245 acpi_cm_remove_reference (arg_desc
);
249 /* Get the value, delete the internal object */
251 (*obj_desc
)->buffer
.length
= (u32
) arg_desc
->number
.value
;
252 acpi_cm_remove_reference (arg_desc
);
254 /* Allocate the buffer */
256 if ((*obj_desc
)->buffer
.length
== 0) {
257 (*obj_desc
)->buffer
.pointer
= NULL
;
258 REPORT_WARNING (("Buffer created with zero length in AML\n"));
263 (*obj_desc
)->buffer
.pointer
=
264 acpi_cm_callocate ((*obj_desc
)->buffer
.length
);
266 if (!(*obj_desc
)->buffer
.pointer
) {
267 return (AE_NO_MEMORY
);
272 * Second arg is the buffer data (optional)
273 * Byte_list can be either individual bytes or a
274 * string initializer!
279 byte_list
= (ACPI_PARSE2_OBJECT
*) arg
->next
;
281 if (byte_list
->opcode
!= AML_BYTELIST_OP
) {
285 MEMCPY ((*obj_desc
)->buffer
.pointer
, byte_list
->data
,
286 (*obj_desc
)->buffer
.length
);
292 case ACPI_TYPE_PACKAGE
:
295 * When called, an internal package object has already
296 * been built and is pointed to by *Obj_desc.
297 * Acpi_ds_build_internal_object build another internal
298 * package object, so remove reference to the original
299 * so that it is deleted. Error checking is done
300 * within the remove reference function.
302 acpi_cm_remove_reference(*obj_desc
);
304 status
= acpi_ds_build_internal_object (walk_state
, op
, obj_desc
);
307 case ACPI_TYPE_NUMBER
:
308 (*obj_desc
)->number
.value
= op
->value
.integer
;
312 case ACPI_TYPE_STRING
:
313 (*obj_desc
)->string
.pointer
= op
->value
.string
;
314 (*obj_desc
)->string
.length
= STRLEN (op
->value
.string
);
318 case ACPI_TYPE_METHOD
:
322 case INTERNAL_TYPE_REFERENCE
:
324 switch (ACPI_GET_OP_CLASS (op_info
))
326 case OPTYPE_LOCAL_VARIABLE
:
328 /* Split the opcode into a base opcode + offset */
330 (*obj_desc
)->reference
.op_code
= AML_LOCAL_OP
;
331 (*obj_desc
)->reference
.offset
= opcode
- AML_LOCAL_OP
;
334 case OPTYPE_METHOD_ARGUMENT
:
336 /* Split the opcode into a base opcode + offset */
338 (*obj_desc
)->reference
.op_code
= AML_ARG_OP
;
339 (*obj_desc
)->reference
.offset
= opcode
- AML_ARG_OP
;
342 default: /* Constants, Literals, etc.. */
344 if (op
->opcode
== AML_NAMEPATH_OP
) {
345 /* Node was saved in Op */
347 (*obj_desc
)->reference
.node
= op
->node
;
350 (*obj_desc
)->reference
.op_code
= opcode
;
366 /*****************************************************************************
368 * FUNCTION: Acpi_ds_build_internal_simple_obj
370 * PARAMETERS: Op - Parser object to be translated
371 * Obj_desc_ptr - Where the ACPI internal object is returned
375 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
376 * Simple objects are any objects other than a package object!
378 ****************************************************************************/
381 acpi_ds_build_internal_simple_obj (
382 ACPI_WALK_STATE
*walk_state
,
383 ACPI_PARSE_OBJECT
*op
,
384 ACPI_OPERAND_OBJECT
**obj_desc_ptr
)
386 ACPI_OPERAND_OBJECT
*obj_desc
;
387 OBJECT_TYPE_INTERNAL type
;
393 if (op
->opcode
== AML_NAMEPATH_OP
) {
395 * This is an object reference. If The name was
396 * previously looked up in the NS, it is stored in this op.
397 * Otherwise, go ahead and look it up now
401 status
= acpi_ns_lookup (walk_state
->scope_info
,
402 op
->value
.string
, ACPI_TYPE_ANY
,
404 NS_SEARCH_PARENT
| NS_DONT_OPEN_SCOPE
,
406 (ACPI_NAMESPACE_NODE
**)&(op
->node
));
408 if (ACPI_FAILURE (status
)) {
409 if (status
== AE_NOT_FOUND
) {
411 acpi_ns_externalize_name (ACPI_UINT32_MAX
, op
->value
.string
, &length
, &name
);
414 REPORT_WARNING (("Reference %s AML %X not found\n",
415 name
, op
->aml_offset
));
419 REPORT_WARNING (("Reference %s AML %X not found\n",
420 op
->value
.string
, op
->aml_offset
));
422 *obj_desc_ptr
= NULL
;
430 * The reference will be a Reference
431 * TBD: [Restructure] unless we really need a separate
432 * type of INTERNAL_TYPE_REFERENCE change
433 * Acpi_ds_map_opcode_to_data_type to handle this case
435 type
= INTERNAL_TYPE_REFERENCE
;
438 type
= acpi_ds_map_opcode_to_data_type (op
->opcode
, NULL
);
442 /* Create and init the internal ACPI object */
444 obj_desc
= acpi_cm_create_internal_object (type
);
446 return (AE_NO_MEMORY
);
449 status
= acpi_ds_init_object_from_op (walk_state
, op
,
450 op
->opcode
, &obj_desc
);
452 if (ACPI_FAILURE (status
)) {
453 acpi_cm_remove_reference (obj_desc
);
457 *obj_desc_ptr
= obj_desc
;
463 /*****************************************************************************
465 * FUNCTION: Acpi_ds_build_internal_package_obj
467 * PARAMETERS: Op - Parser object to be translated
468 * Obj_desc_ptr - Where the ACPI internal object is returned
472 * DESCRIPTION: Translate a parser Op package object to the equivalent
475 ****************************************************************************/
478 acpi_ds_build_internal_package_obj (
479 ACPI_WALK_STATE
*walk_state
,
480 ACPI_PARSE_OBJECT
*op
,
481 ACPI_OPERAND_OBJECT
**obj_desc_ptr
)
483 ACPI_PARSE_OBJECT
*arg
;
484 ACPI_OPERAND_OBJECT
*obj_desc
;
485 ACPI_STATUS status
= AE_OK
;
488 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE
);
490 return (AE_NO_MEMORY
);
493 /* The first argument must be the package length */
496 obj_desc
->package
.count
= arg
->value
.integer
;
499 * Allocate the array of pointers (ptrs to the
500 * individual objects) Add an extra pointer slot so
501 * that the list is always null terminated.
504 obj_desc
->package
.elements
=
505 acpi_cm_callocate ((obj_desc
->package
.count
+ 1) *
508 if (!obj_desc
->package
.elements
) {
509 /* Package vector allocation failure */
511 REPORT_ERROR (("Ds_build_internal_package_obj: Package vector allocation failure\n"));
513 acpi_cm_delete_object_desc (obj_desc
);
514 return (AE_NO_MEMORY
);
517 obj_desc
->package
.next_element
= obj_desc
->package
.elements
;
520 * Now init the elements of the package
525 if (arg
->opcode
== AML_PACKAGE_OP
) {
526 status
= acpi_ds_build_internal_package_obj (walk_state
, arg
,
527 obj_desc
->package
.next_element
);
531 status
= acpi_ds_build_internal_simple_obj (walk_state
, arg
,
532 obj_desc
->package
.next_element
);
535 obj_desc
->package
.next_element
++;
539 *obj_desc_ptr
= obj_desc
;
544 /*****************************************************************************
546 * FUNCTION: Acpi_ds_build_internal_object
548 * PARAMETERS: Op - Parser object to be translated
549 * Obj_desc_ptr - Where the ACPI internal object is returned
553 * DESCRIPTION: Translate a parser Op object to the equivalent namespace
556 ****************************************************************************/
559 acpi_ds_build_internal_object (
560 ACPI_WALK_STATE
*walk_state
,
561 ACPI_PARSE_OBJECT
*op
,
562 ACPI_OPERAND_OBJECT
**obj_desc_ptr
)
567 if (op
->opcode
== AML_PACKAGE_OP
) {
568 status
= acpi_ds_build_internal_package_obj (walk_state
, op
,
573 status
= acpi_ds_build_internal_simple_obj (walk_state
, op
,
581 /*****************************************************************************
583 * FUNCTION: Acpi_ds_create_node
585 * PARAMETERS: Op - Parser object to be translated
586 * Obj_desc_ptr - Where the ACPI internal object is returned
592 ****************************************************************************/
595 acpi_ds_create_node (
596 ACPI_WALK_STATE
*walk_state
,
597 ACPI_NAMESPACE_NODE
*node
,
598 ACPI_PARSE_OBJECT
*op
)
601 ACPI_OPERAND_OBJECT
*obj_desc
;
604 if (!op
->value
.arg
) {
605 /* No arguments, there is nothing to do */
611 /* Build an internal object for the argument(s) */
613 status
= acpi_ds_build_internal_object (walk_state
,
614 op
->value
.arg
, &obj_desc
);
615 if (ACPI_FAILURE (status
)) {
620 /* Re-type the object according to it's argument */
622 node
->type
= obj_desc
->common
.type
;
626 status
= acpi_ns_attach_object ((ACPI_HANDLE
) node
, obj_desc
,
628 if (ACPI_FAILURE (status
)) {
637 acpi_cm_remove_reference (obj_desc
);