Home | History | Annotate | Line # | Download | only in compiler
aslxref.c revision 1.13
      1 /******************************************************************************
      2  *
      3  * Module Name: aslxref - Namespace cross-reference
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2018, 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 ACPI_PARSE_OBJECT *
     70 XfGetParentMethod (
     71     ACPI_PARSE_OBJECT       *Op);
     72 
     73 static BOOLEAN
     74 XfObjectExists (
     75     char                    *Name);
     76 
     77 static ACPI_STATUS
     78 XfCompareOneNamespaceObject (
     79     ACPI_HANDLE             ObjHandle,
     80     UINT32                  Level,
     81     void                    *Context,
     82     void                    **ReturnValue);
     83 
     84 static void
     85 XfCheckFieldRange (
     86     ACPI_PARSE_OBJECT       *Op,
     87     UINT32                  RegionBitLength,
     88     UINT32                  FieldBitOffset,
     89     UINT32                  FieldBitLength,
     90     UINT32                  AccessBitWidth);
     91 
     92 
     93 /*******************************************************************************
     94  *
     95  * FUNCTION:    XfCrossReferenceNamespace
     96  *
     97  * PARAMETERS:  None
     98  *
     99  * RETURN:      Status
    100  *
    101  * DESCRIPTION: Perform a cross reference check of the parse tree against the
    102  *              namespace. Every named referenced within the parse tree
    103  *              should be get resolved with a namespace lookup. If not, the
    104  *              original reference in the ASL code is invalid -- i.e., refers
    105  *              to a non-existent object.
    106  *
    107  * NOTE:  The ASL "External" operator causes the name to be inserted into the
    108  *        namespace so that references to the external name will be resolved
    109  *        correctly here.
    110  *
    111  ******************************************************************************/
    112 
    113 ACPI_STATUS
    114 XfCrossReferenceNamespace (
    115     void)
    116 {
    117     ACPI_WALK_STATE         *WalkState;
    118 
    119 
    120     /*
    121      * Create a new walk state for use when looking up names
    122      * within the namespace (Passed as context to the callbacks)
    123      */
    124     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
    125     if (!WalkState)
    126     {
    127         return (AE_NO_MEMORY);
    128     }
    129 
    130     /* Walk the entire parse tree */
    131 
    132     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
    133         XfNamespaceLocateBegin, XfNamespaceLocateEnd, WalkState);
    134 
    135     ACPI_FREE (WalkState);
    136     return (AE_OK);
    137 }
    138 
    139 
    140 /*******************************************************************************
    141  *
    142  * FUNCTION:    XfObjectExists
    143  *
    144  * PARAMETERS:  Name            - 4 char ACPI name
    145  *
    146  * RETURN:      TRUE if name exists in namespace
    147  *
    148  * DESCRIPTION: Walk the namespace to find an object
    149  *
    150  ******************************************************************************/
    151 
    152 static BOOLEAN
    153 XfObjectExists (
    154     char                    *Name)
    155 {
    156     ACPI_STATUS             Status;
    157 
    158 
    159     /* Walk entire namespace from the supplied root */
    160 
    161     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
    162         ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL,
    163         Name, NULL);
    164     if (Status == AE_CTRL_TRUE)
    165     {
    166         /* At least one instance of the name was found */
    167 
    168         return (TRUE);
    169     }
    170 
    171     return (FALSE);
    172 }
    173 
    174 
    175 /*******************************************************************************
    176  *
    177  * FUNCTION:    XfCompareOneNamespaceObject
    178  *
    179  * PARAMETERS:  ACPI_WALK_CALLBACK
    180  *
    181  * RETURN:      Status
    182  *
    183  * DESCRIPTION: Compare name of one object.
    184  *
    185  ******************************************************************************/
    186 
    187 static ACPI_STATUS
    188 XfCompareOneNamespaceObject (
    189     ACPI_HANDLE             ObjHandle,
    190     UINT32                  Level,
    191     void                    *Context,
    192     void                    **ReturnValue)
    193 {
    194     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    195 
    196 
    197     /* Simply check the name */
    198 
    199     if (*((UINT32 *) (Context)) == Node->Name.Integer)
    200     {
    201         /* Abort walk if we found one instance */
    202 
    203         return (AE_CTRL_TRUE);
    204     }
    205 
    206     return (AE_OK);
    207 }
    208 
    209 
    210 /*******************************************************************************
    211  *
    212  * FUNCTION:    XfCheckFieldRange
    213  *
    214  * PARAMETERS:  RegionBitLength     - Length of entire parent region
    215  *              FieldBitOffset      - Start of the field unit (within region)
    216  *              FieldBitLength      - Entire length of field unit
    217  *              AccessBitWidth      - Access width of the field unit
    218  *
    219  * RETURN:      None
    220  *
    221  * DESCRIPTION: Check one field unit to make sure it fits in the parent
    222  *              op region.
    223  *
    224  * Note: AccessBitWidth must be either 8,16,32, or 64
    225  *
    226  ******************************************************************************/
    227 
    228 static void
    229 XfCheckFieldRange (
    230     ACPI_PARSE_OBJECT       *Op,
    231     UINT32                  RegionBitLength,
    232     UINT32                  FieldBitOffset,
    233     UINT32                  FieldBitLength,
    234     UINT32                  AccessBitWidth)
    235 {
    236     UINT32                  FieldEndBitOffset;
    237 
    238 
    239     /*
    240      * Check each field unit against the region size. The entire
    241      * field unit (start offset plus length) must fit within the
    242      * region.
    243      */
    244     FieldEndBitOffset = FieldBitOffset + FieldBitLength;
    245 
    246     if (FieldEndBitOffset > RegionBitLength)
    247     {
    248         /* Field definition itself is beyond the end-of-region */
    249 
    250         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
    251         return;
    252     }
    253 
    254     /*
    255      * Now check that the field plus AccessWidth doesn't go beyond
    256      * the end-of-region. Assumes AccessBitWidth is a power of 2
    257      */
    258     FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
    259 
    260     if (FieldEndBitOffset > RegionBitLength)
    261     {
    262         /* Field definition combined with the access is beyond EOR */
    263 
    264         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
    265     }
    266 }
    267 
    268 
    269 /*******************************************************************************
    270  *
    271  * FUNCTION:    XfGetParentMethod
    272  *
    273  * PARAMETERS:  Op                      - Parse Op to be checked
    274  *
    275  * RETURN:      Control method Op if found. NULL otherwise
    276  *
    277  * DESCRIPTION: Find the control method parent of a parse op. Returns NULL if
    278  *              the input Op is not within a control method.
    279  *
    280  ******************************************************************************/
    281 
    282 static ACPI_PARSE_OBJECT *
    283 XfGetParentMethod (
    284     ACPI_PARSE_OBJECT       *Op)
    285 {
    286     ACPI_PARSE_OBJECT       *NextOp;
    287 
    288 
    289     NextOp = Op->Asl.Parent;
    290     while (NextOp)
    291     {
    292         if (NextOp->Asl.AmlOpcode == AML_METHOD_OP)
    293         {
    294             return (NextOp);
    295         }
    296 
    297         NextOp = NextOp->Asl.Parent;
    298     }
    299 
    300     return (NULL); /* No parent method found */
    301 }
    302 
    303 /*******************************************************************************
    304  *
    305  * FUNCTION:    XfNamespaceLocateBegin
    306  *
    307  * PARAMETERS:  ASL_WALK_CALLBACK
    308  *
    309  * RETURN:      Status
    310  *
    311  * DESCRIPTION: Descending callback used during cross-reference. For named
    312  *              object references, attempt to locate the name in the
    313  *              namespace.
    314  *
    315  * NOTE: ASL references to named fields within resource descriptors are
    316  *       resolved to integer values here. Therefore, this step is an
    317  *       important part of the code generation. We don't know that the
    318  *       name refers to a resource descriptor until now.
    319  *
    320  ******************************************************************************/
    321 
    322 static ACPI_STATUS
    323 XfNamespaceLocateBegin (
    324     ACPI_PARSE_OBJECT       *Op,
    325     UINT32                  Level,
    326     void                    *Context)
    327 {
    328     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
    329     ACPI_NAMESPACE_NODE     *Node;
    330     ACPI_STATUS             Status;
    331     ACPI_OBJECT_TYPE        ObjectType;
    332     char                    *Path;
    333     UINT8                   PassedArgs;
    334     ACPI_PARSE_OBJECT       *NextOp;
    335     ACPI_PARSE_OBJECT       *OwningOp;
    336     ACPI_PARSE_OBJECT       *SpaceIdOp;
    337     UINT32                  MinimumLength;
    338     UINT32                  Offset;
    339     UINT32                  FieldBitLength;
    340     UINT32                  TagBitLength;
    341     UINT8                   Message = 0;
    342     const ACPI_OPCODE_INFO  *OpInfo;
    343     UINT32                  Flags;
    344     ASL_METHOD_LOCAL        *MethodLocals = NULL;
    345     ASL_METHOD_LOCAL        *MethodArgs = NULL;
    346     int                     RegisterNumber;
    347     UINT32                  i;
    348 
    349 
    350     ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);
    351 
    352 
    353     if ((Op->Asl.AmlOpcode == AML_METHOD_OP) && Op->Asl.Node)
    354     {
    355         Node = Op->Asl.Node;
    356 
    357         /* Support for method LocalX/ArgX analysis */
    358 
    359         if (!Node->MethodLocals)
    360         {
    361             /* Create local/arg info blocks */
    362 
    363             MethodLocals = UtLocalCalloc (
    364                 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS);
    365             Node->MethodLocals = MethodLocals;
    366 
    367             MethodArgs = UtLocalCalloc (
    368                 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS);
    369             Node->MethodArgs = MethodArgs;
    370 
    371             /*
    372              * Get the method argument count
    373              * First, get the name node
    374              */
    375             NextOp = Op->Asl.Child;
    376 
    377             /* Get the NumArguments node */
    378 
    379             NextOp = NextOp->Asl.Next;
    380             Node->ArgCount = (UINT8)
    381                 (((UINT8) NextOp->Asl.Value.Integer) & 0x07);
    382 
    383             /* We will track all posible ArgXs */
    384 
    385             for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
    386             {
    387                 if (i < Node->ArgCount)
    388                 {
    389                     /* Real Args are always "initialized" */
    390 
    391                     MethodArgs[i].Flags = ASL_ARG_INITIALIZED;
    392                 }
    393                 else
    394                 {
    395                     /* Other ArgXs can be used as locals */
    396 
    397                     MethodArgs[i].Flags = ASL_ARG_IS_LOCAL;
    398                 }
    399 
    400                 MethodArgs[i].Op = Op;
    401             }
    402         }
    403     }
    404 
    405     /*
    406      * If this node is the actual declaration of a name
    407      * [such as the XXXX name in "Method (XXXX)"],
    408      * we are not interested in it here. We only care about names that are
    409      * references to other objects within the namespace and the parent objects
    410      * of name declarations
    411      */
    412     if (Op->Asl.CompileFlags & OP_IS_NAME_DECLARATION)
    413     {
    414         return_ACPI_STATUS (AE_OK);
    415     }
    416 
    417     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    418 
    419     /* Check method LocalX variables */
    420 
    421     if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE)
    422     {
    423         /* Find parent method Op */
    424 
    425         NextOp = XfGetParentMethod (Op);
    426         if (!NextOp)
    427         {
    428             return_ACPI_STATUS (AE_OK);
    429         }
    430 
    431         /* Get method node */
    432 
    433         Node = NextOp->Asl.Node;
    434 
    435         RegisterNumber = Op->Asl.AmlOpcode & 0x0007; /* 0x60 through 0x67 */
    436         MethodLocals = Node->MethodLocals;
    437 
    438         if (Op->Asl.CompileFlags & OP_IS_TARGET)
    439         {
    440             /* Local is being initialized */
    441 
    442             MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_INITIALIZED;
    443             MethodLocals[RegisterNumber].Op = Op;
    444 
    445             return_ACPI_STATUS (AE_OK);
    446         }
    447 
    448         /* Mark this Local as referenced */
    449 
    450         MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_REFERENCED;
    451         MethodLocals[RegisterNumber].Op = Op;
    452 
    453         return_ACPI_STATUS (AE_OK);
    454     }
    455 
    456     /* Check method ArgX variables */
    457 
    458     if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT)
    459     {
    460         /* Find parent method Op */
    461 
    462         NextOp = XfGetParentMethod (Op);
    463         if (!NextOp)
    464         {
    465             return_ACPI_STATUS (AE_OK);
    466         }
    467 
    468         /* Get method node */
    469 
    470         Node = NextOp->Asl.Node;
    471 
    472         /* Get Arg # */
    473 
    474         RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */
    475         MethodArgs = Node->MethodArgs;
    476 
    477         /* Mark this Arg as referenced */
    478 
    479         MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED;
    480         MethodArgs[RegisterNumber].Op = Op;
    481 
    482         if (Op->Asl.CompileFlags & OP_IS_TARGET)
    483         {
    484             /* Arg is being initialized */
    485 
    486             MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED;
    487         }
    488 
    489         return_ACPI_STATUS (AE_OK);
    490     }
    491 
    492     /*
    493      * After method ArgX and LocalX, we are only interested in opcodes
    494      * that have an associated name
    495      */
    496     if ((!(OpInfo->Flags & AML_NAMED)) &&
    497         (!(OpInfo->Flags & AML_CREATE)) &&
    498         (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
    499         (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
    500         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL) &&
    501         (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL))
    502     {
    503         return_ACPI_STATUS (AE_OK);
    504     }
    505 
    506     /*
    507      * One special case: CondRefOf operator - we don't care if the name exists
    508      * or not at this point, just ignore it, the point of the operator is to
    509      * determine if the name exists at runtime.
    510      */
    511     if ((Op->Asl.Parent) &&
    512         (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
    513     {
    514         return_ACPI_STATUS (AE_OK);
    515     }
    516 
    517     /*
    518      * We must enable the "search-to-root" for single NameSegs, but
    519      * we have to be very careful about opening up scopes
    520      */
    521     Flags = ACPI_NS_SEARCH_PARENT;
    522     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
    523         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
    524         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
    525         (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
    526     {
    527         /*
    528          * These are name references, do not push the scope stack
    529          * for them.
    530          */
    531         Flags |= ACPI_NS_DONT_OPEN_SCOPE;
    532     }
    533 
    534     /* Get the NamePath from the appropriate place */
    535 
    536     if (OpInfo->Flags & AML_NAMED)
    537     {
    538         /* For nearly all NAMED operators, the name reference is the first child */
    539 
    540         Path = Op->Asl.Child->Asl.Value.String;
    541         if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
    542         {
    543             /*
    544              * ALIAS is the only oddball opcode, the name declaration
    545              * (alias name) is the second operand
    546              */
    547             Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
    548         }
    549     }
    550     else if (OpInfo->Flags & AML_CREATE)
    551     {
    552         /* Name must appear as the last parameter */
    553 
    554         NextOp = Op->Asl.Child;
    555         while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
    556         {
    557             NextOp = NextOp->Asl.Next;
    558         }
    559 
    560         Path = NextOp->Asl.Value.String;
    561     }
    562     else
    563     {
    564         Path = Op->Asl.Value.String;
    565     }
    566 
    567     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
    568     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    569         "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
    570 
    571     /*
    572      * Lookup the name in the namespace. Name must exist at this point, or it
    573      * is an invalid reference.
    574      *
    575      * The namespace is also used as a lookup table for references to resource
    576      * descriptors and the fields within them.
    577      */
    578     AslGbl_NsLookupCount++;
    579 
    580     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
    581         ACPI_IMODE_EXECUTE, Flags, WalkState, &Node);
    582     if (ACPI_FAILURE (Status))
    583     {
    584         if (Status == AE_NOT_FOUND)
    585         {
    586             /*
    587              * We didn't find the name reference by path -- we can qualify this
    588              * a little better before we print an error message
    589              */
    590             if (strlen (Path) == ACPI_NAME_SIZE)
    591             {
    592                 /* A simple, one-segment ACPI name */
    593 
    594                 if (XfObjectExists (Path))
    595                 {
    596                     /*
    597                      * There exists such a name, but we couldn't get to it
    598                      * from this scope
    599                      */
    600                     AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
    601                         Op->Asl.ExternalName);
    602                 }
    603                 else
    604                 {
    605                     /* The name doesn't exist, period */
    606 
    607                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
    608                         Op, Op->Asl.ExternalName);
    609                 }
    610             }
    611             else
    612             {
    613                 /* The NamePath contains multiple NameSegs */
    614 
    615                 if ((OpInfo->Flags & AML_CREATE) ||
    616                     (OpInfo->ObjectType == ACPI_TYPE_LOCAL_ALIAS))
    617                 {
    618                     /*
    619                      * The new name is the last parameter. For the
    620                      * CreateXXXXField and Alias operators
    621                      */
    622                     NextOp = Op->Asl.Child;
    623                     while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
    624                     {
    625                         NextOp = NextOp->Asl.Next;
    626                     }
    627 
    628                     AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, NextOp,
    629                         NextOp->Asl.ExternalName);
    630                 }
    631                 else if (OpInfo->Flags & AML_NAMED)
    632                 {
    633                     /* The new name is the first parameter */
    634 
    635                     AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, Op,
    636                         Op->Asl.ExternalName);
    637                 }
    638                 else if (Path[0] == AML_ROOT_PREFIX)
    639                 {
    640                     /* Full namepath from root, the object does not exist */
    641 
    642                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
    643                         Op->Asl.ExternalName);
    644                 }
    645                 else
    646                 {
    647                     /*
    648                      * Generic "not found" error. Cannot determine whether it
    649                      * doesn't exist or just can't be reached. However, we
    650                      * can differentiate between a NameSeg vs. NamePath.
    651                      */
    652                     if (strlen (Op->Asl.ExternalName) == ACPI_NAME_SIZE)
    653                     {
    654                         AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
    655                             Op->Asl.ExternalName);
    656                     }
    657                     else
    658                     {
    659                         AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op,
    660                             Op->Asl.ExternalName);
    661                     }
    662                 }
    663             }
    664 
    665             Status = AE_OK;
    666         }
    667 
    668         return_ACPI_STATUS (Status);
    669     }
    670 
    671     /* Object was found above, check for an illegal forward reference */
    672 
    673     if (Op->Asl.CompileFlags & OP_NOT_FOUND_DURING_LOAD)
    674     {
    675         /*
    676          * During the load phase, this Op was flagged as a possible
    677          * illegal forward reference
    678          *
    679          * Note: Allow "forward references" from within a method to an
    680          * object that is not within any method (module-level code)
    681          */
    682         if (!WalkState->ScopeInfo || (UtGetParentMethod (Node) &&
    683             !UtNodeIsDescendantOf (WalkState->ScopeInfo->Scope.Node,
    684                 UtGetParentMethod (Node))))
    685         {
    686             AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
    687                 Op->Asl.ExternalName);
    688         }
    689     }
    690 
    691     /* Check for a reference vs. name declaration */
    692 
    693     if (!(OpInfo->Flags & AML_NAMED) &&
    694         !(OpInfo->Flags & AML_CREATE))
    695     {
    696         /* This node has been referenced, mark it for reference check */
    697 
    698         Node->Flags |= ANOBJ_IS_REFERENCED;
    699     }
    700 
    701     /* Attempt to optimize the NamePath */
    702 
    703     OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
    704 
    705     /*
    706      * 1) Dereference an alias (A name reference that is an alias)
    707      *    Aliases are not nested, the alias always points to the final object
    708      */
    709     if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
    710         (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
    711     {
    712         /* This node points back to the original PARSEOP_ALIAS */
    713 
    714         NextOp = Node->Op;
    715 
    716         /* The first child is the alias target op */
    717 
    718         NextOp = NextOp->Asl.Child;
    719 
    720         /* That in turn points back to original target alias node */
    721 
    722         if (NextOp->Asl.Node)
    723         {
    724             Node = NextOp->Asl.Node;
    725         }
    726 
    727         /* Else - forward reference to alias, will be resolved later */
    728     }
    729 
    730     /* 2) Check for a reference to a resource descriptor */
    731 
    732     if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
    733         (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
    734     {
    735         /*
    736          * This was a reference to a field within a resource descriptor.
    737          * Extract the associated field offset (either a bit or byte
    738          * offset depending on the field type) and change the named
    739          * reference into an integer for AML code generation
    740          */
    741         Offset = Node->Value;
    742         TagBitLength = Node->Length;
    743 
    744         /*
    745          * If a field is being created, generate the length (in bits) of
    746          * the field. Note: Opcodes other than CreateXxxField and Index
    747          * can come through here. For other opcodes, we just need to
    748          * convert the resource tag reference to an integer offset.
    749          */
    750         switch (Op->Asl.Parent->Asl.AmlOpcode)
    751         {
    752         case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
    753             /*
    754              * We know the length operand is an integer constant because
    755              * we know that it contains a reference to a resource
    756              * descriptor tag.
    757              */
    758             FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
    759             break;
    760 
    761         case AML_CREATE_BIT_FIELD_OP:
    762 
    763             FieldBitLength = 1;
    764             break;
    765 
    766         case AML_CREATE_BYTE_FIELD_OP:
    767         case AML_INDEX_OP:
    768 
    769             FieldBitLength = 8;
    770             break;
    771 
    772         case AML_CREATE_WORD_FIELD_OP:
    773 
    774             FieldBitLength = 16;
    775             break;
    776 
    777         case AML_CREATE_DWORD_FIELD_OP:
    778 
    779             FieldBitLength = 32;
    780             break;
    781 
    782         case AML_CREATE_QWORD_FIELD_OP:
    783 
    784             FieldBitLength = 64;
    785             break;
    786 
    787         default:
    788 
    789             FieldBitLength = 0;
    790             break;
    791         }
    792 
    793         /* Check the field length against the length of the resource tag */
    794 
    795         if (FieldBitLength)
    796         {
    797             if (TagBitLength < FieldBitLength)
    798             {
    799                 Message = ASL_MSG_TAG_SMALLER;
    800             }
    801             else if (TagBitLength > FieldBitLength)
    802             {
    803                 Message = ASL_MSG_TAG_LARGER;
    804             }
    805 
    806             if (Message)
    807             {
    808                 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
    809                     "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
    810                     TagBitLength, (TagBitLength > 1) ? "s" : "",
    811                     FieldBitLength, (FieldBitLength > 1) ? "s" : "");
    812 
    813                 AslError (ASL_WARNING, Message, Op, AslGbl_MsgBuffer);
    814             }
    815         }
    816 
    817         /* Convert the BitOffset to a ByteOffset for certain opcodes */
    818 
    819         switch (Op->Asl.Parent->Asl.AmlOpcode)
    820         {
    821         case AML_CREATE_BYTE_FIELD_OP:
    822         case AML_CREATE_WORD_FIELD_OP:
    823         case AML_CREATE_DWORD_FIELD_OP:
    824         case AML_CREATE_QWORD_FIELD_OP:
    825         case AML_INDEX_OP:
    826 
    827             Offset = ACPI_DIV_8 (Offset);
    828             break;
    829 
    830         default:
    831 
    832             break;
    833         }
    834 
    835         /* Now convert this node to an integer whose value is the field offset */
    836 
    837         Op->Asl.AmlLength = 0;
    838         Op->Asl.ParseOpcode = PARSEOP_INTEGER;
    839         Op->Asl.Value.Integer = (UINT64) Offset;
    840         Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD;
    841 
    842         OpcGenerateAmlOpcode (Op);
    843     }
    844 
    845     /* 3) Check for a method invocation */
    846 
    847     else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
    848                 (Node->Type == ACPI_TYPE_METHOD) &&
    849                 (Op->Asl.Parent) &&
    850                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||
    851 
    852                 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
    853     {
    854         /*
    855          * A reference to a method within one of these opcodes is not an
    856          * invocation of the method, it is simply a reference to the method.
    857          *
    858          * September 2016: Removed DeRefOf from this list
    859          */
    860         if ((Op->Asl.Parent) &&
    861             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF)     ||
    862             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE)    ||
    863             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)||
    864             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
    865         {
    866             return_ACPI_STATUS (AE_OK);
    867         }
    868 
    869         /*
    870          * There are two types of method invocation:
    871          * 1) Invocation with arguments -- the parser recognizes this
    872          *    as a METHODCALL.
    873          * 2) Invocation with no arguments --the parser cannot determine that
    874          *    this is a method invocation, therefore we have to figure it out
    875          *    here.
    876          */
    877         if (Node->Type != ACPI_TYPE_METHOD)
    878         {
    879             snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s is a %s",
    880                 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
    881 
    882             AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, AslGbl_MsgBuffer);
    883             return_ACPI_STATUS (AE_OK);
    884         }
    885 
    886         /* Save the method node in the caller's op */
    887 
    888         Op->Asl.Node = Node;
    889         if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
    890         {
    891             return_ACPI_STATUS (AE_OK);
    892         }
    893 
    894         /*
    895          * This is a method invocation, with or without arguments.
    896          * Count the number of arguments, each appears as a child
    897          * under the parent node
    898          */
    899         Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
    900         UtSetParseOpName (Op);
    901 
    902         PassedArgs = 0;
    903         NextOp = Op->Asl.Child;
    904 
    905         while (NextOp)
    906         {
    907             PassedArgs++;
    908             NextOp = NextOp->Asl.Next;
    909         }
    910 
    911         if (Node->Value != ASL_EXTERNAL_METHOD &&
    912             Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL)
    913         {
    914             /*
    915              * Check the parsed arguments with the number expected by the
    916              * method declaration itself
    917              */
    918             if (PassedArgs != Node->Value)
    919             {
    920                 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s requires %u", Op->Asl.ExternalName,
    921                             Node->Value);
    922 
    923                 if (PassedArgs < Node->Value)
    924                 {
    925                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, AslGbl_MsgBuffer);
    926                 }
    927                 else
    928                 {
    929                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, AslGbl_MsgBuffer);
    930                 }
    931             }
    932         }
    933     }
    934 
    935     /* 4) Check for an ASL Field definition */
    936 
    937     else if ((Op->Asl.Parent) &&
    938             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
    939              (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
    940     {
    941         /*
    942          * Offset checking for fields. If the parent operation region has a
    943          * constant length (known at compile time), we can check fields
    944          * defined in that region against the region length. This will catch
    945          * fields and field units that cannot possibly fit within the region.
    946          *
    947          * Note: Index fields do not directly reference an operation region,
    948          * thus they are not included in this check.
    949          */
    950         if (Op == Op->Asl.Parent->Asl.Child)
    951         {
    952             /*
    953              * This is the first child of the field node, which is
    954              * the name of the region. Get the parse node for the
    955              * region -- which contains the length of the region.
    956              */
    957             OwningOp = Node->Op;
    958             Op->Asl.Parent->Asl.ExtraValue =
    959                 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
    960 
    961             /* Examine the field access width */
    962 
    963             switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
    964             {
    965             case AML_FIELD_ACCESS_ANY:
    966             case AML_FIELD_ACCESS_BYTE:
    967             case AML_FIELD_ACCESS_BUFFER:
    968             default:
    969 
    970                 MinimumLength = 1;
    971                 break;
    972 
    973             case AML_FIELD_ACCESS_WORD:
    974 
    975                 MinimumLength = 2;
    976                 break;
    977 
    978             case AML_FIELD_ACCESS_DWORD:
    979 
    980                 MinimumLength = 4;
    981                 break;
    982 
    983             case AML_FIELD_ACCESS_QWORD:
    984 
    985                 MinimumLength = 8;
    986                 break;
    987             }
    988 
    989             /*
    990              * Is the region at least as big as the access width?
    991              * Note: DataTableRegions have 0 length
    992              */
    993             if (((UINT32) OwningOp->Asl.Value.Integer) &&
    994                 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
    995             {
    996                 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
    997             }
    998 
    999             /*
   1000              * Check EC/CMOS/SMBUS fields to make sure that the correct
   1001              * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
   1002              */
   1003             SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
   1004             switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
   1005             {
   1006             case ACPI_ADR_SPACE_EC:
   1007             case ACPI_ADR_SPACE_CMOS:
   1008             case ACPI_ADR_SPACE_GPIO:
   1009 
   1010                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
   1011                     AML_FIELD_ACCESS_BYTE)
   1012                 {
   1013                     AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
   1014                 }
   1015                 break;
   1016 
   1017             case ACPI_ADR_SPACE_SMBUS:
   1018             case ACPI_ADR_SPACE_IPMI:
   1019             case ACPI_ADR_SPACE_GSBUS:
   1020 
   1021                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
   1022                     AML_FIELD_ACCESS_BUFFER)
   1023                 {
   1024                     AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
   1025                 }
   1026                 break;
   1027 
   1028             default:
   1029 
   1030                 /* Nothing to do for other address spaces */
   1031 
   1032                 break;
   1033             }
   1034         }
   1035         else
   1036         {
   1037             /*
   1038              * This is one element of the field list. Check to make sure
   1039              * that it does not go beyond the end of the parent operation region.
   1040              *
   1041              * In the code below:
   1042              *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
   1043              *    Op->Asl.ExtraValue                  - Field start offset (bits)
   1044              *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
   1045              *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
   1046              */
   1047             if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
   1048             {
   1049                 XfCheckFieldRange (Op,
   1050                     Op->Asl.Parent->Asl.ExtraValue,
   1051                     Op->Asl.ExtraValue,
   1052                     (UINT32) Op->Asl.Child->Asl.Value.Integer,
   1053                     Op->Asl.Child->Asl.ExtraValue);
   1054             }
   1055         }
   1056     }
   1057 
   1058     /* 5) Check for a connection object */
   1059 #if 0
   1060     else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
   1061     {
   1062         return_ACPI_STATUS (Status);
   1063     }
   1064 #endif
   1065 
   1066     Op->Asl.Node = Node;
   1067     return_ACPI_STATUS (Status);
   1068 }
   1069 
   1070 
   1071 /*******************************************************************************
   1072  *
   1073  * FUNCTION:    XfNamespaceLocateEnd
   1074  *
   1075  * PARAMETERS:  ASL_WALK_CALLBACK
   1076  *
   1077  * RETURN:      Status
   1078  *
   1079  * DESCRIPTION: Ascending callback used during cross reference. We only
   1080  *              need to worry about scope management here.
   1081  *
   1082  ******************************************************************************/
   1083 
   1084 static ACPI_STATUS
   1085 XfNamespaceLocateEnd (
   1086     ACPI_PARSE_OBJECT       *Op,
   1087     UINT32                  Level,
   1088     void                    *Context)
   1089 {
   1090     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
   1091     const ACPI_OPCODE_INFO  *OpInfo;
   1092 
   1093 
   1094     ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd);
   1095 
   1096 
   1097     /* We are only interested in opcodes that have an associated name */
   1098 
   1099     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
   1100     if (!(OpInfo->Flags & AML_NAMED))
   1101     {
   1102         return_ACPI_STATUS (AE_OK);
   1103     }
   1104 
   1105     /* Not interested in name references, we did not open a scope for them */
   1106 
   1107     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
   1108         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
   1109         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
   1110         (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
   1111     {
   1112         return_ACPI_STATUS (AE_OK);
   1113     }
   1114 
   1115     /* Pop the scope stack if necessary */
   1116 
   1117     if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
   1118     {
   1119 
   1120         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
   1121             "%s: Popping scope for Op %p\n",
   1122             AcpiUtGetTypeName (OpInfo->ObjectType), Op));
   1123 
   1124         (void) AcpiDsScopeStackPop (WalkState);
   1125     }
   1126 
   1127     return_ACPI_STATUS (AE_OK);
   1128 }
   1129