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