2 /******************************************************************************
4 * Module Name: amresolv - AML Interpreter object resolution
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
37 #define _COMPONENT INTERPRETER
38 MODULE_NAME ("amresolv");
41 /*******************************************************************************
43 * FUNCTION: Acpi_aml_get_field_unit_value
45 * PARAMETERS: *Field_desc - Pointer to a Field_unit
46 * *Result_desc - Pointer to an empty descriptor
47 * which will become a Number
48 * containing the field's value.
52 * DESCRIPTION: Retrieve the value from a Field_unit
54 ******************************************************************************/
57 acpi_aml_get_field_unit_value (
58 ACPI_OBJECT_INTERNAL
*field_desc
,
59 ACPI_OBJECT_INTERNAL
*result_desc
)
61 ACPI_STATUS status
= AE_OK
;
68 status
= AE_AML_NO_OPERAND
;
71 else if (!field_desc
->field_unit
.container
) {
72 status
= AE_AML_INTERNAL
;
75 else if (ACPI_TYPE_BUFFER
!= field_desc
->field_unit
.container
->common
.type
) {
76 status
= AE_AML_OPERAND_TYPE
;
79 else if (field_desc
->field_unit
.sequence
80 != field_desc
->field_unit
.container
->buffer
.sequence
)
82 status
= AE_AML_INTERNAL
;
85 else if (!result_desc
) {
86 status
= AE_AML_INTERNAL
;
89 if (ACPI_FAILURE (status
)) {
94 /* Get the global lock if needed */
96 locked
= acpi_aml_acquire_global_lock (field_desc
->field_unit
.lock_rule
);
98 /* Field location is (base of buffer) + (byte offset) */
100 location
= field_desc
->field_unit
.container
->buffer
.pointer
101 + field_desc
->field_unit
.offset
;
104 * Construct Mask with as many 1 bits as the field width
106 * NOTE: Only the bottom 5 bits are valid for a shift operation, so
107 * special care must be taken for any shift greater than 31 bits.
109 * TBD: [Unhandled] Fields greater than 32-bits will not work.
112 if (field_desc
->field_unit
.length
< 32) {
113 mask
= ((u32
) 1 << field_desc
->field_unit
.length
) - (u32
) 1;
119 result_desc
->number
.type
= (u8
) ACPI_TYPE_NUMBER
;
121 /* Get the 32 bit value at the location */
123 MOVE_UNALIGNED32_TO_32 (&result_desc
->number
.value
, location
);
126 * Shift the 32-bit word containing the field, and mask off the
130 result_desc
->number
.value
=
131 (result_desc
->number
.value
>> field_desc
->field_unit
.bit_offset
) & mask
;
133 /* Release global lock if we acquired it earlier */
135 acpi_aml_release_global_lock (locked
);
141 /*******************************************************************************
143 * FUNCTION: Acpi_aml_resolve_to_value
145 * PARAMETERS: **Stack_ptr - Points to entry on Obj_stack, which can
146 * be either an (ACPI_OBJECT_INTERNAL *)
151 * DESCRIPTION: Convert Reference entries on Obj_stack to Rvalues
153 ******************************************************************************/
156 acpi_aml_resolve_to_value (
157 ACPI_OBJECT_INTERNAL
**stack_ptr
)
159 ACPI_STATUS status
= AE_OK
;
162 if (!stack_ptr
|| !*stack_ptr
) {
163 return (AE_AML_NO_OPERAND
);
168 * The entity pointed to by the Stack_ptr can be either
169 * 1) A valid ACPI_OBJECT_INTERNAL, or
170 * 2) A ACPI_NAMED_OBJECT(nte)
173 if (VALID_DESCRIPTOR_TYPE (*stack_ptr
, ACPI_DESC_TYPE_INTERNAL
)) {
175 status
= acpi_aml_resolve_object_to_value (stack_ptr
);
176 if (ACPI_FAILURE (status
)) {
182 * Object on the stack may have changed if Acpi_aml_resolve_object_to_value()
183 * was called (i.e., we can't use an _else_ here.)
186 if (VALID_DESCRIPTOR_TYPE (*stack_ptr
, ACPI_DESC_TYPE_NAMED
)) {
187 status
= acpi_aml_resolve_entry_to_value ((ACPI_NAMED_OBJECT
**) stack_ptr
);
195 /*******************************************************************************
197 * FUNCTION: Acpi_aml_resolve_object_to_value
199 * PARAMETERS: Stack_ptr - Pointer to a stack location that contains a
200 * ptr to an internal object.
204 * DESCRIPTION: Retrieve the value from an internal object. The Reference type
205 * uses the associated AML opcode to determine the value.
207 ******************************************************************************/
210 acpi_aml_resolve_object_to_value (
211 ACPI_OBJECT_INTERNAL
**stack_ptr
)
213 ACPI_OBJECT_INTERNAL
*stack_desc
;
214 ACPI_STATUS status
= AE_OK
;
215 ACPI_HANDLE temp_handle
= NULL
;
216 ACPI_OBJECT_INTERNAL
*obj_desc
= NULL
;
221 stack_desc
= *stack_ptr
;
223 /* This is an ACPI_OBJECT_INTERNAL */
225 switch (stack_desc
->common
.type
)
228 case INTERNAL_TYPE_REFERENCE
:
230 opcode
= stack_desc
->reference
.op_code
;
238 * Convert indirect name ptr to a direct name ptr.
239 * Then, Acpi_aml_resolve_entry_to_value can be used to get the value
242 temp_handle
= stack_desc
->reference
.object
;
244 /* Delete the Reference Object */
246 acpi_cm_remove_reference (stack_desc
);
248 /* Put direct name pointer onto stack and exit */
250 (*stack_ptr
) = temp_handle
;
257 index
= stack_desc
->reference
.offset
;
259 /* Delete the Reference Object */
261 acpi_cm_remove_reference (stack_desc
);
264 * Get the local from the method's state info
265 * Note: this increments the object reference count
268 status
= acpi_ds_method_data_get_value (MTH_TYPE_LOCAL
, index
,
270 if (ACPI_FAILURE (status
)) {
274 stack_desc
= *stack_ptr
;
276 if (ACPI_TYPE_NUMBER
== stack_desc
->common
.type
) {
277 /* Value is a Number */
286 index
= stack_desc
->reference
.offset
;
288 /* Delete the Reference Object*/
290 acpi_cm_remove_reference (stack_desc
);
293 * Get the argument from the method's state info
294 * Note: this increments the object reference count
297 status
= acpi_ds_method_data_get_value (MTH_TYPE_ARG
, index
,
299 if (ACPI_FAILURE (status
)) {
303 stack_desc
= *stack_ptr
;
305 if (ACPI_TYPE_NUMBER
== stack_desc
->common
.type
) {
306 /* Value is a Number */
314 * TBD: [Restructure] These next three opcodes change the type of
315 * the object, which is actually a no-no.
320 stack_desc
->common
.type
= (u8
) ACPI_TYPE_NUMBER
;
321 stack_desc
->number
.value
= 0;
327 stack_desc
->common
.type
= (u8
) ACPI_TYPE_NUMBER
;
328 stack_desc
->number
.value
= 1;
334 stack_desc
->common
.type
= (u8
) ACPI_TYPE_NUMBER
;
335 stack_desc
->number
.value
= 0xFFFFFFFF;
341 switch (stack_desc
->reference
.target_type
)
343 case ACPI_TYPE_BUFFER_FIELD
:
345 /* Just return - leave the Reference on the stack */
349 case ACPI_TYPE_PACKAGE
:
350 obj_desc
= *stack_desc
->reference
.where
;
353 * Valid obj descriptor, copy pointer to return value
354 * (i.e., dereference the package index)
355 * Delete the ref object, increment the returned object
357 acpi_cm_remove_reference (stack_desc
);
358 acpi_cm_add_reference (obj_desc
);
359 *stack_ptr
= obj_desc
;
364 * A NULL object descriptor means an unitialized element of
365 * the package, can't deref it
368 status
= AE_AML_UNINITIALIZED_ELEMENT
;
373 /* Invalid reference OBJ*/
375 status
= AE_AML_INTERNAL
;
384 /* Just leave the object as-is */
390 status
= AE_AML_INTERNAL
;
392 } /* switch (Opcode) */
395 if (AE_OK
!= status
) {
399 break; /* case INTERNAL_TYPE_REFERENCE */
402 case ACPI_TYPE_FIELD_UNIT
:
404 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_ANY
);
406 /* Descriptor allocation failure */
408 return (AE_NO_MEMORY
);
411 status
= acpi_aml_get_field_unit_value (stack_desc
, obj_desc
);
412 if (ACPI_FAILURE (status
)) {
413 acpi_cm_remove_reference (obj_desc
);
417 *stack_ptr
= (void *) obj_desc
;
421 case INTERNAL_TYPE_BANK_FIELD
:
423 obj_desc
= acpi_cm_create_internal_object (ACPI_TYPE_ANY
);
425 /* Descriptor allocation failure */
427 return (AE_NO_MEMORY
);
430 status
= acpi_aml_get_field_unit_value (stack_desc
, obj_desc
);
431 if (ACPI_FAILURE (status
)) {
432 acpi_cm_remove_reference (obj_desc
);
436 *stack_ptr
= (void *) obj_desc
;
440 /* TBD: [Future] - may need to handle Index_field, and Def_field someday */
446 } /* switch (Stack_desc->Common.Type) */