exresolv.c revision 1.1.1.3 1 /******************************************************************************
2 *
3 * Module Name: exresolv - AML Interpreter object resolution
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #define __EXRESOLV_C__
45
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "amlcode.h"
49 #include "acdispat.h"
50 #include "acinterp.h"
51 #include "acnamesp.h"
52
53
54 #define _COMPONENT ACPI_EXECUTER
55 ACPI_MODULE_NAME ("exresolv")
56
57 /* Local prototypes */
58
59 static ACPI_STATUS
60 AcpiExResolveObjectToValue (
61 ACPI_OPERAND_OBJECT **StackPtr,
62 ACPI_WALK_STATE *WalkState);
63
64
65 /*******************************************************************************
66 *
67 * FUNCTION: AcpiExResolveToValue
68 *
69 * PARAMETERS: **StackPtr - Points to entry on ObjStack, which can
70 * be either an (ACPI_OPERAND_OBJECT *)
71 * or an ACPI_HANDLE.
72 * WalkState - Current method state
73 *
74 * RETURN: Status
75 *
76 * DESCRIPTION: Convert Reference objects to values
77 *
78 ******************************************************************************/
79
80 ACPI_STATUS
81 AcpiExResolveToValue (
82 ACPI_OPERAND_OBJECT **StackPtr,
83 ACPI_WALK_STATE *WalkState)
84 {
85 ACPI_STATUS Status;
86
87
88 ACPI_FUNCTION_TRACE_PTR (ExResolveToValue, StackPtr);
89
90
91 if (!StackPtr || !*StackPtr)
92 {
93 ACPI_ERROR ((AE_INFO, "Internal - null pointer"));
94 return_ACPI_STATUS (AE_AML_NO_OPERAND);
95 }
96
97 /*
98 * The entity pointed to by the StackPtr can be either
99 * 1) A valid ACPI_OPERAND_OBJECT, or
100 * 2) A ACPI_NAMESPACE_NODE (NamedObj)
101 */
102 if (ACPI_GET_DESCRIPTOR_TYPE (*StackPtr) == ACPI_DESC_TYPE_OPERAND)
103 {
104 Status = AcpiExResolveObjectToValue (StackPtr, WalkState);
105 if (ACPI_FAILURE (Status))
106 {
107 return_ACPI_STATUS (Status);
108 }
109
110 if (!*StackPtr)
111 {
112 ACPI_ERROR ((AE_INFO, "Internal - null pointer"));
113 return_ACPI_STATUS (AE_AML_NO_OPERAND);
114 }
115 }
116
117 /*
118 * Object on the stack may have changed if AcpiExResolveObjectToValue()
119 * was called (i.e., we can't use an _else_ here.)
120 */
121 if (ACPI_GET_DESCRIPTOR_TYPE (*StackPtr) == ACPI_DESC_TYPE_NAMED)
122 {
123 Status = AcpiExResolveNodeToValue (
124 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, StackPtr),
125 WalkState);
126 if (ACPI_FAILURE (Status))
127 {
128 return_ACPI_STATUS (Status);
129 }
130 }
131
132 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Resolved object %p\n", *StackPtr));
133 return_ACPI_STATUS (AE_OK);
134 }
135
136
137 /*******************************************************************************
138 *
139 * FUNCTION: AcpiExResolveObjectToValue
140 *
141 * PARAMETERS: StackPtr - Pointer to an internal object
142 * WalkState - Current method state
143 *
144 * RETURN: Status
145 *
146 * DESCRIPTION: Retrieve the value from an internal object. The Reference type
147 * uses the associated AML opcode to determine the value.
148 *
149 ******************************************************************************/
150
151 static ACPI_STATUS
152 AcpiExResolveObjectToValue (
153 ACPI_OPERAND_OBJECT **StackPtr,
154 ACPI_WALK_STATE *WalkState)
155 {
156 ACPI_STATUS Status = AE_OK;
157 ACPI_OPERAND_OBJECT *StackDesc;
158 ACPI_OPERAND_OBJECT *ObjDesc = NULL;
159 UINT8 RefType;
160
161
162 ACPI_FUNCTION_TRACE (ExResolveObjectToValue);
163
164
165 StackDesc = *StackPtr;
166
167 /* This is an object of type ACPI_OPERAND_OBJECT */
168
169 switch (StackDesc->Common.Type)
170 {
171 case ACPI_TYPE_LOCAL_REFERENCE:
172
173 RefType = StackDesc->Reference.Class;
174
175 switch (RefType)
176 {
177 case ACPI_REFCLASS_LOCAL:
178 case ACPI_REFCLASS_ARG:
179 /*
180 * Get the local from the method's state info
181 * Note: this increments the local's object reference count
182 */
183 Status = AcpiDsMethodDataGetValue (RefType,
184 StackDesc->Reference.Value, WalkState, &ObjDesc);
185 if (ACPI_FAILURE (Status))
186 {
187 return_ACPI_STATUS (Status);
188 }
189
190 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] ValueObj is %p\n",
191 StackDesc->Reference.Value, ObjDesc));
192
193 /*
194 * Now we can delete the original Reference Object and
195 * replace it with the resolved value
196 */
197 AcpiUtRemoveReference (StackDesc);
198 *StackPtr = ObjDesc;
199 break;
200
201 case ACPI_REFCLASS_INDEX:
202
203 switch (StackDesc->Reference.TargetType)
204 {
205 case ACPI_TYPE_BUFFER_FIELD:
206
207 /* Just return - do not dereference */
208 break;
209
210 case ACPI_TYPE_PACKAGE:
211
212 /* If method call or CopyObject - do not dereference */
213
214 if ((WalkState->Opcode == AML_INT_METHODCALL_OP) ||
215 (WalkState->Opcode == AML_COPY_OP))
216 {
217 break;
218 }
219
220 /* Otherwise, dereference the PackageIndex to a package element */
221
222 ObjDesc = *StackDesc->Reference.Where;
223 if (ObjDesc)
224 {
225 /*
226 * Valid object descriptor, copy pointer to return value
227 * (i.e., dereference the package index)
228 * Delete the ref object, increment the returned object
229 */
230 AcpiUtRemoveReference (StackDesc);
231 AcpiUtAddReference (ObjDesc);
232 *StackPtr = ObjDesc;
233 }
234 else
235 {
236 /*
237 * A NULL object descriptor means an uninitialized element of
238 * the package, can't dereference it
239 */
240 ACPI_ERROR ((AE_INFO,
241 "Attempt to dereference an Index to NULL package element Idx=%p",
242 StackDesc));
243 Status = AE_AML_UNINITIALIZED_ELEMENT;
244 }
245 break;
246
247 default:
248
249 /* Invalid reference object */
250
251 ACPI_ERROR ((AE_INFO,
252 "Unknown TargetType 0x%X in Index/Reference object %p",
253 StackDesc->Reference.TargetType, StackDesc));
254 Status = AE_AML_INTERNAL;
255 break;
256 }
257 break;
258
259 case ACPI_REFCLASS_REFOF:
260 case ACPI_REFCLASS_DEBUG:
261 case ACPI_REFCLASS_TABLE:
262
263 /* Just leave the object as-is, do not dereference */
264
265 break;
266
267 case ACPI_REFCLASS_NAME: /* Reference to a named object */
268
269 /* Dereference the name */
270
271 if ((StackDesc->Reference.Node->Type == ACPI_TYPE_DEVICE) ||
272 (StackDesc->Reference.Node->Type == ACPI_TYPE_THERMAL))
273 {
274 /* These node types do not have 'real' subobjects */
275
276 *StackPtr = (void *) StackDesc->Reference.Node;
277 }
278 else
279 {
280 /* Get the object pointed to by the namespace node */
281
282 *StackPtr = (StackDesc->Reference.Node)->Object;
283 AcpiUtAddReference (*StackPtr);
284 }
285
286 AcpiUtRemoveReference (StackDesc);
287 break;
288
289 default:
290
291 ACPI_ERROR ((AE_INFO,
292 "Unknown Reference type 0x%X in %p", RefType, StackDesc));
293 Status = AE_AML_INTERNAL;
294 break;
295 }
296 break;
297
298 case ACPI_TYPE_BUFFER:
299
300 Status = AcpiDsGetBufferArguments (StackDesc);
301 break;
302
303 case ACPI_TYPE_PACKAGE:
304
305 Status = AcpiDsGetPackageArguments (StackDesc);
306 break;
307
308 case ACPI_TYPE_BUFFER_FIELD:
309 case ACPI_TYPE_LOCAL_REGION_FIELD:
310 case ACPI_TYPE_LOCAL_BANK_FIELD:
311 case ACPI_TYPE_LOCAL_INDEX_FIELD:
312
313 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "FieldRead SourceDesc=%p Type=%X\n",
314 StackDesc, StackDesc->Common.Type));
315
316 Status = AcpiExReadDataFromField (WalkState, StackDesc, &ObjDesc);
317
318 /* Remove a reference to the original operand, then override */
319
320 AcpiUtRemoveReference (*StackPtr);
321 *StackPtr = (void *) ObjDesc;
322 break;
323
324 default:
325
326 break;
327 }
328
329 return_ACPI_STATUS (Status);
330 }
331
332
333 /*******************************************************************************
334 *
335 * FUNCTION: AcpiExResolveMultiple
336 *
337 * PARAMETERS: WalkState - Current state (contains AML opcode)
338 * Operand - Starting point for resolution
339 * ReturnType - Where the object type is returned
340 * ReturnDesc - Where the resolved object is returned
341 *
342 * RETURN: Status
343 *
344 * DESCRIPTION: Return the base object and type. Traverse a reference list if
345 * necessary to get to the base object.
346 *
347 ******************************************************************************/
348
349 ACPI_STATUS
350 AcpiExResolveMultiple (
351 ACPI_WALK_STATE *WalkState,
352 ACPI_OPERAND_OBJECT *Operand,
353 ACPI_OBJECT_TYPE *ReturnType,
354 ACPI_OPERAND_OBJECT **ReturnDesc)
355 {
356 ACPI_OPERAND_OBJECT *ObjDesc = (void *) Operand;
357 ACPI_NAMESPACE_NODE *Node;
358 ACPI_OBJECT_TYPE Type;
359 ACPI_STATUS Status;
360
361
362 ACPI_FUNCTION_TRACE (AcpiExResolveMultiple);
363
364
365 /* Operand can be either a namespace node or an operand descriptor */
366
367 switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
368 {
369 case ACPI_DESC_TYPE_OPERAND:
370
371 Type = ObjDesc->Common.Type;
372 break;
373
374 case ACPI_DESC_TYPE_NAMED:
375
376 Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type;
377 ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc);
378
379 /* If we had an Alias node, use the attached object for type info */
380
381 if (Type == ACPI_TYPE_LOCAL_ALIAS)
382 {
383 Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type;
384 ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc);
385 }
386 break;
387
388 default:
389 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
390 }
391
392 /* If type is anything other than a reference, we are done */
393
394 if (Type != ACPI_TYPE_LOCAL_REFERENCE)
395 {
396 goto Exit;
397 }
398
399 /*
400 * For reference objects created via the RefOf, Index, or Load/LoadTable
401 * operators, we need to get to the base object (as per the ACPI
402 * specification of the ObjectType and SizeOf operators). This means
403 * traversing the list of possibly many nested references.
404 */
405 while (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)
406 {
407 switch (ObjDesc->Reference.Class)
408 {
409 case ACPI_REFCLASS_REFOF:
410 case ACPI_REFCLASS_NAME:
411
412 /* Dereference the reference pointer */
413
414 if (ObjDesc->Reference.Class == ACPI_REFCLASS_REFOF)
415 {
416 Node = ObjDesc->Reference.Object;
417 }
418 else /* AML_INT_NAMEPATH_OP */
419 {
420 Node = ObjDesc->Reference.Node;
421 }
422
423 /* All "References" point to a NS node */
424
425 if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
426 {
427 ACPI_ERROR ((AE_INFO,
428 "Not a namespace node %p [%s]",
429 Node, AcpiUtGetDescriptorName (Node)));
430 return_ACPI_STATUS (AE_AML_INTERNAL);
431 }
432
433 /* Get the attached object */
434
435 ObjDesc = AcpiNsGetAttachedObject (Node);
436 if (!ObjDesc)
437 {
438 /* No object, use the NS node type */
439
440 Type = AcpiNsGetType (Node);
441 goto Exit;
442 }
443
444 /* Check for circular references */
445
446 if (ObjDesc == Operand)
447 {
448 return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE);
449 }
450 break;
451
452 case ACPI_REFCLASS_INDEX:
453
454 /* Get the type of this reference (index into another object) */
455
456 Type = ObjDesc->Reference.TargetType;
457 if (Type != ACPI_TYPE_PACKAGE)
458 {
459 goto Exit;
460 }
461
462 /*
463 * The main object is a package, we want to get the type
464 * of the individual package element that is referenced by
465 * the index.
466 *
467 * This could of course in turn be another reference object.
468 */
469 ObjDesc = *(ObjDesc->Reference.Where);
470 if (!ObjDesc)
471 {
472 /* NULL package elements are allowed */
473
474 Type = 0; /* Uninitialized */
475 goto Exit;
476 }
477 break;
478
479 case ACPI_REFCLASS_TABLE:
480
481 Type = ACPI_TYPE_DDB_HANDLE;
482 goto Exit;
483
484 case ACPI_REFCLASS_LOCAL:
485 case ACPI_REFCLASS_ARG:
486
487 if (ReturnDesc)
488 {
489 Status = AcpiDsMethodDataGetValue (ObjDesc->Reference.Class,
490 ObjDesc->Reference.Value, WalkState, &ObjDesc);
491 if (ACPI_FAILURE (Status))
492 {
493 return_ACPI_STATUS (Status);
494 }
495 AcpiUtRemoveReference (ObjDesc);
496 }
497 else
498 {
499 Status = AcpiDsMethodDataGetNode (ObjDesc->Reference.Class,
500 ObjDesc->Reference.Value, WalkState, &Node);
501 if (ACPI_FAILURE (Status))
502 {
503 return_ACPI_STATUS (Status);
504 }
505
506 ObjDesc = AcpiNsGetAttachedObject (Node);
507 if (!ObjDesc)
508 {
509 Type = ACPI_TYPE_ANY;
510 goto Exit;
511 }
512 }
513 break;
514
515 case ACPI_REFCLASS_DEBUG:
516
517 /* The Debug Object is of type "DebugObject" */
518
519 Type = ACPI_TYPE_DEBUG_OBJECT;
520 goto Exit;
521
522 default:
523
524 ACPI_ERROR ((AE_INFO,
525 "Unknown Reference Class 0x%2.2X", ObjDesc->Reference.Class));
526 return_ACPI_STATUS (AE_AML_INTERNAL);
527 }
528 }
529
530 /*
531 * Now we are guaranteed to have an object that has not been created
532 * via the RefOf or Index operators.
533 */
534 Type = ObjDesc->Common.Type;
535
536
537 Exit:
538 /* Convert internal types to external types */
539
540 switch (Type)
541 {
542 case ACPI_TYPE_LOCAL_REGION_FIELD:
543 case ACPI_TYPE_LOCAL_BANK_FIELD:
544 case ACPI_TYPE_LOCAL_INDEX_FIELD:
545
546 Type = ACPI_TYPE_FIELD_UNIT;
547 break;
548
549 case ACPI_TYPE_LOCAL_SCOPE:
550
551 /* Per ACPI Specification, Scope is untyped */
552
553 Type = ACPI_TYPE_ANY;
554 break;
555
556 default:
557
558 /* No change to Type required */
559
560 break;
561 }
562
563 *ReturnType = Type;
564 if (ReturnDesc)
565 {
566 *ReturnDesc = ObjDesc;
567 }
568 return_ACPI_STATUS (AE_OK);
569 }
570