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
38 #define _COMPONENT ACPI_EXECUTER
39 MODULE_NAME ("amresolv")
42 /*******************************************************************************
44 * FUNCTION: Acpi_aml_get_field_unit_value
46 * PARAMETERS: *Field_desc - Pointer to a Field_unit
47 * *Result_desc - Pointer to an empty descriptor
48 * which will become a Number
49 * containing the field's value.
53 * DESCRIPTION: Retrieve the value from a Field_unit
55 ******************************************************************************/
58 acpi_aml_get_field_unit_value (
59 ACPI_OPERAND_OBJECT
*field_desc
,
60 ACPI_OPERAND_OBJECT
*result_desc
)
62 ACPI_STATUS status
= AE_OK
;
69 status
= AE_AML_NO_OPERAND
;
72 if (!(field_desc
->common
.flags
& AOPOBJ_DATA_VALID
)) {
73 status
= acpi_ds_get_field_unit_arguments (field_desc
);
74 if (ACPI_FAILURE (status
)) {
79 if (!field_desc
->field_unit
.container
) {
80 status
= AE_AML_INTERNAL
;
83 else if (ACPI_TYPE_BUFFER
!= field_desc
->field_unit
.container
->common
.type
) {
84 status
= AE_AML_OPERAND_TYPE
;
87 else if (!result_desc
) {
88 status
= AE_AML_INTERNAL
;
91 if (ACPI_FAILURE (status
)) {
96 /* Get the global lock if needed */
98 locked
= acpi_aml_acquire_global_lock (field_desc
->field_unit
.lock_rule
);
100 /* Field location is (base of buffer) + (byte offset) */
102 location
= field_desc
->field_unit
.container
->buffer
.pointer
103 + field_desc
->field_unit
.offset
;
106 * Construct Mask with as many 1 bits as the field width
108 * NOTE: Only the bottom 5 bits are valid for a shift operation, so
109 * special care must be taken for any shift greater than 31 bits.
111 * TBD: [Unhandled] Fields greater than 32-bits will not work.
114 if (field_desc
->field_unit
.length
< 32) {
115 mask
= ((u32
) 1 << field_desc
->field_unit
.length
) - (u32
) 1;
118 mask
= ACPI_UINT32_MAX
;
121 result_desc
->integer
.type
= (u8
) ACPI_TYPE_INTEGER
;
123 /* Get the 32 bit value at the location */
125 MOVE_UNALIGNED32_TO_32 (&result_desc
->integer
.value
, location
);
128 * Shift the 32-bit word containing the field, and mask off the
132 result_desc
->integer
.value
=
133 (result_desc
->integer
.value
>> field_desc
->field_unit
.bit_offset
) & mask
;
135 /* Release global lock if we acquired it earlier */
137 acpi_aml_release_global_lock (locked
);
143 /*******************************************************************************
145 * FUNCTION: Acpi_aml_resolve_to_value
147 * PARAMETERS: **Stack_ptr - Points to entry on Obj_stack, which can
148 * be either an (ACPI_OPERAND_OBJECT *)
153 * DESCRIPTION: Convert Reference objects to values
155 ******************************************************************************/
158 acpi_aml_resolve_to_value (
159 ACPI_OPERAND_OBJECT
**stack_ptr
,
160 ACPI_WALK_STATE
*walk_state
)
162 ACPI_STATUS status
= AE_OK
;
165 if (!stack_ptr
|| !*stack_ptr
) {
166 return (AE_AML_NO_OPERAND
);
171 * The entity pointed to by the Stack_ptr can be either
172 * 1) A valid ACPI_OPERAND_OBJECT, or
173 * 2) A ACPI_NAMESPACE_NODE (Named_obj)
176 if (VALID_DESCRIPTOR_TYPE (*stack_ptr
, ACPI_DESC_TYPE_INTERNAL
)) {
178 status
= acpi_aml_resolve_object_to_value (stack_ptr
, walk_state
);
179 if (ACPI_FAILURE (status
)) {
185 * Object on the stack may have changed if Acpi_aml_resolve_object_to_value()
186 * was called (i.e., we can't use an _else_ here.)
189 if (VALID_DESCRIPTOR_TYPE (*stack_ptr
, ACPI_DESC_TYPE_NAMED
)) {
190 status
= acpi_aml_resolve_node_to_value ((ACPI_NAMESPACE_NODE
**) stack_ptr
, walk_state
);
198 /*******************************************************************************
200 * FUNCTION: Acpi_aml_resolve_object_to_value
202 * PARAMETERS: Stack_ptr - Pointer to a stack location that contains a
203 * ptr to an internal object.
207 * DESCRIPTION: Retrieve the value from an internal object. The Reference type
208 * uses the associated AML opcode to determine the value.
210 ******************************************************************************/
213 acpi_aml_resolve_object_to_value (
214 ACPI_OPERAND_OBJECT
**stack_ptr
,
215 ACPI_WALK_STATE
*walk_state
)
217 ACPI_OPERAND_OBJECT
*stack_desc
;
218 ACPI_STATUS status
= AE_OK
;
219 ACPI_HANDLE temp_handle
= NULL
;
220 ACPI_OPERAND_OBJECT
*obj_desc
= NULL
;
225 stack_desc
= *stack_ptr
;
227 /* This is an ACPI_OPERAND_OBJECT */
229 switch (stack_desc
->common
.type
) {
231 case INTERNAL_TYPE_REFERENCE
:
233 opcode
= stack_desc
->reference
.opcode
;
240 * Convert indirect name ptr to a direct name ptr.
241 * Then, Acpi_aml_resolve_node_to_value can be used to get the value
244 temp_handle
= stack_desc
->reference
.object
;
246 /* Delete the Reference Object */
248 acpi_cm_remove_reference (stack_desc
);
250 /* Put direct name pointer onto stack and exit */
252 (*stack_ptr
) = temp_handle
;
260 index
= stack_desc
->reference
.offset
;
263 * Get the local from the method's state info
264 * Note: this increments the local's object reference count
267 status
= acpi_ds_method_data_get_value (opcode
, index
,
268 walk_state
, &obj_desc
);
269 if (ACPI_FAILURE (status
)) {
274 * Now we can delete the original Reference Object and
275 * replace it with the resolve value
278 acpi_cm_remove_reference (stack_desc
);
279 *stack_ptr
= obj_desc
;
285 * TBD: [Restructure] These next three opcodes change the type of
286 * the object, which is actually a no-no.
291 stack_desc
->common
.type
= (u8
) ACPI_TYPE_INTEGER
;
292 stack_desc
->integer
.value
= 0;
298 stack_desc
->common
.type
= (u8
) ACPI_TYPE_INTEGER
;
299 stack_desc
->integer
.value
= 1;
305 stack_desc
->common
.type
= (u8
) ACPI_TYPE_INTEGER
;
306 stack_desc
->integer
.value
= ACPI_INTEGER_MAX
;
308 /* Truncate value if we are executing from a 32-bit ACPI table */
310 acpi_aml_truncate_for32bit_table (stack_desc
, walk_state
);
316 switch (stack_desc
->reference
.target_type
) {
317 case ACPI_TYPE_BUFFER_FIELD
:
319 /* Just return - leave the Reference on the stack */
323 case ACPI_TYPE_PACKAGE
:
324 obj_desc
= *stack_desc
->reference
.where
;
327 * Valid obj descriptor, copy pointer to return value
328 * (i.e., dereference the package index)
329 * Delete the ref object, increment the returned object
331 acpi_cm_remove_reference (stack_desc
);
332 acpi_cm_add_reference (obj_desc
);
333 *stack_ptr
= obj_desc
;
338 * A NULL object descriptor means an unitialized element of
339 * the package, can't deref it
342 status
= AE_AML_UNINITIALIZED_ELEMENT
;
347 /* Invalid reference OBJ*/
349 status
= AE_AML_INTERNAL
;
358 /* Just leave the object as-is */
364 status
= AE_AML_INTERNAL
;
366 } /* switch (Opcode) */
369 if (ACPI_FAILURE (status
)) {
373 break; /* case INTERNAL_TYPE_REFERENCE */
376 case ACPI_TYPE_FIELD_UNIT
:
378 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_ANY
);
380 /* Descriptor allocation failure */
382 return (AE_NO_MEMORY
);
385 status
= acpi_aml_get_field_unit_value (stack_desc
, obj_desc
);
386 if (ACPI_FAILURE (status
)) {
387 acpi_cm_remove_reference (obj_desc
);
391 *stack_ptr
= (void *) obj_desc
;
395 case INTERNAL_TYPE_BANK_FIELD
:
397 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_ANY
);
399 /* Descriptor allocation failure */
401 return (AE_NO_MEMORY
);
404 status
= acpi_aml_get_field_unit_value (stack_desc
, obj_desc
);
405 if (ACPI_FAILURE (status
)) {
406 acpi_cm_remove_reference (obj_desc
);
410 *stack_ptr
= (void *) obj_desc
;
414 /* TBD: [Future] - may need to handle Index_field, and Def_field someday */
420 } /* switch (Stack_desc->Common.Type) */