2 /******************************************************************************
4 * Module Name: amresnte - AML Interpreter object resolution
7 *****************************************************************************/
10 * Copyright (C) 2000 R. Byron Moore
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 #define _COMPONENT INTERPRETER
39 MODULE_NAME ("amresnte")
42 /*******************************************************************************
44 * FUNCTION: Acpi_aml_resolve_node_to_value
46 * PARAMETERS: Stack_ptr - Pointer to a location on a stack that contains
47 * a pointer to an Node
51 * DESCRIPTION: Resolve a ACPI_NAMESPACE_NODE (Node,
52 * A.K.A. a "direct name pointer")
54 * Note: for some of the data types, the pointer attached to the Node
55 * can be either a pointer to an actual internal object or a pointer into the
56 * AML stream itself. These types are currently:
64 ******************************************************************************/
67 acpi_aml_resolve_node_to_value (
68 ACPI_NAMESPACE_NODE
**stack_ptr
,
69 ACPI_WALK_STATE
*walk_state
)
72 ACPI_STATUS status
= AE_OK
;
73 ACPI_OPERAND_OBJECT
*val_desc
= NULL
;
74 ACPI_OPERAND_OBJECT
*obj_desc
= NULL
;
75 ACPI_NAMESPACE_NODE
*node
;
76 u8
*aml_pointer
= NULL
;
77 OBJECT_TYPE_INTERNAL entry_type
;
79 u8 attached_aml_pointer
= FALSE
;
81 ACPI_INTEGER temp_val
;
82 OBJECT_TYPE_INTERNAL object_type
;
89 * The stack pointer is a "Direct name ptr", and points to a
90 * a ACPI_NAMESPACE_NODE (Node). Get the pointer that is attached to
94 val_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) node
);
95 entry_type
= acpi_ns_get_type ((ACPI_HANDLE
) node
);
98 * The Val_desc attached to the Node can be either:
99 * 1) An internal ACPI object
100 * 2) A pointer into the AML stream (into one of the ACPI system tables)
103 if (acpi_tb_system_table_pointer (val_desc
)) {
104 attached_aml_pointer
= TRUE
;
105 aml_opcode
= *((u8
*) val_desc
);
106 aml_pointer
= ((u8
*) val_desc
) + 1;
112 * Several Entry_types do not require further processing, so
113 * we will return immediately
115 /* Devices rarely have an attached object, return the Node
116 * and Method locals and arguments have a pseudo-Node
118 if (entry_type
== ACPI_TYPE_DEVICE
||
119 (node
->flags
& (ANOBJ_METHOD_ARG
| ANOBJ_METHOD_LOCAL
)))
125 return (AE_AML_NO_OPERAND
);
129 * Action is based on the type of the Node, which indicates the type
130 * of the attached object or pointer
135 case ACPI_TYPE_PACKAGE
:
137 if (attached_aml_pointer
) {
139 * This means that the package initialization is not parsed
140 * -- should not happen
142 return (AE_NOT_IMPLEMENTED
);
145 /* Val_desc is an internal object in all cases by the time we get here */
147 if (ACPI_TYPE_PACKAGE
!= val_desc
->common
.type
) {
148 return (AE_AML_OPERAND_TYPE
);
151 /* Return an additional reference to the object */
154 acpi_cm_add_reference (obj_desc
);
158 case ACPI_TYPE_BUFFER
:
160 if (attached_aml_pointer
) {
162 * This means that the buffer initialization is not parsed
163 * -- should not happen
165 return (AE_NOT_IMPLEMENTED
);
168 /* Val_desc is an internal object in all cases by the time we get here */
170 if (ACPI_TYPE_BUFFER
!= val_desc
->common
.type
) {
171 return (AE_AML_OPERAND_TYPE
);
174 /* Return an additional reference to the object */
177 acpi_cm_add_reference (obj_desc
);
181 case ACPI_TYPE_STRING
:
183 if (attached_aml_pointer
) {
184 /* Allocate a new string object */
186 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_STRING
);
188 return (AE_NO_MEMORY
);
191 /* Init the internal object */
193 obj_desc
->string
.pointer
= (NATIVE_CHAR
*) aml_pointer
;
194 obj_desc
->string
.length
= STRLEN (obj_desc
->string
.pointer
);
198 if (ACPI_TYPE_STRING
!= val_desc
->common
.type
) {
199 return (AE_AML_OPERAND_TYPE
);
202 /* Return an additional reference to the object */
205 acpi_cm_add_reference (obj_desc
);
211 case ACPI_TYPE_NUMBER
:
214 * The Node has an attached internal object, make sure that it's a
218 if (ACPI_TYPE_NUMBER
!= val_desc
->common
.type
) {
219 return (AE_AML_OPERAND_TYPE
);
222 /* Return an additional reference to the object */
225 acpi_cm_add_reference (obj_desc
);
229 case INTERNAL_TYPE_DEF_FIELD
:
232 * TBD: [Investigate] Is this the correct solution?
234 * This section was extended to convert to generic buffer if
235 * the return length is greater than 32 bits, but still allows
236 * for returning a type Number for smaller values because the
237 * caller can then apply arithmetic operators on those fields.
239 * XXX - Implementation limitation: Fields are implemented as type
240 * XXX - Number, but they really are supposed to be type Buffer.
241 * XXX - The two are interchangeable only for lengths <= 32 bits.
243 if(val_desc
->field
.length
> 32) {
244 object_type
= ACPI_TYPE_BUFFER
;
247 object_type
= ACPI_TYPE_NUMBER
;
251 * Create the destination buffer object and the buffer space.
253 obj_desc
= acpi_cm_create_internal_object (object_type
);
255 return (AE_NO_MEMORY
);
259 * Fill in the object specific details
261 if (ACPI_TYPE_BUFFER
== object_type
) {
262 obj_desc
->buffer
.pointer
= acpi_cm_callocate (val_desc
->field
.length
);
263 if (!obj_desc
->buffer
.pointer
) {
264 acpi_cm_remove_reference(obj_desc
);
265 return (AE_NO_MEMORY
);
268 obj_desc
->buffer
.length
= val_desc
->field
.length
;
270 status
= acpi_aml_access_named_field (ACPI_READ
, (ACPI_HANDLE
) node
,
271 obj_desc
->buffer
.pointer
, obj_desc
->buffer
.length
);
273 if (ACPI_FAILURE (status
)) {
278 status
= acpi_aml_access_named_field (ACPI_READ
, (ACPI_HANDLE
) node
,
279 &temp_val
, sizeof (temp_val
));
281 if (ACPI_FAILURE (status
)) {
285 obj_desc
->number
.value
= temp_val
;
292 case INTERNAL_TYPE_BANK_FIELD
:
294 if (attached_aml_pointer
) {
295 return (AE_AML_OPERAND_TYPE
);
298 if (INTERNAL_TYPE_BANK_FIELD
!= val_desc
->common
.type
) {
299 return (AE_AML_OPERAND_TYPE
);
303 /* Get the global lock if needed */
305 obj_desc
= (ACPI_OPERAND_OBJECT
*) *stack_ptr
;
306 locked
= acpi_aml_acquire_global_lock (obj_desc
->field_unit
.lock_rule
);
308 /* Set Index value to select proper Data register */
309 /* perform the update */
311 status
= acpi_aml_access_named_field (ACPI_WRITE
,
312 val_desc
->bank_field
.bank_select
, &val_desc
->bank_field
.value
,
313 sizeof (val_desc
->bank_field
.value
));
315 acpi_aml_release_global_lock (locked
);
318 if (ACPI_FAILURE (status
)) {
322 /* Read Data value */
324 status
= acpi_aml_access_named_field (ACPI_READ
,
325 (ACPI_HANDLE
) val_desc
->bank_field
.container
,
326 &temp_val
, sizeof (temp_val
));
327 if (ACPI_FAILURE (status
)) {
331 /* Create an object for the result */
333 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_NUMBER
);
335 return (AE_NO_MEMORY
);
338 obj_desc
->number
.value
= temp_val
;
342 case INTERNAL_TYPE_INDEX_FIELD
:
344 if (attached_aml_pointer
) {
345 return (AE_AML_OPERAND_TYPE
);
348 if (INTERNAL_TYPE_INDEX_FIELD
!= val_desc
->common
.type
) {
349 return (AE_AML_OPERAND_TYPE
);
353 /* Set Index value to select proper Data register */
354 /* Get the global lock if needed */
356 obj_desc
= (ACPI_OPERAND_OBJECT
*) *stack_ptr
;
357 locked
= acpi_aml_acquire_global_lock (obj_desc
->field_unit
.lock_rule
);
359 /* Perform the update */
361 status
= acpi_aml_access_named_field (ACPI_WRITE
,
362 val_desc
->index_field
.index
, &val_desc
->index_field
.value
,
363 sizeof (val_desc
->index_field
.value
));
365 acpi_aml_release_global_lock (locked
);
367 if (ACPI_FAILURE (status
)) {
371 /* Read Data value */
373 status
= acpi_aml_access_named_field (ACPI_READ
, val_desc
->index_field
.data
,
374 &temp_val
, sizeof (temp_val
));
375 if (ACPI_FAILURE (status
)) {
379 /* Create an object for the result */
381 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_NUMBER
);
383 return (AE_NO_MEMORY
);
386 obj_desc
->number
.value
= temp_val
;
390 case ACPI_TYPE_FIELD_UNIT
:
392 if (attached_aml_pointer
) {
393 return (AE_AML_OPERAND_TYPE
);
396 if (val_desc
->common
.type
!= (u8
) entry_type
) {
397 return (AE_AML_OPERAND_TYPE
);
401 /* Create object for result */
403 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_ANY
);
405 return (AE_NO_MEMORY
);
408 status
= acpi_aml_get_field_unit_value (val_desc
, obj_desc
);
409 if (ACPI_FAILURE (status
)) {
410 acpi_cm_remove_reference (obj_desc
);
418 * For these objects, just return the object attached to the Node
421 case ACPI_TYPE_MUTEX
:
422 case ACPI_TYPE_METHOD
:
423 case ACPI_TYPE_POWER
:
424 case ACPI_TYPE_PROCESSOR
:
425 case ACPI_TYPE_THERMAL
:
426 case ACPI_TYPE_EVENT
:
427 case ACPI_TYPE_REGION
:
430 /* Return an additional reference to the object */
433 acpi_cm_add_reference (obj_desc
);
437 /* TYPE_Any is untyped, and thus there is no object associated with it */
441 return (AE_AML_OPERAND_TYPE
); /* Cannot be AE_TYPE */
446 * The only named references allowed are named constants
448 * e.g. Name (\OSFL, Ones)
450 case INTERNAL_TYPE_REFERENCE
:
452 switch (val_desc
->reference
.op_code
)
469 temp_val
= ACPI_INTEGER_MAX
;
475 return (AE_AML_BAD_OPCODE
);
478 /* Create object for result */
480 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_NUMBER
);
482 return (AE_NO_MEMORY
);
485 obj_desc
->number
.value
= temp_val
;
487 /* Truncate value if we are executing from a 32-bit ACPI table */
489 acpi_aml_truncate_for32bit_table (obj_desc
, walk_state
);
493 /* Default case is for unknown types */
497 return (AE_AML_OPERAND_TYPE
);
499 } /* switch (Entry_type) */
502 /* Put the object descriptor on the stack */
504 *stack_ptr
= (void *) obj_desc
;