1 /******************************************************************************
2  *
3  * Module Name: dspkginit - Completion of deferred package initialization
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 #include "acpi.h"
45 #include "accommon.h"
46 #include "acnamesp.h"
47 #include "amlcode.h"
48 #include "acdispat.h"
49 #include "acinterp.h"
50 #include "acparser.h"
51 
52 
53 #define _COMPONENT          ACPI_NAMESPACE
54         ACPI_MODULE_NAME    ("dspkginit")
55 
56 
57 /* Local prototypes */
58 
59 static void
60 AcpiDsResolvePackageElement (
61     ACPI_OPERAND_OBJECT     **Element);
62 
63 
64 /*******************************************************************************
65  *
66  * FUNCTION:    AcpiDsBuildInternalPackageObj
67  *
68  * PARAMETERS:  WalkState       - Current walk state
69  *              Op              - Parser object to be translated
70  *              ElementCount    - Number of elements in the package - this is
71  *                                the NumElements argument to Package()
72  *              ObjDescPtr      - Where the ACPI internal object is returned
73  *
74  * RETURN:      Status
75  *
76  * DESCRIPTION: Translate a parser Op package object to the equivalent
77  *              namespace object
78  *
79  * NOTE: The number of elements in the package will be always be the NumElements
80  * count, regardless of the number of elements in the package list. If
81  * NumElements is smaller, only that many package list elements are used.
82  * if NumElements is larger, the Package object is padded out with
83  * objects of type Uninitialized (as per ACPI spec.)
84  *
85  * Even though the ASL compilers do not allow NumElements to be smaller
86  * than the Package list length (for the fixed length package opcode), some
87  * BIOS code modifies the AML on the fly to adjust the NumElements, and
88  * this code compensates for that. This also provides compatibility with
89  * other AML interpreters.
90  *
91  ******************************************************************************/
92 
93 ACPI_STATUS
94 AcpiDsBuildInternalPackageObj (
95     ACPI_WALK_STATE         *WalkState,
96     ACPI_PARSE_OBJECT       *Op,
97     UINT32                  ElementCount,
98     ACPI_OPERAND_OBJECT     **ObjDescPtr)
99 {
100     ACPI_PARSE_OBJECT       *Arg;
101     ACPI_PARSE_OBJECT       *Parent;
102     ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
103     ACPI_STATUS             Status = AE_OK;
104     BOOLEAN                 ModuleLevelCode = FALSE;
105     UINT16                  ReferenceCount;
106     UINT32                  Index;
107     UINT32                  i;
108 
109 
110     ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj);
111 
112 
113     /* Check if we are executing module level code */
114 
115     if (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)
116     {
117         ModuleLevelCode = TRUE;
118     }
119 
120     /* Find the parent of a possibly nested package */
121 
122     Parent = Op->Common.Parent;
123     while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
124            (Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
125     {
126         Parent = Parent->Common.Parent;
127     }
128 
129     /*
130      * If we are evaluating a Named package object of the form:
131      *      Name (xxxx, Package)
132      * the package object already exists, otherwise it must be created.
133      */
134     ObjDesc = *ObjDescPtr;
135     if (!ObjDesc)
136     {
137         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE);
138         *ObjDescPtr = ObjDesc;
139         if (!ObjDesc)
140         {
141             return_ACPI_STATUS (AE_NO_MEMORY);
142         }
143 
144         ObjDesc->Package.Node = Parent->Common.Node;
145     }
146 
147     if (ObjDesc->Package.Flags & AOPOBJ_DATA_VALID) /* Just in case */
148     {
149         return_ACPI_STATUS (AE_OK);
150     }
151 
152     /*
153      * Allocate the element array (array of pointers to the individual
154      * objects) if necessary. the count is based on the NumElements
155      * parameter. Add an extra pointer slot so that the list is always
156      * null terminated.
157      */
158     if (!ObjDesc->Package.Elements)
159     {
160         ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED (
161             ((ACPI_SIZE) ElementCount + 1) * sizeof (void *));
162 
163         if (!ObjDesc->Package.Elements)
164         {
165             AcpiUtDeleteObjectDesc (ObjDesc);
166             return_ACPI_STATUS (AE_NO_MEMORY);
167         }
168 
169         ObjDesc->Package.Count = ElementCount;
170     }
171 
172     /* First arg is element count. Second arg begins the initializer list */
173 
174     Arg = Op->Common.Value.Arg;
175     Arg = Arg->Common.Next;
176 
177     /*
178      * If we are executing module-level code, we will defer the
179      * full resolution of the package elements in order to support
180      * forward references from the elements. This provides
181      * compatibility with other ACPI implementations.
182      */
183     if (ModuleLevelCode)
184     {
185         ObjDesc->Package.AmlStart = WalkState->Aml;
186         ObjDesc->Package.AmlLength = 0;
187 
188         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
189             "%s: Deferring resolution of Package elements\n",
190             ACPI_GET_FUNCTION_NAME));
191     }
192 
193     /*
194      * Initialize the elements of the package, up to the NumElements count.
195      * Package is automatically padded with uninitialized (NULL) elements
196      * if NumElements is greater than the package list length. Likewise,
197      * Package is truncated if NumElements is less than the list length.
198      */
199     for (i = 0; Arg && (i < ElementCount); i++)
200     {
201         if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP)
202         {
203             if (!Arg->Common.Node)
204             {
205                 /*
206                  * This is the case where an expression has returned a value.
207                  * The use of expressions (TermArgs) within individual
208                  * package elements is not supported by the AML interpreter,
209                  * even though the ASL grammar supports it. Example:
210                  *
211                  *      Name (INT1, 0x1234)
212                  *
213                  *      Name (PKG3, Package () {
214                  *          Add (INT1, 0xAAAA0000)
215                  *      })
216                  *
217                  *  1) No known AML interpreter supports this type of construct
218                  *  2) This fixes a fault if the construct is encountered
219                  */
220                 ACPI_EXCEPTION ((AE_INFO, AE_SUPPORT,
221                     "Expressions within package elements are not supported"));
222 
223                 /* Cleanup the return object, it is not needed */
224 
225                 AcpiUtRemoveReference (WalkState->Results->Results.ObjDesc[0]);
226                 return_ACPI_STATUS (AE_SUPPORT);
227             }
228 
229             if (Arg->Common.Node->Type == ACPI_TYPE_METHOD)
230             {
231                 /*
232                  * A method reference "looks" to the parser to be a method
233                  * invocation, so we special case it here
234                  */
235                 Arg->Common.AmlOpcode = AML_INT_NAMEPATH_OP;
236                 Status = AcpiDsBuildInternalObject (
237                     WalkState, Arg, &ObjDesc->Package.Elements[i]);
238             }
239             else
240             {
241                 /* This package element is already built, just get it */
242 
243                 ObjDesc->Package.Elements[i] =
244                     ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node);
245             }
246         }
247         else
248         {
249             Status = AcpiDsBuildInternalObject (
250                 WalkState, Arg, &ObjDesc->Package.Elements[i]);
251             if (Status == AE_NOT_FOUND)
252             {
253                 ACPI_ERROR ((AE_INFO, "%-48s", "****DS namepath not found"));
254             }
255 
256             if (!ModuleLevelCode)
257             {
258                 /*
259                  * Initialize this package element. This function handles the
260                  * resolution of named references within the package.
261                  * Forward references from module-level code are deferred
262                  * until all ACPI tables are loaded.
263                  */
264                 AcpiDsInitPackageElement (0, ObjDesc->Package.Elements[i],
265                     NULL, &ObjDesc->Package.Elements[i]);
266             }
267         }
268 
269         if (*ObjDescPtr)
270         {
271             /* Existing package, get existing reference count */
272 
273             ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount;
274             if (ReferenceCount > 1)
275             {
276                 /* Make new element ref count match original ref count */
277                 /* TBD: Probably need an AcpiUtAddReferences function */
278 
279                 for (Index = 0; Index < ((UINT32) ReferenceCount - 1); Index++)
280                 {
281                     AcpiUtAddReference ((ObjDesc->Package.Elements[i]));
282                 }
283             }
284         }
285 
286         Arg = Arg->Common.Next;
287     }
288 
289     /* Check for match between NumElements and actual length of PackageList */
290 
291     if (Arg)
292     {
293         /*
294          * NumElements was exhausted, but there are remaining elements in
295          * the PackageList. Truncate the package to NumElements.
296          *
297          * Note: technically, this is an error, from ACPI spec: "It is an
298          * error for NumElements to be less than the number of elements in
299          * the PackageList". However, we just print a message and no
300          * exception is returned. This provides compatibility with other
301          * ACPI implementations. Some firmware implementations will alter
302          * the NumElements on the fly, possibly creating this type of
303          * ill-formed package object.
304          */
305         while (Arg)
306         {
307             /*
308              * We must delete any package elements that were created earlier
309              * and are not going to be used because of the package truncation.
310              */
311             if (Arg->Common.Node)
312             {
313                 AcpiUtRemoveReference (
314                     ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node));
315                 Arg->Common.Node = NULL;
316             }
317 
318             /* Find out how many elements there really are */
319 
320             i++;
321             Arg = Arg->Common.Next;
322         }
323 
324         ACPI_INFO ((
325             "Actual Package length (%u) is larger than "
326             "NumElements field (%u), truncated",
327             i, ElementCount));
328     }
329     else if (i < ElementCount)
330     {
331         /*
332          * Arg list (elements) was exhausted, but we did not reach
333          * NumElements count.
334          *
335          * Note: this is not an error, the package is padded out
336          * with NULLs as per the ACPI specification.
337          */
338         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,
339             "%s: Package List length (%u) smaller than NumElements "
340             "count (%u), padded with null elements\n",
341             ACPI_GET_FUNCTION_NAME, i, ElementCount));
342     }
343 
344     /* Module-level packages will be resolved later */
345 
346     if (!ModuleLevelCode)
347     {
348         ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID;
349     }
350 
351     Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);
352     return_ACPI_STATUS (Status);
353 }
354 
355 
356 /*******************************************************************************
357  *
358  * FUNCTION:    AcpiDsInitPackageElement
359  *
360  * PARAMETERS:  ACPI_PKG_CALLBACK
361  *
362  * RETURN:      Status
363  *
364  * DESCRIPTION: Resolve a named reference element within a package object
365  *
366  ******************************************************************************/
367 
368 ACPI_STATUS
369 AcpiDsInitPackageElement (
370     UINT8                   ObjectType,
371     ACPI_OPERAND_OBJECT     *SourceObject,
372     ACPI_GENERIC_STATE      *State,
373     void                    *Context)
374 {
375     ACPI_OPERAND_OBJECT     **ElementPtr;
376 
377 
378     ACPI_FUNCTION_TRACE (DsInitPackageElement);
379 
380 
381     if (!SourceObject)
382     {
383         return_ACPI_STATUS (AE_OK);
384     }
385 
386     /*
387      * The following code is a bit of a hack to workaround a (current)
388      * limitation of the ACPI_PKG_CALLBACK interface. We need a pointer
389      * to the location within the element array because a new object
390      * may be created and stored there.
391      */
392     if (Context)
393     {
394         /* A direct call was made to this function */
395 
396         ElementPtr = (ACPI_OPERAND_OBJECT **) Context;
397     }
398     else
399     {
400         /* Call came from AcpiUtWalkPackageTree */
401 
402         ElementPtr = State->Pkg.ThisTargetObj;
403     }
404 
405     /* We are only interested in reference objects/elements */
406 
407     if (SourceObject->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)
408     {
409         /* Attempt to resolve the (named) reference to a namespace node */
410 
411         AcpiDsResolvePackageElement (ElementPtr);
412     }
413     else if (SourceObject->Common.Type == ACPI_TYPE_PACKAGE)
414     {
415         SourceObject->Package.Flags |= AOPOBJ_DATA_VALID;
416     }
417 
418     return_ACPI_STATUS (AE_OK);
419 }
420 
421 
422 /*******************************************************************************
423  *
424  * FUNCTION:    AcpiDsResolvePackageElement
425  *
426  * PARAMETERS:  ElementPtr          - Pointer to a reference object
427  *
428  * RETURN:      Possible new element is stored to the indirect ElementPtr
429  *
430  * DESCRIPTION: Resolve a package element that is a reference to a named
431  *              object.
432  *
433  ******************************************************************************/
434 
435 static void
436 AcpiDsResolvePackageElement (
437     ACPI_OPERAND_OBJECT     **ElementPtr)
438 {
439     ACPI_STATUS             Status;
440     ACPI_STATUS             Status2;
441     ACPI_GENERIC_STATE      ScopeInfo;
442     ACPI_OPERAND_OBJECT     *Element = *ElementPtr;
443     ACPI_NAMESPACE_NODE     *ResolvedNode;
444     ACPI_NAMESPACE_NODE     *OriginalNode;
445     char                    *ExternalPath = "";
446     ACPI_OBJECT_TYPE        Type;
447 
448 
449     ACPI_FUNCTION_TRACE (DsResolvePackageElement);
450 
451 
452     /* Check if reference element is already resolved */
453 
454     if (Element->Reference.Resolved)
455     {
456         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
457             "%s: Package element is already resolved\n",
458             ACPI_GET_FUNCTION_NAME));
459 
460         return_VOID;
461     }
462 
463     /* Element must be a reference object of correct type */
464 
465     ScopeInfo.Scope.Node = Element->Reference.Node; /* Prefix node */
466 
467     Status = AcpiNsLookup (&ScopeInfo, (char *) Element->Reference.Aml,
468         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
469         ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
470         NULL, &ResolvedNode);
471     if (ACPI_FAILURE (Status))
472     {
473         if ((Status == AE_NOT_FOUND) && AcpiGbl_IgnorePackageResolutionErrors)
474         {
475             /*
476              * Optionally be silent about the NOT_FOUND case for the referenced
477              * name. Although this is potentially a serious problem,
478              * it can generate a lot of noise/errors on platforms whose
479              * firmware carries around a bunch of unused Package objects.
480              * To disable these errors, set this global to TRUE:
481              *     AcpiGbl_IgnorePackageResolutionErrors
482              *
483              * If the AML actually tries to use such a package, the unresolved
484              * element(s) will be replaced with NULL elements.
485              */
486 
487             /* Referenced name not found, set the element to NULL */
488 
489             AcpiUtRemoveReference (*ElementPtr);
490             *ElementPtr = NULL;
491             return_VOID;
492         }
493 
494         Status2 = AcpiNsExternalizeName (ACPI_UINT32_MAX,
495             (char *) Element->Reference.Aml, NULL, &ExternalPath);
496 
497         ACPI_EXCEPTION ((AE_INFO, Status,
498             "While resolving a named reference package element - %s",
499             ExternalPath));
500         if (ACPI_SUCCESS (Status2))
501         {
502             ACPI_FREE (ExternalPath);
503         }
504 
505         /* Could not resolve name, set the element to NULL */
506 
507         AcpiUtRemoveReference (*ElementPtr);
508         *ElementPtr = NULL;
509         return_VOID;
510     }
511     else if (ResolvedNode->Type == ACPI_TYPE_ANY)
512     {
513         /* Named reference not resolved, return a NULL package element */
514 
515         ACPI_ERROR ((AE_INFO,
516             "Could not resolve named package element [%4.4s] in [%4.4s]",
517             ResolvedNode->Name.Ascii, ScopeInfo.Scope.Node->Name.Ascii));
518         *ElementPtr = NULL;
519         return_VOID;
520     }
521 
522     /*
523      * Special handling for Alias objects. We need ResolvedNode to point
524      * to the Alias target. This effectively "resolves" the alias.
525      */
526     if (ResolvedNode->Type == ACPI_TYPE_LOCAL_ALIAS)
527     {
528         ResolvedNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
529             ResolvedNode->Object);
530     }
531 
532     /* Update the reference object */
533 
534     Element->Reference.Resolved = TRUE;
535     Element->Reference.Node = ResolvedNode;
536     Type = Element->Reference.Node->Type;
537 
538     /*
539      * Attempt to resolve the node to a value before we insert it into
540      * the package. If this is a reference to a common data type,
541      * resolve it immediately. According to the ACPI spec, package
542      * elements can only be "data objects" or method references.
543      * Attempt to resolve to an Integer, Buffer, String or Package.
544      * If cannot, return the named reference (for things like Devices,
545      * Methods, etc.) Buffer Fields and Fields will resolve to simple
546      * objects (int/buf/str/pkg).
547      *
548      * NOTE: References to things like Devices, Methods, Mutexes, etc.
549      * will remain as named references. This behavior is not described
550      * in the ACPI spec, but it appears to be an oversight.
551      */
552     OriginalNode = ResolvedNode;
553     Status = AcpiExResolveNodeToValue (&ResolvedNode, NULL);
554     if (ACPI_FAILURE (Status))
555     {
556         return_VOID;
557     }
558 
559     switch (Type)
560     {
561     /*
562      * These object types are a result of named references, so we will
563      * leave them as reference objects. In other words, these types
564      * have no intrinsic "value".
565      */
566     case ACPI_TYPE_DEVICE:
567     case ACPI_TYPE_THERMAL:
568     case ACPI_TYPE_METHOD:
569         break;
570 
571     case ACPI_TYPE_MUTEX:
572     case ACPI_TYPE_POWER:
573     case ACPI_TYPE_PROCESSOR:
574     case ACPI_TYPE_EVENT:
575     case ACPI_TYPE_REGION:
576 
577         /* AcpiExResolveNodeToValue gave these an extra reference */
578 
579         AcpiUtRemoveReference (OriginalNode->Object);
580         break;
581 
582     default:
583         /*
584          * For all other types - the node was resolved to an actual
585          * operand object with a value, return the object. Remove
586          * a reference on the existing object.
587          */
588         AcpiUtRemoveReference (Element);
589         *ElementPtr = (ACPI_OPERAND_OBJECT *) ResolvedNode;
590         break;
591     }
592 
593     return_VOID;
594 }
595