Home | History | Annotate | Line # | Download | only in compiler
aslxref.c revision 1.19
      1 /******************************************************************************
      2  *
      3  * Module Name: aslxref - Namespace cross-reference
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2020, 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 MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "aslcompiler.h"
     45 #include "aslcompiler.y.h"
     46 #include "acparser.h"
     47 #include "amlcode.h"
     48 #include "acnamesp.h"
     49 #include "acdispat.h"
     50 
     51 
     52 #define _COMPONENT          ACPI_COMPILER
     53         ACPI_MODULE_NAME    ("aslxref")
     54 
     55 /* Local prototypes */
     56 
     57 static ACPI_STATUS
     58 XfNamespaceLocateBegin (
     59     ACPI_PARSE_OBJECT       *Op,
     60     UINT32                  Level,
     61     void                    *Context);
     62 
     63 static ACPI_STATUS
     64 XfNamespaceLocateEnd (
     65     ACPI_PARSE_OBJECT       *Op,
     66     UINT32                  Level,
     67     void                    *Context);
     68 
     69 static BOOLEAN
     70 XfValidateCrossReference (
     71     ACPI_PARSE_OBJECT       *Op,
     72     const ACPI_OPCODE_INFO  *OpInfo,
     73     ACPI_NAMESPACE_NODE     *Node);
     74 
     75 static BOOLEAN
     76 XfObjectExists (
     77     char                    *Name);
     78 
     79 static ACPI_STATUS
     80 XfCompareOneNamespaceObject (
     81     ACPI_HANDLE             ObjHandle,
     82     UINT32                  Level,
     83     void                    *Context,
     84     void                    **ReturnValue);
     85 
     86 static void
     87 XfCheckFieldRange (
     88     ACPI_PARSE_OBJECT       *Op,
     89     UINT32                  RegionBitLength,
     90     UINT32                  FieldBitOffset,
     91     UINT32                  FieldBitLength,
     92     UINT32                  AccessBitWidth);
     93 
     94 static BOOLEAN
     95 XfFindCondRefOfName (
     96     ACPI_NAMESPACE_NODE     *Node,
     97     ACPI_PARSE_OBJECT       *Op);
     98 
     99 static BOOLEAN
    100 XfRefIsGuardedByIfCondRefOf (
    101     ACPI_NAMESPACE_NODE     *Node,
    102     ACPI_PARSE_OBJECT       *Op);
    103 
    104 
    105 /*******************************************************************************
    106  *
    107  * FUNCTION:    XfCrossReferenceNamespace
    108  *
    109  * PARAMETERS:  None
    110  *
    111  * RETURN:      Status
    112  *
    113  * DESCRIPTION: Perform a cross reference check of the parse tree against the
    114  *              namespace. Every named referenced within the parse tree
    115  *              should be get resolved with a namespace lookup. If not, the
    116  *              original reference in the ASL code is invalid -- i.e., refers
    117  *              to a non-existent object.
    118  *
    119  * NOTE:  The ASL "External" operator causes the name to be inserted into the
    120  *        namespace so that references to the external name will be resolved
    121  *        correctly here.
    122  *
    123  ******************************************************************************/
    124 
    125 ACPI_STATUS
    126 XfCrossReferenceNamespace (
    127     void)
    128 {
    129     ACPI_WALK_STATE         *WalkState;
    130 
    131 
    132     /*
    133      * Create a new walk state for use when looking up names
    134      * within the namespace (Passed as context to the callbacks)
    135      */
    136     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
    137     if (!WalkState)
    138     {
    139         return (AE_NO_MEMORY);
    140     }
    141 
    142     /* Walk the entire parse tree */
    143 
    144     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
    145         XfNamespaceLocateBegin, XfNamespaceLocateEnd, WalkState);
    146 
    147     ACPI_FREE (WalkState);
    148     return (AE_OK);
    149 }
    150 
    151 
    152 /*******************************************************************************
    153  *
    154  * FUNCTION:    XfObjectExists
    155  *
    156  * PARAMETERS:  Name            - 4 char ACPI name
    157  *
    158  * RETURN:      TRUE if name exists in namespace
    159  *
    160  * DESCRIPTION: Walk the namespace to find an object
    161  *
    162  ******************************************************************************/
    163 
    164 static BOOLEAN
    165 XfObjectExists (
    166     char                    *Name)
    167 {
    168     ACPI_STATUS             Status;
    169 
    170 
    171     /* Walk entire namespace from the supplied root */
    172 
    173     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
    174         ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL,
    175         Name, NULL);
    176     if (Status == AE_CTRL_TRUE)
    177     {
    178         /* At least one instance of the name was found */
    179 
    180         return (TRUE);
    181     }
    182 
    183     return (FALSE);
    184 }
    185 
    186 
    187 /*******************************************************************************
    188  *
    189  * FUNCTION:    XfCompareOneNamespaceObject
    190  *
    191  * PARAMETERS:  ACPI_WALK_CALLBACK
    192  *
    193  * RETURN:      Status
    194  *
    195  * DESCRIPTION: Compare name of one object.
    196  *
    197  ******************************************************************************/
    198 
    199 static ACPI_STATUS
    200 XfCompareOneNamespaceObject (
    201     ACPI_HANDLE             ObjHandle,
    202     UINT32                  Level,
    203     void                    *Context,
    204     void                    **ReturnValue)
    205 {
    206     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    207 
    208 
    209     /* Simply check the name */
    210 
    211     if (*((UINT32 *) (Context)) == Node->Name.Integer)
    212     {
    213         /* Abort walk if we found one instance */
    214 
    215         return (AE_CTRL_TRUE);
    216     }
    217 
    218     return (AE_OK);
    219 }
    220 
    221 
    222 /*******************************************************************************
    223  *
    224  * FUNCTION:    XfCheckFieldRange
    225  *
    226  * PARAMETERS:  RegionBitLength     - Length of entire parent region
    227  *              FieldBitOffset      - Start of the field unit (within region)
    228  *              FieldBitLength      - Entire length of field unit
    229  *              AccessBitWidth      - Access width of the field unit
    230  *
    231  * RETURN:      None
    232  *
    233  * DESCRIPTION: Check one field unit to make sure it fits in the parent
    234  *              op region.
    235  *
    236  * Note: AccessBitWidth must be either 8,16,32, or 64
    237  *
    238  ******************************************************************************/
    239 
    240 static void
    241 XfCheckFieldRange (
    242     ACPI_PARSE_OBJECT       *Op,
    243     UINT32                  RegionBitLength,
    244     UINT32                  FieldBitOffset,
    245     UINT32                  FieldBitLength,
    246     UINT32                  AccessBitWidth)
    247 {
    248     UINT32                  FieldEndBitOffset;
    249 
    250 
    251     /*
    252      * Check each field unit against the region size. The entire
    253      * field unit (start offset plus length) must fit within the
    254      * region.
    255      */
    256     FieldEndBitOffset = FieldBitOffset + FieldBitLength;
    257 
    258     if (FieldEndBitOffset > RegionBitLength)
    259     {
    260         /* Field definition itself is beyond the end-of-region */
    261 
    262         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
    263         return;
    264     }
    265 
    266     /*
    267      * Now check that the field plus AccessWidth doesn't go beyond
    268      * the end-of-region. Assumes AccessBitWidth is a power of 2
    269      */
    270     FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
    271 
    272     if (FieldEndBitOffset > RegionBitLength)
    273     {
    274         /* Field definition combined with the access is beyond EOR */
    275 
    276         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
    277     }
    278 }
    279 
    280 
    281 /*******************************************************************************
    282  *
    283  * FUNCTION:    XfNamespaceLocateBegin
    284  *
    285  * PARAMETERS:  ASL_WALK_CALLBACK
    286  *
    287  * RETURN:      Status
    288  *
    289  * DESCRIPTION: Descending callback used during cross-reference. For named
    290  *              object references, attempt to locate the name in the
    291  *              namespace.
    292  *
    293  * NOTE: ASL references to named fields within resource descriptors are
    294  *       resolved to integer values here. Therefore, this step is an
    295  *       important part of the code generation. We don't know that the
    296  *       name refers to a resource descriptor until now.
    297  *
    298  ******************************************************************************/
    299 
    300 static ACPI_STATUS
    301 XfNamespaceLocateBegin (
    302     ACPI_PARSE_OBJECT       *Op,
    303     UINT32                  Level,
    304     void                    *Context)
    305 {
    306     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
    307     ACPI_NAMESPACE_NODE     *Node;
    308     ACPI_STATUS             Status;
    309     ACPI_OBJECT_TYPE        ObjectType;
    310     char                    *Path;
    311     UINT8                   PassedArgs;
    312     ACPI_PARSE_OBJECT       *NextOp;
    313     ACPI_PARSE_OBJECT       *OwningOp;
    314     ACPI_PARSE_OBJECT       *SpaceIdOp;
    315     UINT32                  MinimumLength;
    316     UINT32                  Offset;
    317     UINT32                  FieldBitLength;
    318     UINT32                  TagBitLength;
    319     UINT8                   Message = 0;
    320     const ACPI_OPCODE_INFO  *OpInfo;
    321     UINT32                  Flags;
    322     ASL_METHOD_LOCAL        *MethodLocals = NULL;
    323     ASL_METHOD_LOCAL        *MethodArgs = NULL;
    324     int                     RegisterNumber;
    325     UINT32                  i;
    326     ACPI_NAMESPACE_NODE     *DeclarationParentMethod;
    327     ACPI_PARSE_OBJECT       *ReferenceParentMethod;
    328 
    329 
    330     ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);
    331 
    332 
    333     if ((Op->Asl.AmlOpcode == AML_METHOD_OP) && Op->Asl.Node)
    334     {
    335         Node = Op->Asl.Node;
    336 
    337         /* Support for method LocalX/ArgX analysis */
    338 
    339         if (!Node->MethodLocals)
    340         {
    341             /* Create local/arg info blocks */
    342 
    343             MethodLocals = UtLocalCalloc (
    344                 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS);
    345             Node->MethodLocals = MethodLocals;
    346 
    347             MethodArgs = UtLocalCalloc (
    348                 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS);
    349             Node->MethodArgs = MethodArgs;
    350 
    351             /*
    352              * Get the method argument count
    353              * First, get the name node
    354              */
    355             NextOp = Op->Asl.Child;
    356 
    357             /* Get the NumArguments node */
    358 
    359             NextOp = NextOp->Asl.Next;
    360             Node->ArgCount = (UINT8)
    361                 (((UINT8) NextOp->Asl.Value.Integer) & 0x07);
    362 
    363             /* We will track all possible ArgXs */
    364 
    365             for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
    366             {
    367                 if (i < Node->ArgCount)
    368                 {
    369                     /* Real Args are always "initialized" */
    370 
    371                     MethodArgs[i].Flags = ASL_ARG_INITIALIZED;
    372                 }
    373                 else
    374                 {
    375                     /* Other ArgXs can be used as locals */
    376 
    377                     MethodArgs[i].Flags = ASL_ARG_IS_LOCAL;
    378                 }
    379 
    380                 MethodArgs[i].Op = Op;
    381             }
    382         }
    383     }
    384 
    385     /*
    386      * If this node is the actual declaration of a name
    387      * [such as the XXXX name in "Method (XXXX)"],
    388      * we are not interested in it here. We only care about names that are
    389      * references to other objects within the namespace and the parent objects
    390      * of name declarations
    391      */
    392     if (Op->Asl.CompileFlags & OP_IS_NAME_DECLARATION)
    393     {
    394         return_ACPI_STATUS (AE_OK);
    395     }
    396 
    397     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    398 
    399     /* Check method LocalX variables */
    400 
    401     if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE)
    402     {
    403         /* Find parent method Op */
    404 
    405         NextOp = UtGetParentMethodOp (Op);
    406         if (!NextOp)
    407         {
    408             return_ACPI_STATUS (AE_OK);
    409         }
    410 
    411         /* Get method node */
    412 
    413         Node = NextOp->Asl.Node;
    414 
    415         RegisterNumber = Op->Asl.AmlOpcode & 0x0007; /* 0x60 through 0x67 */
    416         MethodLocals = Node->MethodLocals;
    417 
    418         if (Op->Asl.CompileFlags & OP_IS_TARGET)
    419         {
    420             /* Local is being initialized */
    421 
    422             MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_INITIALIZED;
    423             MethodLocals[RegisterNumber].Op = Op;
    424 
    425             return_ACPI_STATUS (AE_OK);
    426         }
    427 
    428         /* Mark this Local as referenced */
    429 
    430         MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_REFERENCED;
    431         MethodLocals[RegisterNumber].Op = Op;
    432 
    433         return_ACPI_STATUS (AE_OK);
    434     }
    435 
    436     /* Check method ArgX variables */
    437 
    438     if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT)
    439     {
    440         /* Find parent method Op */
    441 
    442         NextOp = UtGetParentMethodOp (Op);
    443         if (!NextOp)
    444         {
    445             return_ACPI_STATUS (AE_OK);
    446         }
    447 
    448         /* Get method node */
    449 
    450         Node = NextOp->Asl.Node;
    451 
    452         /* Get Arg # */
    453 
    454         RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */
    455         MethodArgs = Node->MethodArgs;
    456 
    457         /* Mark this Arg as referenced */
    458 
    459         MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED;
    460         MethodArgs[RegisterNumber].Op = Op;
    461 
    462         if (Op->Asl.CompileFlags & OP_IS_TARGET)
    463         {
    464             /* Arg is being initialized */
    465 
    466             MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED;
    467         }
    468 
    469         return_ACPI_STATUS (AE_OK);
    470     }
    471 
    472     /*
    473      * After method ArgX and LocalX, we are only interested in opcodes
    474      * that have an associated name
    475      */
    476     if ((!(OpInfo->Flags & AML_NAMED)) &&
    477         (!(OpInfo->Flags & AML_CREATE)) &&
    478         (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
    479         (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
    480         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL) &&
    481         (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL))
    482     {
    483         return_ACPI_STATUS (AE_OK);
    484     }
    485 
    486     /*
    487      * We must enable the "search-to-root" for single NameSegs, but
    488      * we have to be very careful about opening up scopes
    489      */
    490     Flags = ACPI_NS_SEARCH_PARENT;
    491     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
    492         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
    493         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
    494         (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)   ||
    495         (Op->Asl.ParseOpcode == PARSEOP_CONDREFOF))
    496     {
    497         /*
    498          * These are name references, do not push the scope stack
    499          * for them.
    500          */
    501         Flags |= ACPI_NS_DONT_OPEN_SCOPE;
    502     }
    503 
    504     /* Get the NamePath from the appropriate place */
    505 
    506     if (OpInfo->Flags & AML_NAMED)
    507     {
    508         /* For nearly all NAMED operators, the name reference is the first child */
    509 
    510         Path = Op->Asl.Child->Asl.Value.String;
    511         if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
    512         {
    513             /*
    514              * ALIAS is the only oddball opcode, the name declaration
    515              * (alias name) is the second operand
    516              */
    517             Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
    518         }
    519     }
    520     else if (OpInfo->Flags & AML_CREATE)
    521     {
    522         /* Name must appear as the last parameter */
    523 
    524         NextOp = Op->Asl.Child;
    525         while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
    526         {
    527             NextOp = NextOp->Asl.Next;
    528         }
    529 
    530         Path = NextOp->Asl.Value.String;
    531     }
    532     else
    533     {
    534         Path = Op->Asl.Value.String;
    535     }
    536 
    537     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
    538     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    539         "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
    540 
    541     /*
    542      * Lookup the name in the namespace. Name must exist at this point, or it
    543      * is an invalid reference.
    544      *
    545      * The namespace is also used as a lookup table for references to resource
    546      * descriptors and the fields within them.
    547      */
    548     AslGbl_NsLookupCount++;
    549 
    550     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
    551         ACPI_IMODE_EXECUTE, Flags, WalkState, &Node);
    552     if (ACPI_FAILURE (Status))
    553     {
    554         if (Status == AE_NOT_FOUND)
    555         {
    556             /*
    557              * We didn't find the name reference by path -- we can qualify this
    558              * a little better before we print an error message
    559              */
    560 
    561             if ((Op->Asl.Parent) &&
    562                 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
    563             {
    564                 /*
    565                  * One special case: CondRefOf operator - if the name doesn't
    566                  * exist at this point, it means that there's no actual or
    567                  * external declaration. If the name is not found, just ignore
    568                  * it, the point of the operator is to determine if the name
    569                  * exists at runtime. We wanted to see if this named object
    570                  * exists to facilitate analysis to allow protected usage of
    571                  * undeclared externals.
    572                  */
    573                 return_ACPI_STATUS (AE_OK);
    574             }
    575             else if (strlen (Path) == ACPI_NAMESEG_SIZE)
    576             {
    577                 /* A simple, one-segment ACPI name */
    578 
    579                 if (XfObjectExists (Path))
    580                 {
    581                     /*
    582                      * There exists such a name, but we couldn't get to it
    583                      * from this scope
    584                      */
    585                     AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
    586                         Op->Asl.ExternalName);
    587                 }
    588                 else
    589                 {
    590                     /* The name doesn't exist, period */
    591 
    592                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
    593                         Op, Op->Asl.ExternalName);
    594                 }
    595             }
    596             else
    597             {
    598                 /* The NamePath contains multiple NameSegs */
    599 
    600                 if ((OpInfo->Flags & AML_CREATE) ||
    601                     (OpInfo->ObjectType == ACPI_TYPE_LOCAL_ALIAS))
    602                 {
    603                     /*
    604                      * The new name is the last parameter. For the
    605                      * CreateXXXXField and Alias operators
    606                      */
    607                     NextOp = Op->Asl.Child;
    608                     while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
    609                     {
    610                         NextOp = NextOp->Asl.Next;
    611                     }
    612 
    613                     AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, NextOp,
    614                         NextOp->Asl.ExternalName);
    615                 }
    616                 else if (OpInfo->Flags & AML_NAMED)
    617                 {
    618                     /* The new name is the first parameter */
    619 
    620                     AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, Op,
    621                         Op->Asl.ExternalName);
    622                 }
    623                 else if (Path[0] == AML_ROOT_PREFIX)
    624                 {
    625                     /* Full namepath from root, the object does not exist */
    626 
    627                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
    628                         Op->Asl.ExternalName);
    629                 }
    630                 else
    631                 {
    632                     /*
    633                      * Generic "not found" error. Cannot determine whether it
    634                      * doesn't exist or just can't be reached. However, we
    635                      * can differentiate between a NameSeg vs. NamePath.
    636                      */
    637                     if (strlen (Op->Asl.ExternalName) == ACPI_NAMESEG_SIZE)
    638                     {
    639                         AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
    640                             Op->Asl.ExternalName);
    641                     }
    642                     else
    643                     {
    644                         AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op,
    645                             Op->Asl.ExternalName);
    646                     }
    647                 }
    648             }
    649 
    650             Status = AE_OK;
    651         }
    652 
    653         return_ACPI_STATUS (Status);
    654     }
    655 
    656     /* Check for an attempt to access an object in another method */
    657 
    658     if (!XfValidateCrossReference (Op, OpInfo, Node))
    659     {
    660         AslError (ASL_ERROR, ASL_MSG_TEMPORARY_OBJECT, Op,
    661             Op->Asl.ExternalName);
    662         return_ACPI_STATUS (Status);
    663     }
    664 
    665    /* Object was found above, check for an illegal forward reference */
    666 
    667     if (Op->Asl.CompileFlags & OP_NOT_FOUND_DURING_LOAD)
    668     {
    669         /*
    670          * During the load phase, this Op was flagged as a possible
    671          * illegal forward reference. In other words, Op is a name path or
    672          * name segment that refers to a named object declared after the
    673          * reference. In this scinario, Node refers to the actual declaration
    674          * and Op is a parse node that references the named object.
    675          *
    676          * Note:
    677          *
    678          * Object references inside of control methods are allowed to
    679          * refer to objects declared outside of control methods.
    680          *
    681          * If the declaration and reference are both contained inside of the
    682          * same method or outside of any method, this is a forward reference
    683          * and should be reported as a compiler error.
    684          */
    685         DeclarationParentMethod = UtGetParentMethodNode (Node);
    686         ReferenceParentMethod = UtGetParentMethodOp (Op);
    687 
    688         /* case 1: declaration and reference are both outside of method */
    689 
    690         if (!ReferenceParentMethod && !DeclarationParentMethod)
    691         {
    692             AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
    693                 Op->Asl.ExternalName);
    694         }
    695 
    696         /* case 2: declaration and reference are both inside of the same method */
    697 
    698         else if (ReferenceParentMethod && DeclarationParentMethod &&
    699             ReferenceParentMethod == DeclarationParentMethod->Op)
    700         {
    701              AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
    702                 Op->Asl.ExternalName);
    703         }
    704     }
    705 
    706     /* Check for a reference vs. name declaration */
    707 
    708     if (!(OpInfo->Flags & AML_NAMED) &&
    709         !(OpInfo->Flags & AML_CREATE))
    710     {
    711         /* This node has been referenced, mark it for reference check */
    712 
    713         Node->Flags |= ANOBJ_IS_REFERENCED;
    714     }
    715 
    716     /*
    717      * Attempt to optimize the NamePath
    718      *
    719      * One special case: CondRefOf operator - not all AML interpreter
    720      * implementations expect optimized namepaths as a parameter to this
    721      * operator. They require relative name paths with prefix operators or
    722      * namepaths starting with the root scope.
    723      *
    724      * Other AML interpreter implementations do not perform the namespace
    725      * search that starts at the current scope and recursively searching the
    726      * parent scope until the root scope. The lack of search is only known to
    727      * occur for the namestring parameter for the CondRefOf operator.
    728      */
    729     if ((Op->Asl.Parent) &&
    730         (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_CONDREFOF))
    731     {
    732         OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
    733     }
    734 
    735     /*
    736      * 1) Dereference an alias (A name reference that is an alias)
    737      *    Aliases are not nested, the alias always points to the final object
    738      */
    739     if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
    740         (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
    741     {
    742         /* This node points back to the original PARSEOP_ALIAS */
    743 
    744         NextOp = Node->Op;
    745 
    746         /* The first child is the alias target op */
    747 
    748         NextOp = NextOp->Asl.Child;
    749 
    750         /* That in turn points back to original target alias node */
    751 
    752         if (NextOp->Asl.Node)
    753         {
    754             Node = NextOp->Asl.Node;
    755         }
    756 
    757         /* Else - forward reference to alias, will be resolved later */
    758     }
    759 
    760     /* 2) Check for a reference to a resource descriptor */
    761 
    762     if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
    763         (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
    764     {
    765         /*
    766          * This was a reference to a field within a resource descriptor.
    767          * Extract the associated field offset (either a bit or byte
    768          * offset depending on the field type) and change the named
    769          * reference into an integer for AML code generation
    770          */
    771         Offset = Node->Value;
    772         TagBitLength = Node->Length;
    773 
    774         /*
    775          * If a field is being created, generate the length (in bits) of
    776          * the field. Note: Opcodes other than CreateXxxField and Index
    777          * can come through here. For other opcodes, we just need to
    778          * convert the resource tag reference to an integer offset.
    779          */
    780         switch (Op->Asl.Parent->Asl.AmlOpcode)
    781         {
    782         case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
    783             /*
    784              * We know the length operand is an integer constant because
    785              * we know that it contains a reference to a resource
    786              * descriptor tag.
    787              */
    788             FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
    789             break;
    790 
    791         case AML_CREATE_BIT_FIELD_OP:
    792 
    793             FieldBitLength = 1;
    794             break;
    795 
    796         case AML_CREATE_BYTE_FIELD_OP:
    797         case AML_INDEX_OP:
    798 
    799             FieldBitLength = 8;
    800             break;
    801 
    802         case AML_CREATE_WORD_FIELD_OP:
    803 
    804             FieldBitLength = 16;
    805             break;
    806 
    807         case AML_CREATE_DWORD_FIELD_OP:
    808 
    809             FieldBitLength = 32;
    810             break;
    811 
    812         case AML_CREATE_QWORD_FIELD_OP:
    813 
    814             FieldBitLength = 64;
    815             break;
    816 
    817         default:
    818 
    819             FieldBitLength = 0;
    820             break;
    821         }
    822 
    823         /* Check the field length against the length of the resource tag */
    824 
    825         if (FieldBitLength)
    826         {
    827             if (TagBitLength < FieldBitLength)
    828             {
    829                 Message = ASL_MSG_TAG_SMALLER;
    830             }
    831             else if (TagBitLength > FieldBitLength)
    832             {
    833                 Message = ASL_MSG_TAG_LARGER;
    834             }
    835 
    836             if (Message)
    837             {
    838                 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
    839                     "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
    840                     TagBitLength, (TagBitLength > 1) ? "s" : "",
    841                     FieldBitLength, (FieldBitLength > 1) ? "s" : "");
    842 
    843                 AslError (ASL_WARNING, Message, Op, AslGbl_MsgBuffer);
    844             }
    845         }
    846 
    847         /* Convert the BitOffset to a ByteOffset for certain opcodes */
    848 
    849         switch (Op->Asl.Parent->Asl.AmlOpcode)
    850         {
    851         case AML_CREATE_BYTE_FIELD_OP:
    852         case AML_CREATE_WORD_FIELD_OP:
    853         case AML_CREATE_DWORD_FIELD_OP:
    854         case AML_CREATE_QWORD_FIELD_OP:
    855         case AML_INDEX_OP:
    856 
    857             Offset = ACPI_DIV_8 (Offset);
    858             break;
    859 
    860         default:
    861 
    862             break;
    863         }
    864 
    865         /* Now convert this node to an integer whose value is the field offset */
    866 
    867         Op->Asl.AmlLength = 0;
    868         Op->Asl.ParseOpcode = PARSEOP_INTEGER;
    869         Op->Asl.Value.Integer = (UINT64) Offset;
    870         Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD;
    871 
    872         OpcGenerateAmlOpcode (Op);
    873     }
    874 
    875     /* 3) Check for a method invocation */
    876 
    877     else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
    878                 (Node->Type == ACPI_TYPE_METHOD) &&
    879                 (Op->Asl.Parent) &&
    880                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||
    881 
    882                 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
    883     {
    884         /*
    885          * A reference to a method within one of these opcodes is not an
    886          * invocation of the method, it is simply a reference to the method.
    887          *
    888          * September 2016: Removed DeRefOf from this list
    889          * July 2020: Added Alias to this list
    890          */
    891         if ((Op->Asl.Parent) &&
    892             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF)     ||
    893             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE)    ||
    894             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)||
    895             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE) ||
    896             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_ALIAS)))
    897         {
    898             return_ACPI_STATUS (AE_OK);
    899         }
    900 
    901         /*
    902          * There are two types of method invocation:
    903          * 1) Invocation with arguments -- the parser recognizes this
    904          *    as a METHODCALL.
    905          * 2) Invocation with no arguments --the parser cannot determine that
    906          *    this is a method invocation, therefore we have to figure it out
    907          *    here.
    908          */
    909         if (Node->Type != ACPI_TYPE_METHOD)
    910         {
    911             snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s is a %s",
    912                 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
    913 
    914             AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, AslGbl_MsgBuffer);
    915             return_ACPI_STATUS (AE_OK);
    916         }
    917 
    918         /* Save the method node in the caller's op */
    919 
    920         Op->Asl.Node = Node;
    921         if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
    922         {
    923             return_ACPI_STATUS (AE_OK);
    924         }
    925 
    926         /*
    927          * This is a method invocation, with or without arguments.
    928          * Count the number of arguments, each appears as a child
    929          * under the parent node
    930          */
    931         Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
    932         UtSetParseOpName (Op);
    933 
    934         PassedArgs = 0;
    935         NextOp = Op->Asl.Child;
    936 
    937         while (NextOp)
    938         {
    939             PassedArgs++;
    940             NextOp = NextOp->Asl.Next;
    941         }
    942 
    943         if (Node->Value != ASL_EXTERNAL_METHOD_UNKNOWN_PARAMS &&
    944             Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL)
    945         {
    946             /*
    947              * Check the parsed arguments with the number expected by the
    948              * method declaration itself
    949              */
    950             if (PassedArgs != Node->Value)
    951             {
    952                 if (Node->Flags & ANOBJ_IS_EXTERNAL)
    953                 {
    954                     snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
    955                         "according to previous use, %s requires %u",
    956                         Op->Asl.ExternalName, Node->Value);
    957                 }
    958                 else
    959                 {
    960                     snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
    961 			"%s requires %u", Op->Asl.ExternalName,
    962                         Node->Value);
    963                 }
    964 
    965                 if (PassedArgs < Node->Value)
    966                 {
    967                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, AslGbl_MsgBuffer);
    968                 }
    969                 else
    970                 {
    971                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, AslGbl_MsgBuffer);
    972                 }
    973             }
    974         }
    975 
    976         /*
    977          * At this point, a method call to an external method has been
    978          * detected. As of 11/19/2019, iASL does not support parameter counts
    979          * for methods declared as external. Therefore, save the parameter
    980          * count of the first method call and use this count check other
    981          * method calls to ensure that the methods are being called with the
    982          * same amount of parameters.
    983          */
    984         else if (Node->Type == ACPI_TYPE_METHOD &&
    985             (Node->Flags & ANOBJ_IS_EXTERNAL) &&
    986             Node->Value == ASL_EXTERNAL_METHOD_UNKNOWN_PARAMS &&
    987             Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL)
    988         {
    989             Node->Value = PassedArgs;
    990         }
    991     }
    992 
    993     /* 4) Check for an ASL Field definition */
    994 
    995     else if ((Op->Asl.Parent) &&
    996             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
    997              (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
    998     {
    999         /*
   1000          * Offset checking for fields. If the parent operation region has a
   1001          * constant length (known at compile time), we can check fields
   1002          * defined in that region against the region length. This will catch
   1003          * fields and field units that cannot possibly fit within the region.
   1004          *
   1005          * Note: Index fields do not directly reference an operation region,
   1006          * thus they are not included in this check.
   1007          */
   1008         if (Op == Op->Asl.Parent->Asl.Child)
   1009         {
   1010             /*
   1011              * This is the first child of the field node, which is
   1012              * the name of the region. Get the parse node for the
   1013              * region -- which contains the length of the region.
   1014              */
   1015             OwningOp = Node->Op;
   1016             Op->Asl.Parent->Asl.ExtraValue =
   1017                 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
   1018 
   1019             /* Examine the field access width */
   1020 
   1021             switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
   1022             {
   1023             case AML_FIELD_ACCESS_ANY:
   1024             case AML_FIELD_ACCESS_BYTE:
   1025             case AML_FIELD_ACCESS_BUFFER:
   1026             default:
   1027 
   1028                 MinimumLength = 1;
   1029                 break;
   1030 
   1031             case AML_FIELD_ACCESS_WORD:
   1032 
   1033                 MinimumLength = 2;
   1034                 break;
   1035 
   1036             case AML_FIELD_ACCESS_DWORD:
   1037 
   1038                 MinimumLength = 4;
   1039                 break;
   1040 
   1041             case AML_FIELD_ACCESS_QWORD:
   1042 
   1043                 MinimumLength = 8;
   1044                 break;
   1045             }
   1046 
   1047             /*
   1048              * Is the region at least as big as the access width?
   1049              * Note: DataTableRegions have 0 length
   1050              */
   1051             if (((UINT32) OwningOp->Asl.Value.Integer) &&
   1052                 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
   1053             {
   1054                 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
   1055             }
   1056 
   1057             /*
   1058              * Check EC/CMOS/SMBUS fields to make sure that the correct
   1059              * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
   1060              */
   1061             SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
   1062             switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
   1063             {
   1064             case ACPI_ADR_SPACE_EC:
   1065             case ACPI_ADR_SPACE_CMOS:
   1066             case ACPI_ADR_SPACE_GPIO:
   1067 
   1068                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
   1069                     AML_FIELD_ACCESS_BYTE)
   1070                 {
   1071                     AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
   1072                 }
   1073                 break;
   1074 
   1075             case ACPI_ADR_SPACE_SMBUS:
   1076             case ACPI_ADR_SPACE_IPMI:
   1077             case ACPI_ADR_SPACE_GSBUS:
   1078 
   1079                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
   1080                     AML_FIELD_ACCESS_BUFFER)
   1081                 {
   1082                     AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
   1083                 }
   1084                 break;
   1085 
   1086             default:
   1087 
   1088                 /* Nothing to do for other address spaces */
   1089 
   1090                 break;
   1091             }
   1092         }
   1093         else
   1094         {
   1095             /*
   1096              * This is one element of the field list. Check to make sure
   1097              * that it does not go beyond the end of the parent operation region.
   1098              *
   1099              * In the code below:
   1100              *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
   1101              *    Op->Asl.ExtraValue                  - Field start offset (bits)
   1102              *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
   1103              *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
   1104              */
   1105             if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
   1106             {
   1107                 XfCheckFieldRange (Op,
   1108                     Op->Asl.Parent->Asl.ExtraValue,
   1109                     Op->Asl.ExtraValue,
   1110                     (UINT32) Op->Asl.Child->Asl.Value.Integer,
   1111                     Op->Asl.Child->Asl.ExtraValue);
   1112             }
   1113         }
   1114     }
   1115 
   1116     /*
   1117      * 5) Check for external resolution
   1118      *
   1119      * By this point, everything should be loaded in the namespace. If a
   1120      * namespace lookup results in a namespace node that is an external, it
   1121      * means that this named object was not defined in the input ASL. This
   1122      * causes issues because there are plenty of incidents where developers
   1123      * use the external keyword to suppress compiler errors about undefined
   1124      * objects. Note: this only applies when compiling multiple definition
   1125      * blocks.
   1126      *
   1127      * Do not check for external resolution in the following cases:
   1128      *
   1129      * case 1) External (ABCD)
   1130      *
   1131      *         This declares ABCD as an external so there is no requirement for
   1132      *         ABCD to be loaded in the namespace when analyzing the actual
   1133      *         External() statement.
   1134      *
   1135      * case 2) CondRefOf (ABCD)
   1136      *
   1137      *         This operator will query the ACPI namespace on the existence of
   1138      *         ABCD. If ABCD does not exist, this operator will return a 0
   1139      *         without incurring AML runtime errors. Therefore, ABCD is allowed
   1140      *         to not exist when analyzing the CondRefOf operator.
   1141      *
   1142      * case 3) External (ABCD)
   1143      *         if (CondRefOf (ABCD))
   1144      *         {
   1145      *             Store (0, ABCD)
   1146      *         }
   1147      *
   1148      *         In this case, ABCD is accessed only if it exists due to the if
   1149      *         statement so there is no need to flag the ABCD nested in the
   1150      *         store operator.
   1151      */
   1152     if (AslGbl_ParseTreeRoot->Asl.Child && AslGbl_ParseTreeRoot->Asl.Child->Asl.Next &&
   1153         (Node->Flags & ANOBJ_IS_EXTERNAL) &&
   1154         Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL &&
   1155         Op->Asl.ParseOpcode != PARSEOP_EXTERNAL &&
   1156         Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_CONDREFOF &&
   1157         !XfRefIsGuardedByIfCondRefOf (Node, Op))
   1158     {
   1159         AslError (ASL_ERROR, ASL_MSG_UNDEFINED_EXTERNAL, Op, NULL);
   1160     }
   1161 
   1162     /* 5) Check for a connection object */
   1163 #if 0
   1164     else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
   1165     {
   1166         return_ACPI_STATUS (Status);
   1167     }
   1168 #endif
   1169 
   1170     Op->Asl.Node = Node;
   1171     return_ACPI_STATUS (Status);
   1172 }
   1173 
   1174 
   1175 /*******************************************************************************
   1176  *
   1177  * FUNCTION:    XfRefIsGuardedByIfCondRefOf
   1178  *
   1179  * PARAMETERS:  Node        - Named object reference node
   1180  *              Op          - Named object reference parse node
   1181  *
   1182  * RETURN:      BOOLEAN
   1183  *
   1184  * DESCRIPTION: returns true if Op checked inside if (CondRefOf (...))
   1185  *              refers to Node.
   1186  *
   1187  ******************************************************************************/
   1188 
   1189 static BOOLEAN
   1190 XfRefIsGuardedByIfCondRefOf (
   1191     ACPI_NAMESPACE_NODE     *Node,
   1192     ACPI_PARSE_OBJECT       *Op)
   1193 {
   1194     ACPI_PARSE_OBJECT       *Parent = Op->Asl.Parent;
   1195 
   1196 
   1197     while (Parent)
   1198     {
   1199         if (Parent->Asl.ParseOpcode == PARSEOP_IF &&
   1200             XfFindCondRefOfName (Node, Parent->Asl.Child))
   1201         {
   1202             return (TRUE);
   1203         }
   1204 
   1205         Parent = Parent->Asl.Parent;
   1206     }
   1207 
   1208     return (FALSE);
   1209 }
   1210 
   1211 
   1212 /*******************************************************************************
   1213  *
   1214  * FUNCTION:    XfRefIsGuardedByIfCondRefOf
   1215  *
   1216  * PARAMETERS:  Node        - Named object reference node
   1217  *              Op          - Named object reference parse node
   1218  *
   1219  * RETURN:      BOOLEAN
   1220  *
   1221  * DESCRIPTION: returns true if Op checked inside if (CondRefOf (...))
   1222  *              refers to Node.
   1223  *
   1224  ******************************************************************************/
   1225 
   1226 static BOOLEAN
   1227 XfFindCondRefOfName (
   1228     ACPI_NAMESPACE_NODE     *Node,
   1229     ACPI_PARSE_OBJECT       *Op)
   1230 {
   1231     BOOLEAN                 CondRefOfFound = FALSE;
   1232 
   1233 
   1234     if (!Op)
   1235     {
   1236         return (FALSE);
   1237     }
   1238 
   1239     switch (Op->Asl.ParseOpcode)
   1240     {
   1241     case PARSEOP_CONDREFOF:
   1242 
   1243         return (Op->Asl.Child->Common.Node == Node);
   1244         break;
   1245 
   1246     case PARSEOP_LAND:
   1247 
   1248         CondRefOfFound = XfFindCondRefOfName (Node, Op->Asl.Child);
   1249         if (CondRefOfFound)
   1250         {
   1251             return (TRUE);
   1252         }
   1253 
   1254         return (XfFindCondRefOfName (Node, Op->Asl.Child->Asl.Next));
   1255         break;
   1256 
   1257     default:
   1258 
   1259         return (FALSE);
   1260         break;
   1261     }
   1262 }
   1263 
   1264 
   1265 /*******************************************************************************
   1266  *
   1267  * FUNCTION:    XfNamespaceLocateEnd
   1268  *
   1269  * PARAMETERS:  ASL_WALK_CALLBACK
   1270  *
   1271  * RETURN:      Status
   1272  *
   1273  * DESCRIPTION: Ascending callback used during cross reference. We only
   1274  *              need to worry about scope management here.
   1275  *
   1276  ******************************************************************************/
   1277 
   1278 static ACPI_STATUS
   1279 XfNamespaceLocateEnd (
   1280     ACPI_PARSE_OBJECT       *Op,
   1281     UINT32                  Level,
   1282     void                    *Context)
   1283 {
   1284     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
   1285     const ACPI_OPCODE_INFO  *OpInfo;
   1286 
   1287 
   1288     ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd);
   1289 
   1290 
   1291     /* We are only interested in opcodes that have an associated name */
   1292 
   1293     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
   1294     if (!(OpInfo->Flags & AML_NAMED))
   1295     {
   1296         return_ACPI_STATUS (AE_OK);
   1297     }
   1298 
   1299     /* Not interested in name references, we did not open a scope for them */
   1300 
   1301     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
   1302         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
   1303         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
   1304         (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
   1305     {
   1306         return_ACPI_STATUS (AE_OK);
   1307     }
   1308 
   1309     /* Pop the scope stack if necessary */
   1310 
   1311     if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
   1312     {
   1313 
   1314         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
   1315             "%s: Popping scope for Op %p\n",
   1316             AcpiUtGetTypeName (OpInfo->ObjectType), Op));
   1317 
   1318         (void) AcpiDsScopeStackPop (WalkState);
   1319     }
   1320 
   1321     return_ACPI_STATUS (AE_OK);
   1322 }
   1323 
   1324 
   1325 /*******************************************************************************
   1326  *
   1327  * FUNCTION:    XfValidateCrossReference
   1328  *
   1329  * PARAMETERS:  Op                      - Parse Op that references the object
   1330  *              OpInfo                  - Parse Op info struct
   1331  *              Node                    - Node for the referenced object
   1332  *
   1333  * RETURN:      TRUE if the reference is legal, FALSE otherwise
   1334  *
   1335  * DESCRIPTION: Determine if a reference to another object is allowed.
   1336  *
   1337  * EXAMPLE:
   1338  *      Method (A) {Name (INT1, 1)}     Declaration of object INT1
   1339  *      Method (B) (Store (2, \A.INT1)} Illegal reference to object INT1
   1340  *                                      (INT1 is temporary, valid only during
   1341  *                                      execution of A)
   1342  *
   1343  * NOTES:
   1344  *      A null pointer returned by either UtGetParentMethodOp or
   1345  *      UtGetParentMethodNode indicates that the parameter object is not
   1346  *      within a control method.
   1347  *
   1348  *      Five cases are handled: Case(Op, Node)
   1349  *      1) Case(0,0): Op is not within a method, Node is not    --> OK
   1350  *      2) Case(0,1): Op is not within a method, but Node is    --> Illegal
   1351  *      3) Case(1,0): Op is within a method, Node is not        --> OK
   1352  *      4) Case(1,1): Both are within the same method           --> OK
   1353  *      5) Case(1,1): Both are in methods, but not same method  --> Illegal
   1354  *
   1355  ******************************************************************************/
   1356 
   1357 static BOOLEAN
   1358 XfValidateCrossReference (
   1359     ACPI_PARSE_OBJECT       *Op,
   1360     const ACPI_OPCODE_INFO  *OpInfo,
   1361     ACPI_NAMESPACE_NODE     *Node)
   1362 {
   1363     ACPI_PARSE_OBJECT       *ReferencingMethodOp;
   1364     ACPI_NAMESPACE_NODE     *ReferencedMethodNode;
   1365 
   1366 
   1367     /* Ignore actual named (and related) object declarations */
   1368 
   1369     if (OpInfo->Flags & (AML_NAMED | AML_CREATE | AML_DEFER | AML_HAS_ARGS))
   1370     {
   1371         return (TRUE);
   1372     }
   1373 
   1374     /*
   1375      * 1) Search upwards in parse tree for owner of the referencing object
   1376      * 2) Search upwards in namespace to find the owner of the referenced object
   1377      */
   1378     ReferencingMethodOp = UtGetParentMethodOp (Op);
   1379     ReferencedMethodNode = UtGetParentMethodNode (Node);
   1380 
   1381     if (!ReferencingMethodOp && !ReferencedMethodNode)
   1382     {
   1383         /*
   1384          * 1) Case (0,0): Both Op and Node are not within methods
   1385          * --> OK
   1386          */
   1387         return (TRUE);
   1388     }
   1389 
   1390     if (!ReferencingMethodOp && ReferencedMethodNode)
   1391     {
   1392         /*
   1393          * 2) Case (0,1): Op is not in a method, but Node is within a
   1394          * method --> illegal
   1395          */
   1396         return (FALSE);
   1397     }
   1398     else if (ReferencingMethodOp && !ReferencedMethodNode)
   1399     {
   1400         /*
   1401          * 3) Case (1,0): Op is within a method, but Node is not
   1402          * --> OK
   1403          */
   1404         return (TRUE);
   1405     }
   1406     else if (ReferencingMethodOp->Asl.Node == ReferencedMethodNode)
   1407     {
   1408         /*
   1409          * 4) Case (1,1): Both Op and Node are within the same method
   1410          * --> OK
   1411          */
   1412         return (TRUE);
   1413     }
   1414     else
   1415     {
   1416         /*
   1417          * 5) Case (1,1), Op and Node are in different methods
   1418          * --> Illegal
   1419          */
   1420         return (FALSE);
   1421     }
   1422 }
   1423