xref: /netbsd-src/sys/external/bsd/acpica/dist/dispatcher/dspkginit.c (revision 2c7d7e3ca2e4f0b675c6c58e614f6aede66c678e)
189b8eb6cSchristos /******************************************************************************
289b8eb6cSchristos  *
389b8eb6cSchristos  * Module Name: dspkginit - Completion of deferred package initialization
489b8eb6cSchristos  *
589b8eb6cSchristos  *****************************************************************************/
689b8eb6cSchristos 
789b8eb6cSchristos /*
8*2c7d7e3cSchristos  * Copyright (C) 2000 - 2023, Intel Corp.
989b8eb6cSchristos  * All rights reserved.
1089b8eb6cSchristos  *
1189b8eb6cSchristos  * Redistribution and use in source and binary forms, with or without
1289b8eb6cSchristos  * modification, are permitted provided that the following conditions
1389b8eb6cSchristos  * are met:
1489b8eb6cSchristos  * 1. Redistributions of source code must retain the above copyright
1589b8eb6cSchristos  *    notice, this list of conditions, and the following disclaimer,
1689b8eb6cSchristos  *    without modification.
1789b8eb6cSchristos  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1889b8eb6cSchristos  *    substantially similar to the "NO WARRANTY" disclaimer below
1989b8eb6cSchristos  *    ("Disclaimer") and any redistribution must be conditioned upon
2089b8eb6cSchristos  *    including a substantially similar Disclaimer requirement for further
2189b8eb6cSchristos  *    binary redistribution.
2289b8eb6cSchristos  * 3. Neither the names of the above-listed copyright holders nor the names
2389b8eb6cSchristos  *    of any contributors may be used to endorse or promote products derived
2489b8eb6cSchristos  *    from this software without specific prior written permission.
2589b8eb6cSchristos  *
2689b8eb6cSchristos  * Alternatively, this software may be distributed under the terms of the
2789b8eb6cSchristos  * GNU General Public License ("GPL") version 2 as published by the Free
2889b8eb6cSchristos  * Software Foundation.
2989b8eb6cSchristos  *
3089b8eb6cSchristos  * NO WARRANTY
3189b8eb6cSchristos  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3289b8eb6cSchristos  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3398244dcfSchristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3489b8eb6cSchristos  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3589b8eb6cSchristos  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3689b8eb6cSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3789b8eb6cSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3889b8eb6cSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3989b8eb6cSchristos  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4089b8eb6cSchristos  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4189b8eb6cSchristos  * POSSIBILITY OF SUCH DAMAGES.
4289b8eb6cSchristos  */
4389b8eb6cSchristos 
4489b8eb6cSchristos #include "acpi.h"
4589b8eb6cSchristos #include "accommon.h"
4689b8eb6cSchristos #include "acnamesp.h"
4789b8eb6cSchristos #include "amlcode.h"
4889b8eb6cSchristos #include "acdispat.h"
4989b8eb6cSchristos #include "acinterp.h"
50062782b3Schristos #include "acparser.h"
5189b8eb6cSchristos 
5289b8eb6cSchristos 
5389b8eb6cSchristos #define _COMPONENT          ACPI_NAMESPACE
5489b8eb6cSchristos         ACPI_MODULE_NAME    ("dspkginit")
5589b8eb6cSchristos 
5689b8eb6cSchristos 
5789b8eb6cSchristos /* Local prototypes */
5889b8eb6cSchristos 
5989b8eb6cSchristos static void
6089b8eb6cSchristos AcpiDsResolvePackageElement (
6189b8eb6cSchristos     ACPI_OPERAND_OBJECT     **Element);
6289b8eb6cSchristos 
6389b8eb6cSchristos 
6489b8eb6cSchristos /*******************************************************************************
6589b8eb6cSchristos  *
6689b8eb6cSchristos  * FUNCTION:    AcpiDsBuildInternalPackageObj
6789b8eb6cSchristos  *
6889b8eb6cSchristos  * PARAMETERS:  WalkState       - Current walk state
6989b8eb6cSchristos  *              Op              - Parser object to be translated
7089b8eb6cSchristos  *              ElementCount    - Number of elements in the package - this is
7189b8eb6cSchristos  *                                the NumElements argument to Package()
7289b8eb6cSchristos  *              ObjDescPtr      - Where the ACPI internal object is returned
7389b8eb6cSchristos  *
7489b8eb6cSchristos  * RETURN:      Status
7589b8eb6cSchristos  *
7689b8eb6cSchristos  * DESCRIPTION: Translate a parser Op package object to the equivalent
7789b8eb6cSchristos  *              namespace object
7889b8eb6cSchristos  *
7989b8eb6cSchristos  * NOTE: The number of elements in the package will be always be the NumElements
8089b8eb6cSchristos  * count, regardless of the number of elements in the package list. If
8189b8eb6cSchristos  * NumElements is smaller, only that many package list elements are used.
8289b8eb6cSchristos  * if NumElements is larger, the Package object is padded out with
8389b8eb6cSchristos  * objects of type Uninitialized (as per ACPI spec.)
8489b8eb6cSchristos  *
8589b8eb6cSchristos  * Even though the ASL compilers do not allow NumElements to be smaller
8689b8eb6cSchristos  * than the Package list length (for the fixed length package opcode), some
8789b8eb6cSchristos  * BIOS code modifies the AML on the fly to adjust the NumElements, and
8889b8eb6cSchristos  * this code compensates for that. This also provides compatibility with
8989b8eb6cSchristos  * other AML interpreters.
9089b8eb6cSchristos  *
9189b8eb6cSchristos  ******************************************************************************/
9289b8eb6cSchristos 
9389b8eb6cSchristos ACPI_STATUS
AcpiDsBuildInternalPackageObj(ACPI_WALK_STATE * WalkState,ACPI_PARSE_OBJECT * Op,UINT32 ElementCount,ACPI_OPERAND_OBJECT ** ObjDescPtr)9489b8eb6cSchristos AcpiDsBuildInternalPackageObj (
9589b8eb6cSchristos     ACPI_WALK_STATE         *WalkState,
9689b8eb6cSchristos     ACPI_PARSE_OBJECT       *Op,
9789b8eb6cSchristos     UINT32                  ElementCount,
9889b8eb6cSchristos     ACPI_OPERAND_OBJECT     **ObjDescPtr)
9989b8eb6cSchristos {
10089b8eb6cSchristos     ACPI_PARSE_OBJECT       *Arg;
10189b8eb6cSchristos     ACPI_PARSE_OBJECT       *Parent;
10289b8eb6cSchristos     ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
10389b8eb6cSchristos     ACPI_STATUS             Status = AE_OK;
104062782b3Schristos     BOOLEAN                 ModuleLevelCode = FALSE;
10589b8eb6cSchristos     UINT16                  ReferenceCount;
10689b8eb6cSchristos     UINT32                  Index;
10789b8eb6cSchristos     UINT32                  i;
10889b8eb6cSchristos 
10989b8eb6cSchristos 
11089b8eb6cSchristos     ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj);
11189b8eb6cSchristos 
11289b8eb6cSchristos 
113062782b3Schristos     /* Check if we are executing module level code */
114062782b3Schristos 
115062782b3Schristos     if (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)
116062782b3Schristos     {
117062782b3Schristos         ModuleLevelCode = TRUE;
118062782b3Schristos     }
119062782b3Schristos 
12089b8eb6cSchristos     /* Find the parent of a possibly nested package */
12189b8eb6cSchristos 
12289b8eb6cSchristos     Parent = Op->Common.Parent;
12389b8eb6cSchristos     while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
12489b8eb6cSchristos            (Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
12589b8eb6cSchristos     {
12689b8eb6cSchristos         Parent = Parent->Common.Parent;
12789b8eb6cSchristos     }
12889b8eb6cSchristos 
12989b8eb6cSchristos     /*
13089b8eb6cSchristos      * If we are evaluating a Named package object of the form:
13189b8eb6cSchristos      *      Name (xxxx, Package)
13289b8eb6cSchristos      * the package object already exists, otherwise it must be created.
13389b8eb6cSchristos      */
13489b8eb6cSchristos     ObjDesc = *ObjDescPtr;
13589b8eb6cSchristos     if (!ObjDesc)
13689b8eb6cSchristos     {
13789b8eb6cSchristos         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE);
13889b8eb6cSchristos         *ObjDescPtr = ObjDesc;
13989b8eb6cSchristos         if (!ObjDesc)
14089b8eb6cSchristos         {
14189b8eb6cSchristos             return_ACPI_STATUS (AE_NO_MEMORY);
14289b8eb6cSchristos         }
14389b8eb6cSchristos 
14489b8eb6cSchristos         ObjDesc->Package.Node = Parent->Common.Node;
14589b8eb6cSchristos     }
14689b8eb6cSchristos 
14789b8eb6cSchristos     if (ObjDesc->Package.Flags & AOPOBJ_DATA_VALID) /* Just in case */
14889b8eb6cSchristos     {
14989b8eb6cSchristos         return_ACPI_STATUS (AE_OK);
15089b8eb6cSchristos     }
15189b8eb6cSchristos 
15289b8eb6cSchristos     /*
15389b8eb6cSchristos      * Allocate the element array (array of pointers to the individual
154062782b3Schristos      * objects) if necessary. the count is based on the NumElements
155062782b3Schristos      * parameter. Add an extra pointer slot so that the list is always
156062782b3Schristos      * null terminated.
15789b8eb6cSchristos      */
158062782b3Schristos     if (!ObjDesc->Package.Elements)
159062782b3Schristos     {
16089b8eb6cSchristos         ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED (
16189b8eb6cSchristos             ((ACPI_SIZE) ElementCount + 1) * sizeof (void *));
16289b8eb6cSchristos 
16389b8eb6cSchristos         if (!ObjDesc->Package.Elements)
16489b8eb6cSchristos         {
16589b8eb6cSchristos             AcpiUtDeleteObjectDesc (ObjDesc);
16689b8eb6cSchristos             return_ACPI_STATUS (AE_NO_MEMORY);
16789b8eb6cSchristos         }
16889b8eb6cSchristos 
16989b8eb6cSchristos         ObjDesc->Package.Count = ElementCount;
170062782b3Schristos     }
171062782b3Schristos 
172062782b3Schristos     /* First arg is element count. Second arg begins the initializer list */
173062782b3Schristos 
17489b8eb6cSchristos     Arg = Op->Common.Value.Arg;
17589b8eb6cSchristos     Arg = Arg->Common.Next;
17689b8eb6cSchristos 
177062782b3Schristos     /*
178062782b3Schristos      * If we are executing module-level code, we will defer the
179062782b3Schristos      * full resolution of the package elements in order to support
180062782b3Schristos      * forward references from the elements. This provides
181062782b3Schristos      * compatibility with other ACPI implementations.
182062782b3Schristos      */
183062782b3Schristos     if (ModuleLevelCode)
18489b8eb6cSchristos     {
185062782b3Schristos         ObjDesc->Package.AmlStart = WalkState->Aml;
186062782b3Schristos         ObjDesc->Package.AmlLength = 0;
187062782b3Schristos 
188062782b3Schristos         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
189062782b3Schristos             "%s: Deferring resolution of Package elements\n",
190062782b3Schristos             ACPI_GET_FUNCTION_NAME));
19189b8eb6cSchristos     }
19289b8eb6cSchristos 
19389b8eb6cSchristos     /*
19489b8eb6cSchristos      * Initialize the elements of the package, up to the NumElements count.
19589b8eb6cSchristos      * Package is automatically padded with uninitialized (NULL) elements
19689b8eb6cSchristos      * if NumElements is greater than the package list length. Likewise,
19789b8eb6cSchristos      * Package is truncated if NumElements is less than the list length.
19889b8eb6cSchristos      */
19989b8eb6cSchristos     for (i = 0; Arg && (i < ElementCount); i++)
20089b8eb6cSchristos     {
20189b8eb6cSchristos         if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP)
20289b8eb6cSchristos         {
2037efa3256Schristos             if (!Arg->Common.Node)
2047efa3256Schristos             {
2057efa3256Schristos                 /*
2067efa3256Schristos                  * This is the case where an expression has returned a value.
2077efa3256Schristos                  * The use of expressions (TermArgs) within individual
2087efa3256Schristos                  * package elements is not supported by the AML interpreter,
2097efa3256Schristos                  * even though the ASL grammar supports it. Example:
2107efa3256Schristos                  *
2117efa3256Schristos                  *      Name (INT1, 0x1234)
2127efa3256Schristos                  *
2137efa3256Schristos                  *      Name (PKG3, Package () {
2147efa3256Schristos                  *          Add (INT1, 0xAAAA0000)
2157efa3256Schristos                  *      })
2167efa3256Schristos                  *
2177efa3256Schristos                  *  1) No known AML interpreter supports this type of construct
2187efa3256Schristos                  *  2) This fixes a fault if the construct is encountered
2197efa3256Schristos                  */
2207efa3256Schristos                 ACPI_EXCEPTION ((AE_INFO, AE_SUPPORT,
2217efa3256Schristos                     "Expressions within package elements are not supported"));
2227efa3256Schristos 
2237efa3256Schristos                 /* Cleanup the return object, it is not needed */
2247efa3256Schristos 
2257efa3256Schristos                 AcpiUtRemoveReference (WalkState->Results->Results.ObjDesc[0]);
2267efa3256Schristos                 return_ACPI_STATUS (AE_SUPPORT);
2277efa3256Schristos             }
2287efa3256Schristos 
22989b8eb6cSchristos             if (Arg->Common.Node->Type == ACPI_TYPE_METHOD)
23089b8eb6cSchristos             {
23189b8eb6cSchristos                 /*
23289b8eb6cSchristos                  * A method reference "looks" to the parser to be a method
23389b8eb6cSchristos                  * invocation, so we special case it here
23489b8eb6cSchristos                  */
23589b8eb6cSchristos                 Arg->Common.AmlOpcode = AML_INT_NAMEPATH_OP;
23689b8eb6cSchristos                 Status = AcpiDsBuildInternalObject (
23789b8eb6cSchristos                     WalkState, Arg, &ObjDesc->Package.Elements[i]);
23889b8eb6cSchristos             }
23989b8eb6cSchristos             else
24089b8eb6cSchristos             {
24189b8eb6cSchristos                 /* This package element is already built, just get it */
24289b8eb6cSchristos 
24389b8eb6cSchristos                 ObjDesc->Package.Elements[i] =
24489b8eb6cSchristos                     ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node);
24589b8eb6cSchristos             }
24689b8eb6cSchristos         }
24789b8eb6cSchristos         else
24889b8eb6cSchristos         {
24989b8eb6cSchristos             Status = AcpiDsBuildInternalObject (
25089b8eb6cSchristos                 WalkState, Arg, &ObjDesc->Package.Elements[i]);
25189b8eb6cSchristos             if (Status == AE_NOT_FOUND)
25289b8eb6cSchristos             {
25389b8eb6cSchristos                 ACPI_ERROR ((AE_INFO, "%-48s", "****DS namepath not found"));
25489b8eb6cSchristos             }
25589b8eb6cSchristos 
256062782b3Schristos             if (!ModuleLevelCode)
257062782b3Schristos             {
25889b8eb6cSchristos                 /*
25989b8eb6cSchristos                  * Initialize this package element. This function handles the
26089b8eb6cSchristos                  * resolution of named references within the package.
261062782b3Schristos                  * Forward references from module-level code are deferred
262062782b3Schristos                  * until all ACPI tables are loaded.
26389b8eb6cSchristos                  */
26489b8eb6cSchristos                 AcpiDsInitPackageElement (0, ObjDesc->Package.Elements[i],
26589b8eb6cSchristos                     NULL, &ObjDesc->Package.Elements[i]);
26689b8eb6cSchristos             }
267062782b3Schristos         }
26889b8eb6cSchristos 
26989b8eb6cSchristos         if (*ObjDescPtr)
27089b8eb6cSchristos         {
27189b8eb6cSchristos             /* Existing package, get existing reference count */
27289b8eb6cSchristos 
27389b8eb6cSchristos             ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount;
27489b8eb6cSchristos             if (ReferenceCount > 1)
27589b8eb6cSchristos             {
27689b8eb6cSchristos                 /* Make new element ref count match original ref count */
27789b8eb6cSchristos                 /* TBD: Probably need an AcpiUtAddReferences function */
27889b8eb6cSchristos 
27989b8eb6cSchristos                 for (Index = 0; Index < ((UINT32) ReferenceCount - 1); Index++)
28089b8eb6cSchristos                 {
28189b8eb6cSchristos                     AcpiUtAddReference ((ObjDesc->Package.Elements[i]));
28289b8eb6cSchristos                 }
28389b8eb6cSchristos             }
28489b8eb6cSchristos         }
28589b8eb6cSchristos 
28689b8eb6cSchristos         Arg = Arg->Common.Next;
28789b8eb6cSchristos     }
28889b8eb6cSchristos 
28989b8eb6cSchristos     /* Check for match between NumElements and actual length of PackageList */
29089b8eb6cSchristos 
29189b8eb6cSchristos     if (Arg)
29289b8eb6cSchristos     {
29389b8eb6cSchristos         /*
29489b8eb6cSchristos          * NumElements was exhausted, but there are remaining elements in
29589b8eb6cSchristos          * the PackageList. Truncate the package to NumElements.
29689b8eb6cSchristos          *
29789b8eb6cSchristos          * Note: technically, this is an error, from ACPI spec: "It is an
29889b8eb6cSchristos          * error for NumElements to be less than the number of elements in
29989b8eb6cSchristos          * the PackageList". However, we just print a message and no
30089b8eb6cSchristos          * exception is returned. This provides compatibility with other
30189b8eb6cSchristos          * ACPI implementations. Some firmware implementations will alter
30289b8eb6cSchristos          * the NumElements on the fly, possibly creating this type of
30389b8eb6cSchristos          * ill-formed package object.
30489b8eb6cSchristos          */
30589b8eb6cSchristos         while (Arg)
30689b8eb6cSchristos         {
30789b8eb6cSchristos             /*
30889b8eb6cSchristos              * We must delete any package elements that were created earlier
30989b8eb6cSchristos              * and are not going to be used because of the package truncation.
31089b8eb6cSchristos              */
31189b8eb6cSchristos             if (Arg->Common.Node)
31289b8eb6cSchristos             {
31389b8eb6cSchristos                 AcpiUtRemoveReference (
31489b8eb6cSchristos                     ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node));
31589b8eb6cSchristos                 Arg->Common.Node = NULL;
31689b8eb6cSchristos             }
31789b8eb6cSchristos 
31889b8eb6cSchristos             /* Find out how many elements there really are */
31989b8eb6cSchristos 
32089b8eb6cSchristos             i++;
32189b8eb6cSchristos             Arg = Arg->Common.Next;
32289b8eb6cSchristos         }
32389b8eb6cSchristos 
32489b8eb6cSchristos         ACPI_INFO ((
32589b8eb6cSchristos             "Actual Package length (%u) is larger than "
32689b8eb6cSchristos             "NumElements field (%u), truncated",
32789b8eb6cSchristos             i, ElementCount));
32889b8eb6cSchristos     }
32989b8eb6cSchristos     else if (i < ElementCount)
33089b8eb6cSchristos     {
33189b8eb6cSchristos         /*
33289b8eb6cSchristos          * Arg list (elements) was exhausted, but we did not reach
33389b8eb6cSchristos          * NumElements count.
33489b8eb6cSchristos          *
33589b8eb6cSchristos          * Note: this is not an error, the package is padded out
336062782b3Schristos          * with NULLs as per the ACPI specification.
33789b8eb6cSchristos          */
338062782b3Schristos         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,
339062782b3Schristos             "%s: Package List length (%u) smaller than NumElements "
34089b8eb6cSchristos             "count (%u), padded with null elements\n",
341062782b3Schristos             ACPI_GET_FUNCTION_NAME, i, ElementCount));
34289b8eb6cSchristos     }
34389b8eb6cSchristos 
344062782b3Schristos     /* Module-level packages will be resolved later */
345062782b3Schristos 
346062782b3Schristos     if (!ModuleLevelCode)
347062782b3Schristos     {
34889b8eb6cSchristos         ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID;
349062782b3Schristos     }
350062782b3Schristos 
35189b8eb6cSchristos     Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);
35289b8eb6cSchristos     return_ACPI_STATUS (Status);
35389b8eb6cSchristos }
35489b8eb6cSchristos 
35589b8eb6cSchristos 
35689b8eb6cSchristos /*******************************************************************************
35789b8eb6cSchristos  *
35889b8eb6cSchristos  * FUNCTION:    AcpiDsInitPackageElement
35989b8eb6cSchristos  *
36089b8eb6cSchristos  * PARAMETERS:  ACPI_PKG_CALLBACK
36189b8eb6cSchristos  *
36289b8eb6cSchristos  * RETURN:      Status
36389b8eb6cSchristos  *
36489b8eb6cSchristos  * DESCRIPTION: Resolve a named reference element within a package object
36589b8eb6cSchristos  *
36689b8eb6cSchristos  ******************************************************************************/
36789b8eb6cSchristos 
36889b8eb6cSchristos ACPI_STATUS
AcpiDsInitPackageElement(UINT8 ObjectType,ACPI_OPERAND_OBJECT * SourceObject,ACPI_GENERIC_STATE * State,void * Context)36989b8eb6cSchristos AcpiDsInitPackageElement (
37089b8eb6cSchristos     UINT8                   ObjectType,
37189b8eb6cSchristos     ACPI_OPERAND_OBJECT     *SourceObject,
37289b8eb6cSchristos     ACPI_GENERIC_STATE      *State,
37389b8eb6cSchristos     void                    *Context)
37489b8eb6cSchristos {
37589b8eb6cSchristos     ACPI_OPERAND_OBJECT     **ElementPtr;
37689b8eb6cSchristos 
37789b8eb6cSchristos 
378062782b3Schristos     ACPI_FUNCTION_TRACE (DsInitPackageElement);
379062782b3Schristos 
380062782b3Schristos 
38189b8eb6cSchristos     if (!SourceObject)
38289b8eb6cSchristos     {
383062782b3Schristos         return_ACPI_STATUS (AE_OK);
38489b8eb6cSchristos     }
38589b8eb6cSchristos 
38689b8eb6cSchristos     /*
38789b8eb6cSchristos      * The following code is a bit of a hack to workaround a (current)
38889b8eb6cSchristos      * limitation of the ACPI_PKG_CALLBACK interface. We need a pointer
38989b8eb6cSchristos      * to the location within the element array because a new object
39089b8eb6cSchristos      * may be created and stored there.
39189b8eb6cSchristos      */
39289b8eb6cSchristos     if (Context)
39389b8eb6cSchristos     {
39489b8eb6cSchristos         /* A direct call was made to this function */
39589b8eb6cSchristos 
39689b8eb6cSchristos         ElementPtr = (ACPI_OPERAND_OBJECT **) Context;
39789b8eb6cSchristos     }
39889b8eb6cSchristos     else
39989b8eb6cSchristos     {
40089b8eb6cSchristos         /* Call came from AcpiUtWalkPackageTree */
40189b8eb6cSchristos 
40289b8eb6cSchristos         ElementPtr = State->Pkg.ThisTargetObj;
40389b8eb6cSchristos     }
40489b8eb6cSchristos 
40589b8eb6cSchristos     /* We are only interested in reference objects/elements */
40689b8eb6cSchristos 
40789b8eb6cSchristos     if (SourceObject->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)
40889b8eb6cSchristos     {
40989b8eb6cSchristos         /* Attempt to resolve the (named) reference to a namespace node */
41089b8eb6cSchristos 
41189b8eb6cSchristos         AcpiDsResolvePackageElement (ElementPtr);
41289b8eb6cSchristos     }
41389b8eb6cSchristos     else if (SourceObject->Common.Type == ACPI_TYPE_PACKAGE)
41489b8eb6cSchristos     {
41589b8eb6cSchristos         SourceObject->Package.Flags |= AOPOBJ_DATA_VALID;
41689b8eb6cSchristos     }
41789b8eb6cSchristos 
418062782b3Schristos     return_ACPI_STATUS (AE_OK);
41989b8eb6cSchristos }
42089b8eb6cSchristos 
42189b8eb6cSchristos 
42289b8eb6cSchristos /*******************************************************************************
42389b8eb6cSchristos  *
42489b8eb6cSchristos  * FUNCTION:    AcpiDsResolvePackageElement
42589b8eb6cSchristos  *
42689b8eb6cSchristos  * PARAMETERS:  ElementPtr          - Pointer to a reference object
42789b8eb6cSchristos  *
42889b8eb6cSchristos  * RETURN:      Possible new element is stored to the indirect ElementPtr
42989b8eb6cSchristos  *
43089b8eb6cSchristos  * DESCRIPTION: Resolve a package element that is a reference to a named
43189b8eb6cSchristos  *              object.
43289b8eb6cSchristos  *
43389b8eb6cSchristos  ******************************************************************************/
43489b8eb6cSchristos 
43589b8eb6cSchristos static void
AcpiDsResolvePackageElement(ACPI_OPERAND_OBJECT ** ElementPtr)43689b8eb6cSchristos AcpiDsResolvePackageElement (
43789b8eb6cSchristos     ACPI_OPERAND_OBJECT     **ElementPtr)
43889b8eb6cSchristos {
43989b8eb6cSchristos     ACPI_STATUS             Status;
440062782b3Schristos     ACPI_STATUS             Status2;
44189b8eb6cSchristos     ACPI_GENERIC_STATE      ScopeInfo;
44289b8eb6cSchristos     ACPI_OPERAND_OBJECT     *Element = *ElementPtr;
44389b8eb6cSchristos     ACPI_NAMESPACE_NODE     *ResolvedNode;
444062782b3Schristos     ACPI_NAMESPACE_NODE     *OriginalNode;
445f45f09e8Schristos     char                    *ExternalPath = __UNCONST("");
44689b8eb6cSchristos     ACPI_OBJECT_TYPE        Type;
44789b8eb6cSchristos 
44889b8eb6cSchristos 
44989b8eb6cSchristos     ACPI_FUNCTION_TRACE (DsResolvePackageElement);
45089b8eb6cSchristos 
45189b8eb6cSchristos 
45289b8eb6cSchristos     /* Check if reference element is already resolved */
45389b8eb6cSchristos 
45489b8eb6cSchristos     if (Element->Reference.Resolved)
45589b8eb6cSchristos     {
456062782b3Schristos         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
457062782b3Schristos             "%s: Package element is already resolved\n",
458062782b3Schristos             ACPI_GET_FUNCTION_NAME));
459062782b3Schristos 
46089b8eb6cSchristos         return_VOID;
46189b8eb6cSchristos     }
46289b8eb6cSchristos 
46389b8eb6cSchristos     /* Element must be a reference object of correct type */
46489b8eb6cSchristos 
46589b8eb6cSchristos     ScopeInfo.Scope.Node = Element->Reference.Node; /* Prefix node */
46689b8eb6cSchristos 
467062782b3Schristos     Status = AcpiNsLookup (&ScopeInfo, (char *) Element->Reference.Aml,
46889b8eb6cSchristos         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
46989b8eb6cSchristos         ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
47089b8eb6cSchristos         NULL, &ResolvedNode);
47189b8eb6cSchristos     if (ACPI_FAILURE (Status))
47289b8eb6cSchristos     {
473062782b3Schristos         if ((Status == AE_NOT_FOUND) && AcpiGbl_IgnorePackageResolutionErrors)
474062782b3Schristos         {
475062782b3Schristos             /*
476062782b3Schristos              * Optionally be silent about the NOT_FOUND case for the referenced
477062782b3Schristos              * name. Although this is potentially a serious problem,
478062782b3Schristos              * it can generate a lot of noise/errors on platforms whose
479062782b3Schristos              * firmware carries around a bunch of unused Package objects.
480062782b3Schristos              * To disable these errors, set this global to TRUE:
481062782b3Schristos              *     AcpiGbl_IgnorePackageResolutionErrors
482062782b3Schristos              *
483062782b3Schristos              * If the AML actually tries to use such a package, the unresolved
484062782b3Schristos              * element(s) will be replaced with NULL elements.
485062782b3Schristos              */
486062782b3Schristos 
487062782b3Schristos             /* Referenced name not found, set the element to NULL */
488062782b3Schristos 
489062782b3Schristos             AcpiUtRemoveReference (*ElementPtr);
490062782b3Schristos             *ElementPtr = NULL;
491062782b3Schristos             return_VOID;
492062782b3Schristos         }
493062782b3Schristos 
494062782b3Schristos         Status2 = AcpiNsExternalizeName (ACPI_UINT32_MAX,
495062782b3Schristos             (char *) Element->Reference.Aml, NULL, &ExternalPath);
49689b8eb6cSchristos 
49789b8eb6cSchristos         ACPI_EXCEPTION ((AE_INFO, Status,
498062782b3Schristos             "While resolving a named reference package element - %s",
499062782b3Schristos             ExternalPath));
500062782b3Schristos         if (ACPI_SUCCESS (Status2))
501062782b3Schristos         {
50289b8eb6cSchristos             ACPI_FREE (ExternalPath);
503062782b3Schristos         }
504062782b3Schristos 
505062782b3Schristos         /* Could not resolve name, set the element to NULL */
506062782b3Schristos 
507062782b3Schristos         AcpiUtRemoveReference (*ElementPtr);
50889b8eb6cSchristos         *ElementPtr = NULL;
50989b8eb6cSchristos         return_VOID;
51089b8eb6cSchristos     }
51189b8eb6cSchristos     else if (ResolvedNode->Type == ACPI_TYPE_ANY)
51289b8eb6cSchristos     {
51389b8eb6cSchristos         /* Named reference not resolved, return a NULL package element */
51489b8eb6cSchristos 
51589b8eb6cSchristos         ACPI_ERROR ((AE_INFO,
51689b8eb6cSchristos             "Could not resolve named package element [%4.4s] in [%4.4s]",
51789b8eb6cSchristos             ResolvedNode->Name.Ascii, ScopeInfo.Scope.Node->Name.Ascii));
51889b8eb6cSchristos         *ElementPtr = NULL;
51989b8eb6cSchristos         return_VOID;
52089b8eb6cSchristos     }
52189b8eb6cSchristos 
52289b8eb6cSchristos     /*
52389b8eb6cSchristos      * Special handling for Alias objects. We need ResolvedNode to point
52489b8eb6cSchristos      * to the Alias target. This effectively "resolves" the alias.
52589b8eb6cSchristos      */
52689b8eb6cSchristos     if (ResolvedNode->Type == ACPI_TYPE_LOCAL_ALIAS)
52789b8eb6cSchristos     {
52889b8eb6cSchristos         ResolvedNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
52989b8eb6cSchristos             ResolvedNode->Object);
53089b8eb6cSchristos     }
53189b8eb6cSchristos 
53289b8eb6cSchristos     /* Update the reference object */
53389b8eb6cSchristos 
53489b8eb6cSchristos     Element->Reference.Resolved = TRUE;
53589b8eb6cSchristos     Element->Reference.Node = ResolvedNode;
53689b8eb6cSchristos     Type = Element->Reference.Node->Type;
53789b8eb6cSchristos 
53889b8eb6cSchristos     /*
53989b8eb6cSchristos      * Attempt to resolve the node to a value before we insert it into
54089b8eb6cSchristos      * the package. If this is a reference to a common data type,
54189b8eb6cSchristos      * resolve it immediately. According to the ACPI spec, package
54289b8eb6cSchristos      * elements can only be "data objects" or method references.
54389b8eb6cSchristos      * Attempt to resolve to an Integer, Buffer, String or Package.
54489b8eb6cSchristos      * If cannot, return the named reference (for things like Devices,
54589b8eb6cSchristos      * Methods, etc.) Buffer Fields and Fields will resolve to simple
54689b8eb6cSchristos      * objects (int/buf/str/pkg).
54789b8eb6cSchristos      *
54889b8eb6cSchristos      * NOTE: References to things like Devices, Methods, Mutexes, etc.
54989b8eb6cSchristos      * will remain as named references. This behavior is not described
55089b8eb6cSchristos      * in the ACPI spec, but it appears to be an oversight.
55189b8eb6cSchristos      */
552062782b3Schristos     OriginalNode = ResolvedNode;
55389b8eb6cSchristos     Status = AcpiExResolveNodeToValue (&ResolvedNode, NULL);
55489b8eb6cSchristos     if (ACPI_FAILURE (Status))
55589b8eb6cSchristos     {
55689b8eb6cSchristos         return_VOID;
55789b8eb6cSchristos     }
55889b8eb6cSchristos 
55989b8eb6cSchristos     switch (Type)
56089b8eb6cSchristos     {
56189b8eb6cSchristos     /*
56289b8eb6cSchristos      * These object types are a result of named references, so we will
56389b8eb6cSchristos      * leave them as reference objects. In other words, these types
56489b8eb6cSchristos      * have no intrinsic "value".
56589b8eb6cSchristos      */
56689b8eb6cSchristos     case ACPI_TYPE_DEVICE:
56789b8eb6cSchristos     case ACPI_TYPE_THERMAL:
568062782b3Schristos     case ACPI_TYPE_METHOD:
56989b8eb6cSchristos         break;
57089b8eb6cSchristos 
57189b8eb6cSchristos     case ACPI_TYPE_MUTEX:
57289b8eb6cSchristos     case ACPI_TYPE_POWER:
57389b8eb6cSchristos     case ACPI_TYPE_PROCESSOR:
57489b8eb6cSchristos     case ACPI_TYPE_EVENT:
57589b8eb6cSchristos     case ACPI_TYPE_REGION:
57689b8eb6cSchristos 
577062782b3Schristos         /* AcpiExResolveNodeToValue gave these an extra reference */
578062782b3Schristos 
579062782b3Schristos         AcpiUtRemoveReference (OriginalNode->Object);
58089b8eb6cSchristos         break;
58189b8eb6cSchristos 
58289b8eb6cSchristos     default:
58389b8eb6cSchristos         /*
58489b8eb6cSchristos          * For all other types - the node was resolved to an actual
585062782b3Schristos          * operand object with a value, return the object. Remove
586062782b3Schristos          * a reference on the existing object.
58789b8eb6cSchristos          */
588062782b3Schristos         AcpiUtRemoveReference (Element);
58989b8eb6cSchristos         *ElementPtr = (ACPI_OPERAND_OBJECT *) ResolvedNode;
59089b8eb6cSchristos         break;
59189b8eb6cSchristos     }
59289b8eb6cSchristos 
59389b8eb6cSchristos     return_VOID;
59489b8eb6cSchristos }
595