blob: 795ec8c7363c90d0a9bec63b85c8e4055d88d3e6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001
2/******************************************************************************
3 *
4 * Module Name: exresolv - AML Interpreter object resolution
5 *
6 *****************************************************************************/
7
8/*
Bob Moore6c9deb72007-02-02 19:48:24 +03009 * Copyright (C) 2000 - 2007, R. Byron Moore
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <acpi/acpi.h>
46#include <acpi/amlcode.h>
47#include <acpi/acdispat.h>
48#include <acpi/acinterp.h>
49#include <acpi/acnamesp.h>
50#include <acpi/acparser.h>
51
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#define _COMPONENT ACPI_EXECUTER
Len Brown4be44fc2005-08-05 00:44:28 -040053ACPI_MODULE_NAME("exresolv")
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Robert Moore44f6c012005-04-18 22:49:35 -040055/* Local prototypes */
Robert Moore44f6c012005-04-18 22:49:35 -040056static acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -040057acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
58 struct acpi_walk_state *walk_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60/*******************************************************************************
61 *
62 * FUNCTION: acpi_ex_resolve_to_value
63 *
64 * PARAMETERS: **stack_ptr - Points to entry on obj_stack, which can
65 * be either an (union acpi_operand_object *)
66 * or an acpi_handle.
67 * walk_state - Current method state
68 *
69 * RETURN: Status
70 *
71 * DESCRIPTION: Convert Reference objects to values
72 *
73 ******************************************************************************/
74
75acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -040076acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
77 struct acpi_walk_state *walk_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -070078{
Len Brown4be44fc2005-08-05 00:44:28 -040079 acpi_status status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
Bob Mooreb229cf92006-04-21 17:15:00 -040081 ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
83 if (!stack_ptr || !*stack_ptr) {
Bob Mooreb8e4d892006-01-27 16:43:00 -050084 ACPI_ERROR((AE_INFO, "Internal - null pointer"));
Len Brown4be44fc2005-08-05 00:44:28 -040085 return_ACPI_STATUS(AE_AML_NO_OPERAND);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 }
87
88 /*
89 * The entity pointed to by the stack_ptr can be either
90 * 1) A valid union acpi_operand_object, or
91 * 2) A struct acpi_namespace_node (named_obj)
92 */
Len Brown4be44fc2005-08-05 00:44:28 -040093 if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
94 status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state);
95 if (ACPI_FAILURE(status)) {
96 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 }
Robert Moore44f6c012005-04-18 22:49:35 -040098
99 if (!*stack_ptr) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500100 ACPI_ERROR((AE_INFO, "Internal - null pointer"));
Len Brown4be44fc2005-08-05 00:44:28 -0400101 return_ACPI_STATUS(AE_AML_NO_OPERAND);
Robert Moore44f6c012005-04-18 22:49:35 -0400102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 }
104
105 /*
106 * Object on the stack may have changed if acpi_ex_resolve_object_to_value()
107 * was called (i.e., we can't use an _else_ here.)
108 */
Len Brown4be44fc2005-08-05 00:44:28 -0400109 if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
110 status =
111 acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
112 (struct acpi_namespace_node,
113 stack_ptr), walk_state);
114 if (ACPI_FAILURE(status)) {
115 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 }
117 }
118
Len Brown4be44fc2005-08-05 00:44:28 -0400119 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
120 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121}
122
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123/*******************************************************************************
124 *
125 * FUNCTION: acpi_ex_resolve_object_to_value
126 *
Robert Moore44f6c012005-04-18 22:49:35 -0400127 * PARAMETERS: stack_ptr - Pointer to an internal object
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 * walk_state - Current method state
129 *
130 * RETURN: Status
131 *
Robert Moore44f6c012005-04-18 22:49:35 -0400132 * DESCRIPTION: Retrieve the value from an internal object. The Reference type
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 * uses the associated AML opcode to determine the value.
134 *
135 ******************************************************************************/
136
Robert Moore44f6c012005-04-18 22:49:35 -0400137static acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400138acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
139 struct acpi_walk_state *walk_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140{
Len Brown4be44fc2005-08-05 00:44:28 -0400141 acpi_status status = AE_OK;
142 union acpi_operand_object *stack_desc;
Fiodor Suietov65e4b9b2007-02-02 19:48:21 +0300143 union acpi_operand_object *obj_desc = NULL;
Len Brown4be44fc2005-08-05 00:44:28 -0400144 u16 opcode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Bob Mooreb229cf92006-04-21 17:15:00 -0400146 ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
148 stack_desc = *stack_ptr;
149
150 /* This is an union acpi_operand_object */
151
Len Brown4be44fc2005-08-05 00:44:28 -0400152 switch (ACPI_GET_OBJECT_TYPE(stack_desc)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 case ACPI_TYPE_LOCAL_REFERENCE:
154
155 opcode = stack_desc->reference.opcode;
156
157 switch (opcode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 case AML_LOCAL_OP:
159 case AML_ARG_OP:
160
161 /*
162 * Get the local from the method's state info
163 * Note: this increments the local's object reference count
164 */
Len Brown4be44fc2005-08-05 00:44:28 -0400165 status = acpi_ds_method_data_get_value(opcode,
166 stack_desc->
167 reference.offset,
168 walk_state,
169 &obj_desc);
170 if (ACPI_FAILURE(status)) {
171 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 }
173
Len Brown4be44fc2005-08-05 00:44:28 -0400174 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
Bob Mooreb229cf92006-04-21 17:15:00 -0400175 "[Arg/Local %X] ValueObj is %p\n",
Len Brown4be44fc2005-08-05 00:44:28 -0400176 stack_desc->reference.offset,
177 obj_desc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178
179 /*
180 * Now we can delete the original Reference Object and
181 * replace it with the resolved value
182 */
Len Brown4be44fc2005-08-05 00:44:28 -0400183 acpi_ut_remove_reference(stack_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 *stack_ptr = obj_desc;
185 break;
186
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 case AML_INDEX_OP:
188
189 switch (stack_desc->reference.target_type) {
190 case ACPI_TYPE_BUFFER_FIELD:
191
192 /* Just return - leave the Reference on the stack */
193 break;
194
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 case ACPI_TYPE_PACKAGE:
196
Lin Minge5bcc812008-04-10 19:06:41 +0400197 /* If method call - leave the Reference on the stack */
198
199 if (walk_state->opcode == AML_INT_METHODCALL_OP) {
200 break;
201 }
202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 obj_desc = *stack_desc->reference.where;
204 if (obj_desc) {
205 /*
206 * Valid obj descriptor, copy pointer to return value
207 * (i.e., dereference the package index)
208 * Delete the ref object, increment the returned object
209 */
Len Brown4be44fc2005-08-05 00:44:28 -0400210 acpi_ut_remove_reference(stack_desc);
211 acpi_ut_add_reference(obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 *stack_ptr = obj_desc;
Len Brown4be44fc2005-08-05 00:44:28 -0400213 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 /*
215 * A NULL object descriptor means an unitialized element of
216 * the package, can't dereference it
217 */
Bob Mooreb8e4d892006-01-27 16:43:00 -0500218 ACPI_ERROR((AE_INFO,
Lin Minge5bcc812008-04-10 19:06:41 +0400219 "Attempt to dereference an Index to NULL package element Idx=%p",
Bob Mooreb8e4d892006-01-27 16:43:00 -0500220 stack_desc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 status = AE_AML_UNINITIALIZED_ELEMENT;
222 }
223 break;
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 default:
226
227 /* Invalid reference object */
228
Bob Mooreb8e4d892006-01-27 16:43:00 -0500229 ACPI_ERROR((AE_INFO,
Lin Minge5bcc812008-04-10 19:06:41 +0400230 "Unknown TargetType %X in Index/Reference object %p",
Bob Mooreb8e4d892006-01-27 16:43:00 -0500231 stack_desc->reference.target_type,
232 stack_desc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 status = AE_AML_INTERNAL;
234 break;
235 }
236 break;
237
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 case AML_REF_OF_OP:
239 case AML_DEBUG_OP:
240 case AML_LOAD_OP:
241
242 /* Just leave the object as-is */
243
244 break;
245
Len Brown4be44fc2005-08-05 00:44:28 -0400246 case AML_INT_NAMEPATH_OP: /* Reference to a named object */
Robert Moore44f6c012005-04-18 22:49:35 -0400247
Bob Moore4c90ece2006-06-08 16:29:00 -0400248 /* Dereference the name */
Robert Moore44f6c012005-04-18 22:49:35 -0400249
Bob Moore4c90ece2006-06-08 16:29:00 -0400250 if ((stack_desc->reference.node->type ==
251 ACPI_TYPE_DEVICE)
252 || (stack_desc->reference.node->type ==
253 ACPI_TYPE_THERMAL)) {
254
255 /* These node types do not have 'real' subobjects */
256
257 *stack_ptr = (void *)stack_desc->reference.node;
258 } else {
259 /* Get the object pointed to by the namespace node */
260
261 *stack_ptr =
262 (stack_desc->reference.node)->object;
263 acpi_ut_add_reference(*stack_ptr);
264 }
265
Len Brown4be44fc2005-08-05 00:44:28 -0400266 acpi_ut_remove_reference(stack_desc);
Robert Moore44f6c012005-04-18 22:49:35 -0400267 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
269 default:
270
Bob Mooreb8e4d892006-01-27 16:43:00 -0500271 ACPI_ERROR((AE_INFO,
272 "Unknown Reference opcode %X (%s) in %p",
273 opcode, acpi_ps_get_opcode_name(opcode),
274 stack_desc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 status = AE_AML_INTERNAL;
276 break;
277 }
278 break;
279
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 case ACPI_TYPE_BUFFER:
281
Len Brown4be44fc2005-08-05 00:44:28 -0400282 status = acpi_ds_get_buffer_arguments(stack_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 break;
284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 case ACPI_TYPE_PACKAGE:
286
Len Brown4be44fc2005-08-05 00:44:28 -0400287 status = acpi_ds_get_package_arguments(stack_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 break;
289
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 case ACPI_TYPE_BUFFER_FIELD:
291 case ACPI_TYPE_LOCAL_REGION_FIELD:
292 case ACPI_TYPE_LOCAL_BANK_FIELD:
293 case ACPI_TYPE_LOCAL_INDEX_FIELD:
294
Len Brown4be44fc2005-08-05 00:44:28 -0400295 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
Bob Mooreb229cf92006-04-21 17:15:00 -0400296 "FieldRead SourceDesc=%p Type=%X\n",
Len Brown4be44fc2005-08-05 00:44:28 -0400297 stack_desc,
298 ACPI_GET_OBJECT_TYPE(stack_desc)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
Len Brown4be44fc2005-08-05 00:44:28 -0400300 status =
301 acpi_ex_read_data_from_field(walk_state, stack_desc,
302 &obj_desc);
Fiodor Suietov65e4b9b2007-02-02 19:48:21 +0300303
304 /* Remove a reference to the original operand, then override */
305
306 acpi_ut_remove_reference(*stack_ptr);
Len Brown4be44fc2005-08-05 00:44:28 -0400307 *stack_ptr = (void *)obj_desc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 break;
309
310 default:
311 break;
312 }
313
Len Brown4be44fc2005-08-05 00:44:28 -0400314 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315}
316
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317/*******************************************************************************
318 *
319 * FUNCTION: acpi_ex_resolve_multiple
320 *
321 * PARAMETERS: walk_state - Current state (contains AML opcode)
322 * Operand - Starting point for resolution
323 * return_type - Where the object type is returned
324 * return_desc - Where the resolved object is returned
325 *
326 * RETURN: Status
327 *
328 * DESCRIPTION: Return the base object and type. Traverse a reference list if
329 * necessary to get to the base object.
330 *
331 ******************************************************************************/
332
333acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400334acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
335 union acpi_operand_object *operand,
336 acpi_object_type * return_type,
337 union acpi_operand_object **return_desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338{
Len Brown4be44fc2005-08-05 00:44:28 -0400339 union acpi_operand_object *obj_desc = (void *)operand;
340 struct acpi_namespace_node *node;
341 acpi_object_type type;
342 acpi_status status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
Bob Mooreb229cf92006-04-21 17:15:00 -0400344 ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
Robert Moore44f6c012005-04-18 22:49:35 -0400346 /* Operand can be either a namespace node or an operand descriptor */
347
Len Brown4be44fc2005-08-05 00:44:28 -0400348 switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 case ACPI_DESC_TYPE_OPERAND:
350 type = obj_desc->common.type;
351 break;
352
353 case ACPI_DESC_TYPE_NAMED:
Len Brown4be44fc2005-08-05 00:44:28 -0400354 type = ((struct acpi_namespace_node *)obj_desc)->type;
355 obj_desc =
356 acpi_ns_get_attached_object((struct acpi_namespace_node *)
357 obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358
359 /* If we had an Alias node, use the attached object for type info */
360
361 if (type == ACPI_TYPE_LOCAL_ALIAS) {
Len Brown4be44fc2005-08-05 00:44:28 -0400362 type = ((struct acpi_namespace_node *)obj_desc)->type;
363 obj_desc =
364 acpi_ns_get_attached_object((struct
365 acpi_namespace_node *)
366 obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 }
368 break;
369
370 default:
Len Brown4be44fc2005-08-05 00:44:28 -0400371 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 }
373
Robert Moore44f6c012005-04-18 22:49:35 -0400374 /* If type is anything other than a reference, we are done */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 if (type != ACPI_TYPE_LOCAL_REFERENCE) {
377 goto exit;
378 }
379
380 /*
381 * For reference objects created via the ref_of or Index operators,
382 * we need to get to the base object (as per the ACPI specification
383 * of the object_type and size_of operators). This means traversing
384 * the list of possibly many nested references.
385 */
Len Brown4be44fc2005-08-05 00:44:28 -0400386 while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 switch (obj_desc->reference.opcode) {
388 case AML_REF_OF_OP:
Bob Moore52fc0b02006-10-02 00:00:00 -0400389 case AML_INT_NAMEPATH_OP:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
391 /* Dereference the reference pointer */
392
Bob Moore52fc0b02006-10-02 00:00:00 -0400393 if (obj_desc->reference.opcode == AML_REF_OF_OP) {
394 node = obj_desc->reference.object;
395 } else { /* AML_INT_NAMEPATH_OP */
396
397 node = obj_desc->reference.node;
398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
400 /* All "References" point to a NS node */
401
Len Brown4be44fc2005-08-05 00:44:28 -0400402 if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
403 ACPI_DESC_TYPE_NAMED) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500404 ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]",
405 node,
406 acpi_ut_get_descriptor_name(node)));
Len Brown4be44fc2005-08-05 00:44:28 -0400407 return_ACPI_STATUS(AE_AML_INTERNAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 }
409
410 /* Get the attached object */
411
Len Brown4be44fc2005-08-05 00:44:28 -0400412 obj_desc = acpi_ns_get_attached_object(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 if (!obj_desc) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400414
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 /* No object, use the NS node type */
416
Len Brown4be44fc2005-08-05 00:44:28 -0400417 type = acpi_ns_get_type(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 goto exit;
419 }
420
421 /* Check for circular references */
422
423 if (obj_desc == operand) {
Len Brown4be44fc2005-08-05 00:44:28 -0400424 return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 }
426 break;
427
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 case AML_INDEX_OP:
429
430 /* Get the type of this reference (index into another object) */
431
432 type = obj_desc->reference.target_type;
433 if (type != ACPI_TYPE_PACKAGE) {
434 goto exit;
435 }
436
437 /*
438 * The main object is a package, we want to get the type
439 * of the individual package element that is referenced by
440 * the index.
441 *
442 * This could of course in turn be another reference object.
443 */
444 obj_desc = *(obj_desc->reference.where);
445 if (!obj_desc) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400446
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 /* NULL package elements are allowed */
448
Len Brown4be44fc2005-08-05 00:44:28 -0400449 type = 0; /* Uninitialized */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 goto exit;
451 }
452 break;
453
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 case AML_LOCAL_OP:
455 case AML_ARG_OP:
456
457 if (return_desc) {
Len Brown4be44fc2005-08-05 00:44:28 -0400458 status =
459 acpi_ds_method_data_get_value(obj_desc->
460 reference.
461 opcode,
462 obj_desc->
463 reference.
464 offset,
465 walk_state,
466 &obj_desc);
467 if (ACPI_FAILURE(status)) {
468 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 }
Len Brown4be44fc2005-08-05 00:44:28 -0400470 acpi_ut_remove_reference(obj_desc);
471 } else {
472 status =
473 acpi_ds_method_data_get_node(obj_desc->
474 reference.
475 opcode,
476 obj_desc->
477 reference.
478 offset,
479 walk_state,
480 &node);
481 if (ACPI_FAILURE(status)) {
482 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 }
484
Len Brown4be44fc2005-08-05 00:44:28 -0400485 obj_desc = acpi_ns_get_attached_object(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 if (!obj_desc) {
487 type = ACPI_TYPE_ANY;
488 goto exit;
489 }
490 }
491 break;
492
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 case AML_DEBUG_OP:
494
Bob Mooreb229cf92006-04-21 17:15:00 -0400495 /* The Debug Object is of type "DebugObject" */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
497 type = ACPI_TYPE_DEBUG_OBJECT;
498 goto exit;
499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 default:
501
Bob Mooreb8e4d892006-01-27 16:43:00 -0500502 ACPI_ERROR((AE_INFO,
503 "Unknown Reference subtype %X",
504 obj_desc->reference.opcode));
Len Brown4be44fc2005-08-05 00:44:28 -0400505 return_ACPI_STATUS(AE_AML_INTERNAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 }
507 }
508
509 /*
510 * Now we are guaranteed to have an object that has not been created
511 * via the ref_of or Index operators.
512 */
Len Brown4be44fc2005-08-05 00:44:28 -0400513 type = ACPI_GET_OBJECT_TYPE(obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
Len Brown4be44fc2005-08-05 00:44:28 -0400515 exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 /* Convert internal types to external types */
517
518 switch (type) {
519 case ACPI_TYPE_LOCAL_REGION_FIELD:
520 case ACPI_TYPE_LOCAL_BANK_FIELD:
521 case ACPI_TYPE_LOCAL_INDEX_FIELD:
522
523 type = ACPI_TYPE_FIELD_UNIT;
524 break;
525
526 case ACPI_TYPE_LOCAL_SCOPE:
527
528 /* Per ACPI Specification, Scope is untyped */
529
530 type = ACPI_TYPE_ANY;
531 break;
532
533 default:
534 /* No change to Type required */
535 break;
536 }
537
538 *return_type = type;
539 if (return_desc) {
540 *return_desc = obj_desc;
541 }
Len Brown4be44fc2005-08-05 00:44:28 -0400542 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543}