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