Home | History | Annotate | Line # | Download | only in dispatcher
dspkginit.c revision 1.5.6.1
      1 /******************************************************************************
      2  *
      3  * Module Name: dspkginit - Completion of deferred package initialization
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2021, 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 = __UNCONST("");
    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