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