xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslxref.c (revision e6c7e151de239c49d2e38720a061ed9d1fa99309)
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 
95 /*******************************************************************************
96  *
97  * FUNCTION:    XfCrossReferenceNamespace
98  *
99  * PARAMETERS:  None
100  *
101  * RETURN:      Status
102  *
103  * DESCRIPTION: Perform a cross reference check of the parse tree against the
104  *              namespace. Every named referenced within the parse tree
105  *              should be get resolved with a namespace lookup. If not, the
106  *              original reference in the ASL code is invalid -- i.e., refers
107  *              to a non-existent object.
108  *
109  * NOTE:  The ASL "External" operator causes the name to be inserted into the
110  *        namespace so that references to the external name will be resolved
111  *        correctly here.
112  *
113  ******************************************************************************/
114 
115 ACPI_STATUS
116 XfCrossReferenceNamespace (
117     void)
118 {
119     ACPI_WALK_STATE         *WalkState;
120 
121 
122     /*
123      * Create a new walk state for use when looking up names
124      * within the namespace (Passed as context to the callbacks)
125      */
126     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
127     if (!WalkState)
128     {
129         return (AE_NO_MEMORY);
130     }
131 
132     /* Walk the entire parse tree */
133 
134     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
135         XfNamespaceLocateBegin, XfNamespaceLocateEnd, WalkState);
136 
137     ACPI_FREE (WalkState);
138     return (AE_OK);
139 }
140 
141 
142 /*******************************************************************************
143  *
144  * FUNCTION:    XfObjectExists
145  *
146  * PARAMETERS:  Name            - 4 char ACPI name
147  *
148  * RETURN:      TRUE if name exists in namespace
149  *
150  * DESCRIPTION: Walk the namespace to find an object
151  *
152  ******************************************************************************/
153 
154 static BOOLEAN
155 XfObjectExists (
156     char                    *Name)
157 {
158     ACPI_STATUS             Status;
159 
160 
161     /* Walk entire namespace from the supplied root */
162 
163     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
164         ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL,
165         Name, NULL);
166     if (Status == AE_CTRL_TRUE)
167     {
168         /* At least one instance of the name was found */
169 
170         return (TRUE);
171     }
172 
173     return (FALSE);
174 }
175 
176 
177 /*******************************************************************************
178  *
179  * FUNCTION:    XfCompareOneNamespaceObject
180  *
181  * PARAMETERS:  ACPI_WALK_CALLBACK
182  *
183  * RETURN:      Status
184  *
185  * DESCRIPTION: Compare name of one object.
186  *
187  ******************************************************************************/
188 
189 static ACPI_STATUS
190 XfCompareOneNamespaceObject (
191     ACPI_HANDLE             ObjHandle,
192     UINT32                  Level,
193     void                    *Context,
194     void                    **ReturnValue)
195 {
196     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
197 
198 
199     /* Simply check the name */
200 
201     if (*((UINT32 *) (Context)) == Node->Name.Integer)
202     {
203         /* Abort walk if we found one instance */
204 
205         return (AE_CTRL_TRUE);
206     }
207 
208     return (AE_OK);
209 }
210 
211 
212 /*******************************************************************************
213  *
214  * FUNCTION:    XfCheckFieldRange
215  *
216  * PARAMETERS:  RegionBitLength     - Length of entire parent region
217  *              FieldBitOffset      - Start of the field unit (within region)
218  *              FieldBitLength      - Entire length of field unit
219  *              AccessBitWidth      - Access width of the field unit
220  *
221  * RETURN:      None
222  *
223  * DESCRIPTION: Check one field unit to make sure it fits in the parent
224  *              op region.
225  *
226  * Note: AccessBitWidth must be either 8,16,32, or 64
227  *
228  ******************************************************************************/
229 
230 static void
231 XfCheckFieldRange (
232     ACPI_PARSE_OBJECT       *Op,
233     UINT32                  RegionBitLength,
234     UINT32                  FieldBitOffset,
235     UINT32                  FieldBitLength,
236     UINT32                  AccessBitWidth)
237 {
238     UINT32                  FieldEndBitOffset;
239 
240 
241     /*
242      * Check each field unit against the region size. The entire
243      * field unit (start offset plus length) must fit within the
244      * region.
245      */
246     FieldEndBitOffset = FieldBitOffset + FieldBitLength;
247 
248     if (FieldEndBitOffset > RegionBitLength)
249     {
250         /* Field definition itself is beyond the end-of-region */
251 
252         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
253         return;
254     }
255 
256     /*
257      * Now check that the field plus AccessWidth doesn't go beyond
258      * the end-of-region. Assumes AccessBitWidth is a power of 2
259      */
260     FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
261 
262     if (FieldEndBitOffset > RegionBitLength)
263     {
264         /* Field definition combined with the access is beyond EOR */
265 
266         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
267     }
268 }
269 
270 
271 /*******************************************************************************
272  *
273  * FUNCTION:    XfNamespaceLocateBegin
274  *
275  * PARAMETERS:  ASL_WALK_CALLBACK
276  *
277  * RETURN:      Status
278  *
279  * DESCRIPTION: Descending callback used during cross-reference. For named
280  *              object references, attempt to locate the name in the
281  *              namespace.
282  *
283  * NOTE: ASL references to named fields within resource descriptors are
284  *       resolved to integer values here. Therefore, this step is an
285  *       important part of the code generation. We don't know that the
286  *       name refers to a resource descriptor until now.
287  *
288  ******************************************************************************/
289 
290 static ACPI_STATUS
291 XfNamespaceLocateBegin (
292     ACPI_PARSE_OBJECT       *Op,
293     UINT32                  Level,
294     void                    *Context)
295 {
296     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
297     ACPI_NAMESPACE_NODE     *Node;
298     ACPI_STATUS             Status;
299     ACPI_OBJECT_TYPE        ObjectType;
300     char                    *Path;
301     UINT8                   PassedArgs;
302     ACPI_PARSE_OBJECT       *NextOp;
303     ACPI_PARSE_OBJECT       *OwningOp;
304     ACPI_PARSE_OBJECT       *SpaceIdOp;
305     UINT32                  MinimumLength;
306     UINT32                  Offset;
307     UINT32                  FieldBitLength;
308     UINT32                  TagBitLength;
309     UINT8                   Message = 0;
310     const ACPI_OPCODE_INFO  *OpInfo;
311     UINT32                  Flags;
312     ASL_METHOD_LOCAL        *MethodLocals = NULL;
313     ASL_METHOD_LOCAL        *MethodArgs = NULL;
314     int                     RegisterNumber;
315     UINT32                  i;
316     ACPI_NAMESPACE_NODE     *DeclarationParentMethod;
317     ACPI_PARSE_OBJECT       *ReferenceParentMethod;
318 
319 
320     ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);
321 
322 
323     if ((Op->Asl.AmlOpcode == AML_METHOD_OP) && Op->Asl.Node)
324     {
325         Node = Op->Asl.Node;
326 
327         /* Support for method LocalX/ArgX analysis */
328 
329         if (!Node->MethodLocals)
330         {
331             /* Create local/arg info blocks */
332 
333             MethodLocals = UtLocalCalloc (
334                 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS);
335             Node->MethodLocals = MethodLocals;
336 
337             MethodArgs = UtLocalCalloc (
338                 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS);
339             Node->MethodArgs = MethodArgs;
340 
341             /*
342              * Get the method argument count
343              * First, get the name node
344              */
345             NextOp = Op->Asl.Child;
346 
347             /* Get the NumArguments node */
348 
349             NextOp = NextOp->Asl.Next;
350             Node->ArgCount = (UINT8)
351                 (((UINT8) NextOp->Asl.Value.Integer) & 0x07);
352 
353             /* We will track all possible ArgXs */
354 
355             for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
356             {
357                 if (i < Node->ArgCount)
358                 {
359                     /* Real Args are always "initialized" */
360 
361                     MethodArgs[i].Flags = ASL_ARG_INITIALIZED;
362                 }
363                 else
364                 {
365                     /* Other ArgXs can be used as locals */
366 
367                     MethodArgs[i].Flags = ASL_ARG_IS_LOCAL;
368                 }
369 
370                 MethodArgs[i].Op = Op;
371             }
372         }
373     }
374 
375     /*
376      * If this node is the actual declaration of a name
377      * [such as the XXXX name in "Method (XXXX)"],
378      * we are not interested in it here. We only care about names that are
379      * references to other objects within the namespace and the parent objects
380      * of name declarations
381      */
382     if (Op->Asl.CompileFlags & OP_IS_NAME_DECLARATION)
383     {
384         return_ACPI_STATUS (AE_OK);
385     }
386 
387     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
388 
389     /* Check method LocalX variables */
390 
391     if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE)
392     {
393         /* Find parent method Op */
394 
395         NextOp = UtGetParentMethodOp (Op);
396         if (!NextOp)
397         {
398             return_ACPI_STATUS (AE_OK);
399         }
400 
401         /* Get method node */
402 
403         Node = NextOp->Asl.Node;
404 
405         RegisterNumber = Op->Asl.AmlOpcode & 0x0007; /* 0x60 through 0x67 */
406         MethodLocals = Node->MethodLocals;
407 
408         if (Op->Asl.CompileFlags & OP_IS_TARGET)
409         {
410             /* Local is being initialized */
411 
412             MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_INITIALIZED;
413             MethodLocals[RegisterNumber].Op = Op;
414 
415             return_ACPI_STATUS (AE_OK);
416         }
417 
418         /* Mark this Local as referenced */
419 
420         MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_REFERENCED;
421         MethodLocals[RegisterNumber].Op = Op;
422 
423         return_ACPI_STATUS (AE_OK);
424     }
425 
426     /* Check method ArgX variables */
427 
428     if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT)
429     {
430         /* Find parent method Op */
431 
432         NextOp = UtGetParentMethodOp (Op);
433         if (!NextOp)
434         {
435             return_ACPI_STATUS (AE_OK);
436         }
437 
438         /* Get method node */
439 
440         Node = NextOp->Asl.Node;
441 
442         /* Get Arg # */
443 
444         RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */
445         MethodArgs = Node->MethodArgs;
446 
447         /* Mark this Arg as referenced */
448 
449         MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED;
450         MethodArgs[RegisterNumber].Op = Op;
451 
452         if (Op->Asl.CompileFlags & OP_IS_TARGET)
453         {
454             /* Arg is being initialized */
455 
456             MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED;
457         }
458 
459         return_ACPI_STATUS (AE_OK);
460     }
461 
462     /*
463      * After method ArgX and LocalX, we are only interested in opcodes
464      * that have an associated name
465      */
466     if ((!(OpInfo->Flags & AML_NAMED)) &&
467         (!(OpInfo->Flags & AML_CREATE)) &&
468         (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
469         (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
470         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL) &&
471         (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL))
472     {
473         return_ACPI_STATUS (AE_OK);
474     }
475 
476     /*
477      * One special case: CondRefOf operator - we don't care if the name exists
478      * or not at this point, just ignore it, the point of the operator is to
479      * determine if the name exists at runtime.
480      */
481     if ((Op->Asl.Parent) &&
482         (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
483     {
484         return_ACPI_STATUS (AE_OK);
485     }
486 
487     /*
488      * We must enable the "search-to-root" for single NameSegs, but
489      * we have to be very careful about opening up scopes
490      */
491     Flags = ACPI_NS_SEARCH_PARENT;
492     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
493         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
494         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
495         (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
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             if (strlen (Path) == ACPI_NAMESEG_SIZE)
561             {
562                 /* A simple, one-segment ACPI name */
563 
564                 if (XfObjectExists (Path))
565                 {
566                     /*
567                      * There exists such a name, but we couldn't get to it
568                      * from this scope
569                      */
570                     AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
571                         Op->Asl.ExternalName);
572                 }
573                 else
574                 {
575                     /* The name doesn't exist, period */
576 
577                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
578                         Op, Op->Asl.ExternalName);
579                 }
580             }
581             else
582             {
583                 /* The NamePath contains multiple NameSegs */
584 
585                 if ((OpInfo->Flags & AML_CREATE) ||
586                     (OpInfo->ObjectType == ACPI_TYPE_LOCAL_ALIAS))
587                 {
588                     /*
589                      * The new name is the last parameter. For the
590                      * CreateXXXXField and Alias operators
591                      */
592                     NextOp = Op->Asl.Child;
593                     while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
594                     {
595                         NextOp = NextOp->Asl.Next;
596                     }
597 
598                     AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, NextOp,
599                         NextOp->Asl.ExternalName);
600                 }
601                 else if (OpInfo->Flags & AML_NAMED)
602                 {
603                     /* The new name is the first parameter */
604 
605                     AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, Op,
606                         Op->Asl.ExternalName);
607                 }
608                 else if (Path[0] == AML_ROOT_PREFIX)
609                 {
610                     /* Full namepath from root, the object does not exist */
611 
612                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
613                         Op->Asl.ExternalName);
614                 }
615                 else
616                 {
617                     /*
618                      * Generic "not found" error. Cannot determine whether it
619                      * doesn't exist or just can't be reached. However, we
620                      * can differentiate between a NameSeg vs. NamePath.
621                      */
622                     if (strlen (Op->Asl.ExternalName) == ACPI_NAMESEG_SIZE)
623                     {
624                         AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
625                             Op->Asl.ExternalName);
626                     }
627                     else
628                     {
629                         AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op,
630                             Op->Asl.ExternalName);
631                     }
632                 }
633             }
634 
635             Status = AE_OK;
636         }
637 
638         return_ACPI_STATUS (Status);
639     }
640 
641     /* Check for an attempt to access an object in another method */
642 
643     if (!XfValidateCrossReference (Op, OpInfo, Node))
644     {
645         AslError (ASL_ERROR, ASL_MSG_TEMPORARY_OBJECT, Op,
646             Op->Asl.ExternalName);
647         return_ACPI_STATUS (Status);
648     }
649 
650    /* Object was found above, check for an illegal forward reference */
651 
652     if (Op->Asl.CompileFlags & OP_NOT_FOUND_DURING_LOAD)
653     {
654         /*
655          * During the load phase, this Op was flagged as a possible
656          * illegal forward reference. In other words, Op is a name path or
657          * name segment that refers to a named object declared after the
658          * reference. In this scinario, Node refers to the actual declaration
659          * and Op is a parse node that references the named object.
660          *
661          * Note:
662          *
663          * Object references inside of control methods are allowed to
664          * refer to objects declared outside of control methods.
665          *
666          * If the declaration and reference are both contained inside of the
667          * same method or outside of any method, this is a forward reference
668          * and should be reported as a compiler error.
669          */
670         DeclarationParentMethod = UtGetParentMethodNode (Node);
671         ReferenceParentMethod = UtGetParentMethodOp (Op);
672 
673         /* case 1: declaration and reference are both outside of method */
674 
675         if (!ReferenceParentMethod && !DeclarationParentMethod)
676         {
677             AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
678                 Op->Asl.ExternalName);
679         }
680 
681         /* case 2: declaration and reference are both inside of the same method */
682 
683         else if (ReferenceParentMethod && DeclarationParentMethod &&
684             ReferenceParentMethod == DeclarationParentMethod->Op)
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_UNKNOWN_PARAMS &&
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                 if (Node->Flags & ANOBJ_IS_EXTERNAL)
921                 {
922                     snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
923                         "according to previous use, %s requires %u",
924                         Op->Asl.ExternalName, Node->Value);
925                 }
926                 else
927                 {
928                     snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
929 			"%s requires %u", Op->Asl.ExternalName,
930                         Node->Value);
931                 }
932 
933                 if (PassedArgs < Node->Value)
934                 {
935                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, AslGbl_MsgBuffer);
936                 }
937                 else
938                 {
939                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, AslGbl_MsgBuffer);
940                 }
941             }
942         }
943 
944         /*
945          * At this point, a method call to an external method has been
946          * detected. As of 11/19/2019, iASL does not support parameter counts
947          * for methods declared as external. Therefore, save the parameter
948          * count of the first method call and use this count check other
949          * method calls to ensure that the methods are being called with the
950          * same amount of parameters.
951          */
952         else if (Node->Type == ACPI_TYPE_METHOD &&
953             (Node->Flags & ANOBJ_IS_EXTERNAL) &&
954             Node->Value == ASL_EXTERNAL_METHOD_UNKNOWN_PARAMS &&
955             Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL)
956         {
957             Node->Value = PassedArgs;
958         }
959     }
960 
961     /* 4) Check for an ASL Field definition */
962 
963     else if ((Op->Asl.Parent) &&
964             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
965              (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
966     {
967         /*
968          * Offset checking for fields. If the parent operation region has a
969          * constant length (known at compile time), we can check fields
970          * defined in that region against the region length. This will catch
971          * fields and field units that cannot possibly fit within the region.
972          *
973          * Note: Index fields do not directly reference an operation region,
974          * thus they are not included in this check.
975          */
976         if (Op == Op->Asl.Parent->Asl.Child)
977         {
978             /*
979              * This is the first child of the field node, which is
980              * the name of the region. Get the parse node for the
981              * region -- which contains the length of the region.
982              */
983             OwningOp = Node->Op;
984             Op->Asl.Parent->Asl.ExtraValue =
985                 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
986 
987             /* Examine the field access width */
988 
989             switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
990             {
991             case AML_FIELD_ACCESS_ANY:
992             case AML_FIELD_ACCESS_BYTE:
993             case AML_FIELD_ACCESS_BUFFER:
994             default:
995 
996                 MinimumLength = 1;
997                 break;
998 
999             case AML_FIELD_ACCESS_WORD:
1000 
1001                 MinimumLength = 2;
1002                 break;
1003 
1004             case AML_FIELD_ACCESS_DWORD:
1005 
1006                 MinimumLength = 4;
1007                 break;
1008 
1009             case AML_FIELD_ACCESS_QWORD:
1010 
1011                 MinimumLength = 8;
1012                 break;
1013             }
1014 
1015             /*
1016              * Is the region at least as big as the access width?
1017              * Note: DataTableRegions have 0 length
1018              */
1019             if (((UINT32) OwningOp->Asl.Value.Integer) &&
1020                 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
1021             {
1022                 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
1023             }
1024 
1025             /*
1026              * Check EC/CMOS/SMBUS fields to make sure that the correct
1027              * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
1028              */
1029             SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
1030             switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
1031             {
1032             case ACPI_ADR_SPACE_EC:
1033             case ACPI_ADR_SPACE_CMOS:
1034             case ACPI_ADR_SPACE_GPIO:
1035 
1036                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
1037                     AML_FIELD_ACCESS_BYTE)
1038                 {
1039                     AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
1040                 }
1041                 break;
1042 
1043             case ACPI_ADR_SPACE_SMBUS:
1044             case ACPI_ADR_SPACE_IPMI:
1045             case ACPI_ADR_SPACE_GSBUS:
1046 
1047                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
1048                     AML_FIELD_ACCESS_BUFFER)
1049                 {
1050                     AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
1051                 }
1052                 break;
1053 
1054             default:
1055 
1056                 /* Nothing to do for other address spaces */
1057 
1058                 break;
1059             }
1060         }
1061         else
1062         {
1063             /*
1064              * This is one element of the field list. Check to make sure
1065              * that it does not go beyond the end of the parent operation region.
1066              *
1067              * In the code below:
1068              *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
1069              *    Op->Asl.ExtraValue                  - Field start offset (bits)
1070              *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
1071              *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
1072              */
1073             if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
1074             {
1075                 XfCheckFieldRange (Op,
1076                     Op->Asl.Parent->Asl.ExtraValue,
1077                     Op->Asl.ExtraValue,
1078                     (UINT32) Op->Asl.Child->Asl.Value.Integer,
1079                     Op->Asl.Child->Asl.ExtraValue);
1080             }
1081         }
1082     }
1083 
1084     /*
1085      * 5) Check for external resolution
1086      * By this point, everything should be loaded in the namespace. If a
1087      * namespace lookup results in a namespace node that is an external, it
1088      * means that this named object was not defined in the input ASL. This
1089      * causes issues because there are plenty of incidents where developers
1090      * use the external keyword to suppress compiler errors about undefined
1091      * objects. Note: this only applies when compiling multiple definition
1092      * blocks.
1093      */
1094     if (AslGbl_ParseTreeRoot->Asl.Child && AslGbl_ParseTreeRoot->Asl.Child->Asl.Next &&
1095         (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL &&
1096         Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL) &&
1097         (Node->Flags & ANOBJ_IS_EXTERNAL))
1098     {
1099         AslError (ASL_ERROR, ASL_MSG_UNDEFINED_EXTERNAL, Op, NULL);
1100     }
1101 
1102     /* 5) Check for a connection object */
1103 #if 0
1104     else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
1105     {
1106         return_ACPI_STATUS (Status);
1107     }
1108 #endif
1109 
1110     Op->Asl.Node = Node;
1111     return_ACPI_STATUS (Status);
1112 }
1113 
1114 
1115 /*******************************************************************************
1116  *
1117  * FUNCTION:    XfNamespaceLocateEnd
1118  *
1119  * PARAMETERS:  ASL_WALK_CALLBACK
1120  *
1121  * RETURN:      Status
1122  *
1123  * DESCRIPTION: Ascending callback used during cross reference. We only
1124  *              need to worry about scope management here.
1125  *
1126  ******************************************************************************/
1127 
1128 static ACPI_STATUS
1129 XfNamespaceLocateEnd (
1130     ACPI_PARSE_OBJECT       *Op,
1131     UINT32                  Level,
1132     void                    *Context)
1133 {
1134     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
1135     const ACPI_OPCODE_INFO  *OpInfo;
1136 
1137 
1138     ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd);
1139 
1140 
1141     /* We are only interested in opcodes that have an associated name */
1142 
1143     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1144     if (!(OpInfo->Flags & AML_NAMED))
1145     {
1146         return_ACPI_STATUS (AE_OK);
1147     }
1148 
1149     /* Not interested in name references, we did not open a scope for them */
1150 
1151     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
1152         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
1153         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
1154         (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
1155     {
1156         return_ACPI_STATUS (AE_OK);
1157     }
1158 
1159     /* Pop the scope stack if necessary */
1160 
1161     if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
1162     {
1163 
1164         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1165             "%s: Popping scope for Op %p\n",
1166             AcpiUtGetTypeName (OpInfo->ObjectType), Op));
1167 
1168         (void) AcpiDsScopeStackPop (WalkState);
1169     }
1170 
1171     return_ACPI_STATUS (AE_OK);
1172 }
1173 
1174 
1175 /*******************************************************************************
1176  *
1177  * FUNCTION:    XfValidateCrossReference
1178  *
1179  * PARAMETERS:  Op                      - Parse Op that references the object
1180  *              OpInfo                  - Parse Op info struct
1181  *              Node                    - Node for the referenced object
1182  *
1183  * RETURN:      TRUE if the reference is legal, FALSE otherwise
1184  *
1185  * DESCRIPTION: Determine if a reference to another object is allowed.
1186  *
1187  * EXAMPLE:
1188  *      Method (A) {Name (INT1, 1)}     Declaration of object INT1
1189  *      Method (B) (Store (2, \A.INT1)} Illegal reference to object INT1
1190  *                                      (INT1 is temporary, valid only during
1191  *                                      execution of A)
1192  *
1193  * NOTES:
1194  *      A null pointer returned by either UtGetParentMethodOp or
1195  *      UtGetParentMethodNode indicates that the parameter object is not
1196  *      within a control method.
1197  *
1198  *      Five cases are handled: Case(Op, Node)
1199  *      1) Case(0,0): Op is not within a method, Node is not    --> OK
1200  *      2) Case(0,1): Op is not within a method, but Node is    --> Illegal
1201  *      3) Case(1,0): Op is within a method, Node is not        --> OK
1202  *      4) Case(1,1): Both are within the same method           --> OK
1203  *      5) Case(1,1): Both are in methods, but not same method  --> Illegal
1204  *
1205  ******************************************************************************/
1206 
1207 static BOOLEAN
1208 XfValidateCrossReference (
1209     ACPI_PARSE_OBJECT       *Op,
1210     const ACPI_OPCODE_INFO  *OpInfo,
1211     ACPI_NAMESPACE_NODE     *Node)
1212 {
1213     ACPI_PARSE_OBJECT       *ReferencingMethodOp;
1214     ACPI_NAMESPACE_NODE     *ReferencedMethodNode;
1215 
1216 
1217     /* Ignore actual named (and related) object declarations */
1218 
1219     if (OpInfo->Flags & (AML_NAMED | AML_CREATE | AML_DEFER | AML_HAS_ARGS))
1220     {
1221         return (TRUE);
1222     }
1223 
1224     /*
1225      * 1) Search upwards in parse tree for owner of the referencing object
1226      * 2) Search upwards in namespace to find the owner of the referenced object
1227      */
1228     ReferencingMethodOp = UtGetParentMethodOp (Op);
1229     ReferencedMethodNode = UtGetParentMethodNode (Node);
1230 
1231     if (!ReferencingMethodOp && !ReferencedMethodNode)
1232     {
1233         /*
1234          * 1) Case (0,0): Both Op and Node are not within methods
1235          * --> OK
1236          */
1237         return (TRUE);
1238     }
1239 
1240     if (!ReferencingMethodOp && ReferencedMethodNode)
1241     {
1242         /*
1243          * 2) Case (0,1): Op is not in a method, but Node is within a
1244          * method --> illegal
1245          */
1246         return (FALSE);
1247     }
1248     else if (ReferencingMethodOp && !ReferencedMethodNode)
1249     {
1250         /*
1251          * 3) Case (1,0): Op is within a method, but Node is not
1252          * --> OK
1253          */
1254         return (TRUE);
1255     }
1256     else if (ReferencingMethodOp->Asl.Node == ReferencedMethodNode)
1257     {
1258         /*
1259          * 4) Case (1,1): Both Op and Node are within the same method
1260          * --> OK
1261          */
1262         return (TRUE);
1263     }
1264     else
1265     {
1266         /*
1267          * 5) Case (1,1), Op and Node are in different methods
1268          * --> Illegal
1269          */
1270         return (FALSE);
1271     }
1272 }
1273