2 /******************************************************************************
4 * Module Name: amresolv - AML Interpreter object resolution
7 *****************************************************************************/
10 * Copyright (C) 2000, 2001 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
32 #define _COMPONENT ACPI_EXECUTER
33 MODULE_NAME ("amresolv")
36 /*******************************************************************************
38 * FUNCTION: Acpi_aml_get_field_unit_value
40 * PARAMETERS: *Field_desc - Pointer to a Field_unit
41 * *Result_desc - Pointer to an empty descriptor
42 * which will become a Number
43 * containing the field's value.
47 * DESCRIPTION: Retrieve the value from a Field_unit
49 ******************************************************************************/
52 acpi_aml_get_field_unit_value (
53 ACPI_OPERAND_OBJECT
*field_desc
,
54 ACPI_OPERAND_OBJECT
*result_desc
)
56 ACPI_STATUS status
= AE_OK
;
63 status
= AE_AML_NO_OPERAND
;
66 if (!(field_desc
->common
.flags
& AOPOBJ_DATA_VALID
)) {
67 status
= acpi_ds_get_field_unit_arguments (field_desc
);
68 if (ACPI_FAILURE (status
)) {
73 if (!field_desc
->field_unit
.container
) {
74 status
= AE_AML_INTERNAL
;
77 else if (ACPI_TYPE_BUFFER
!= field_desc
->field_unit
.container
->common
.type
) {
78 status
= AE_AML_OPERAND_TYPE
;
81 else if (!result_desc
) {
82 status
= AE_AML_INTERNAL
;
85 if (ACPI_FAILURE (status
)) {
90 /* Get the global lock if needed */
92 locked
= acpi_aml_acquire_global_lock (field_desc
->field_unit
.lock_rule
);
94 /* Field location is (base of buffer) + (byte offset) */
96 location
= field_desc
->field_unit
.container
->buffer
.pointer
97 + field_desc
->field_unit
.offset
;
100 * Construct Mask with as many 1 bits as the field width
102 * NOTE: Only the bottom 5 bits are valid for a shift operation, so
103 * special care must be taken for any shift greater than 31 bits.
105 * TBD: [Unhandled] Fields greater than 32-bits will not work.
108 if (field_desc
->field_unit
.length
< 32) {
109 mask
= ((u32
) 1 << field_desc
->field_unit
.length
) - (u32
) 1;
112 mask
= ACPI_UINT32_MAX
;
115 result_desc
->integer
.type
= (u8
) ACPI_TYPE_INTEGER
;
117 /* Get the 32 bit value at the location */
119 MOVE_UNALIGNED32_TO_32 (&result_desc
->integer
.value
, location
);
122 * Shift the 32-bit word containing the field, and mask off the
126 result_desc
->integer
.value
=
127 (result_desc
->integer
.value
>> field_desc
->field_unit
.bit_offset
) & mask
;
129 /* Release global lock if we acquired it earlier */
131 acpi_aml_release_global_lock (locked
);
137 /*******************************************************************************
139 * FUNCTION: Acpi_aml_resolve_to_value
141 * PARAMETERS: **Stack_ptr - Points to entry on Obj_stack, which can
142 * be either an (ACPI_OPERAND_OBJECT *)
147 * DESCRIPTION: Convert Reference objects to values
149 ******************************************************************************/
152 acpi_aml_resolve_to_value (
153 ACPI_OPERAND_OBJECT
**stack_ptr
,
154 ACPI_WALK_STATE
*walk_state
)
156 ACPI_STATUS status
= AE_OK
;
159 if (!stack_ptr
|| !*stack_ptr
) {
160 return (AE_AML_NO_OPERAND
);
165 * The entity pointed to by the Stack_ptr can be either
166 * 1) A valid ACPI_OPERAND_OBJECT, or
167 * 2) A ACPI_NAMESPACE_NODE (Named_obj)
170 if (VALID_DESCRIPTOR_TYPE (*stack_ptr
, ACPI_DESC_TYPE_INTERNAL
)) {
172 status
= acpi_aml_resolve_object_to_value (stack_ptr
, walk_state
);
173 if (ACPI_FAILURE (status
)) {
179 * Object on the stack may have changed if Acpi_aml_resolve_object_to_value()
180 * was called (i.e., we can't use an _else_ here.)
183 if (VALID_DESCRIPTOR_TYPE (*stack_ptr
, ACPI_DESC_TYPE_NAMED
)) {
184 status
= acpi_aml_resolve_node_to_value ((ACPI_NAMESPACE_NODE
**) stack_ptr
, walk_state
);
192 /*******************************************************************************
194 * FUNCTION: Acpi_aml_resolve_object_to_value
196 * PARAMETERS: Stack_ptr - Pointer to a stack location that contains a
197 * ptr to an internal object.
201 * DESCRIPTION: Retrieve the value from an internal object. The Reference type
202 * uses the associated AML opcode to determine the value.
204 ******************************************************************************/
207 acpi_aml_resolve_object_to_value (
208 ACPI_OPERAND_OBJECT
**stack_ptr
,
209 ACPI_WALK_STATE
*walk_state
)
211 ACPI_OPERAND_OBJECT
*stack_desc
;
212 ACPI_STATUS status
= AE_OK
;
213 ACPI_HANDLE temp_handle
= NULL
;
214 ACPI_OPERAND_OBJECT
*obj_desc
= NULL
;
219 stack_desc
= *stack_ptr
;
221 /* This is an ACPI_OPERAND_OBJECT */
223 switch (stack_desc
->common
.type
) {
225 case INTERNAL_TYPE_REFERENCE
:
227 opcode
= stack_desc
->reference
.opcode
;
234 * Convert indirect name ptr to a direct name ptr.
235 * Then, Acpi_aml_resolve_node_to_value can be used to get the value
238 temp_handle
= stack_desc
->reference
.object
;
240 /* Delete the Reference Object */
242 acpi_cm_remove_reference (stack_desc
);
244 /* Put direct name pointer onto stack and exit */
246 (*stack_ptr
) = temp_handle
;
254 index
= stack_desc
->reference
.offset
;
257 * Get the local from the method's state info
258 * Note: this increments the local's object reference count
261 status
= acpi_ds_method_data_get_value (opcode
, index
,
262 walk_state
, &obj_desc
);
263 if (ACPI_FAILURE (status
)) {
268 * Now we can delete the original Reference Object and
269 * replace it with the resolve value
272 acpi_cm_remove_reference (stack_desc
);
273 *stack_ptr
= obj_desc
;
279 * TBD: [Restructure] These next three opcodes change the type of
280 * the object, which is actually a no-no.
285 stack_desc
->common
.type
= (u8
) ACPI_TYPE_INTEGER
;
286 stack_desc
->integer
.value
= 0;
292 stack_desc
->common
.type
= (u8
) ACPI_TYPE_INTEGER
;
293 stack_desc
->integer
.value
= 1;
299 stack_desc
->common
.type
= (u8
) ACPI_TYPE_INTEGER
;
300 stack_desc
->integer
.value
= ACPI_INTEGER_MAX
;
302 /* Truncate value if we are executing from a 32-bit ACPI table */
304 acpi_aml_truncate_for32bit_table (stack_desc
, walk_state
);
310 switch (stack_desc
->reference
.target_type
) {
311 case ACPI_TYPE_BUFFER_FIELD
:
313 /* Just return - leave the Reference on the stack */
317 case ACPI_TYPE_PACKAGE
:
318 obj_desc
= *stack_desc
->reference
.where
;
321 * Valid obj descriptor, copy pointer to return value
322 * (i.e., dereference the package index)
323 * Delete the ref object, increment the returned object
325 acpi_cm_remove_reference (stack_desc
);
326 acpi_cm_add_reference (obj_desc
);
327 *stack_ptr
= obj_desc
;
332 * A NULL object descriptor means an unitialized element of
333 * the package, can't deref it
336 status
= AE_AML_UNINITIALIZED_ELEMENT
;
341 /* Invalid reference OBJ*/
343 status
= AE_AML_INTERNAL
;
352 /* Just leave the object as-is */
358 status
= AE_AML_INTERNAL
;
360 } /* switch (Opcode) */
363 if (ACPI_FAILURE (status
)) {
367 break; /* case INTERNAL_TYPE_REFERENCE */
370 case ACPI_TYPE_FIELD_UNIT
:
372 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_ANY
);
374 /* Descriptor allocation failure */
376 return (AE_NO_MEMORY
);
379 status
= acpi_aml_get_field_unit_value (stack_desc
, obj_desc
);
380 if (ACPI_FAILURE (status
)) {
381 acpi_cm_remove_reference (obj_desc
);
385 *stack_ptr
= (void *) obj_desc
;
389 case INTERNAL_TYPE_BANK_FIELD
:
391 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_ANY
);
393 /* Descriptor allocation failure */
395 return (AE_NO_MEMORY
);
398 status
= acpi_aml_get_field_unit_value (stack_desc
, obj_desc
);
399 if (ACPI_FAILURE (status
)) {
400 acpi_cm_remove_reference (obj_desc
);
404 *stack_ptr
= (void *) obj_desc
;
408 /* TBD: [Future] - may need to handle Index_field, and Def_field someday */
414 } /* switch (Stack_desc->Common.Type) */