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