xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslxref.c (revision 2c7d7e3ca2e4f0b675c6c58e614f6aede66c678e)
1 /******************************************************************************
2  *
3  * Module Name: aslxref - Namespace cross-reference
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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
XfCrossReferenceNamespace(void)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
XfObjectExists(char * Name)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
XfCompareOneNamespaceObject(ACPI_HANDLE ObjHandle,UINT32 Level,void * Context,void ** ReturnValue)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
XfCheckFieldRange(ACPI_PARSE_OBJECT * Op,UINT32 RegionBitLength,UINT32 FieldBitOffset,UINT32 FieldBitLength,UINT32 AccessBitWidth)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
XfNamespaceLocateBegin(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)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     char                    *ExternalPath;
329 
330 
331     ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);
332 
333 
334     if ((Op->Asl.AmlOpcode == AML_METHOD_OP) && Op->Asl.Node)
335     {
336         Node = Op->Asl.Node;
337 
338         /* Support for method LocalX/ArgX analysis */
339 
340         if (!Node->MethodLocals)
341         {
342             /* Create local/arg info blocks */
343 
344             MethodLocals = UtLocalCalloc (
345                 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS);
346             Node->MethodLocals = MethodLocals;
347 
348             MethodArgs = UtLocalCalloc (
349                 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS);
350             Node->MethodArgs = MethodArgs;
351 
352             /*
353              * Get the method argument count
354              * First, get the name node
355              */
356             NextOp = Op->Asl.Child;
357 
358             /* Get the NumArguments node */
359 
360             NextOp = NextOp->Asl.Next;
361             Node->ArgCount = (UINT8)
362                 (((UINT8) NextOp->Asl.Value.Integer) & 0x07);
363 
364             /* We will track all possible ArgXs */
365 
366             for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
367             {
368                 if (i < Node->ArgCount)
369                 {
370                     /* Real Args are always "initialized" */
371 
372                     MethodArgs[i].Flags = ASL_ARG_INITIALIZED;
373                 }
374                 else
375                 {
376                     /* Other ArgXs can be used as locals */
377 
378                     MethodArgs[i].Flags = ASL_ARG_IS_LOCAL;
379                 }
380 
381                 MethodArgs[i].Op = Op;
382             }
383         }
384     }
385 
386     /*
387      * If this node is the actual declaration of a name
388      * [such as the XXXX name in "Method (XXXX)"],
389      * we are not interested in it here. We only care about names that are
390      * references to other objects within the namespace and the parent objects
391      * of name declarations
392      */
393     if (Op->Asl.CompileFlags & OP_IS_NAME_DECLARATION)
394     {
395         return_ACPI_STATUS (AE_OK);
396     }
397 
398     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
399 
400     /* Check method LocalX variables */
401 
402     if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE)
403     {
404         /* Find parent method Op */
405 
406         NextOp = UtGetParentMethodOp (Op);
407         if (!NextOp)
408         {
409             return_ACPI_STATUS (AE_OK);
410         }
411 
412         /* Get method node */
413 
414         Node = NextOp->Asl.Node;
415 
416         RegisterNumber = Op->Asl.AmlOpcode & 0x0007; /* 0x60 through 0x67 */
417         MethodLocals = Node->MethodLocals;
418 
419         if (Op->Asl.CompileFlags & OP_IS_TARGET)
420         {
421             /* Local is being initialized */
422 
423             MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_INITIALIZED;
424             MethodLocals[RegisterNumber].Op = Op;
425 
426             return_ACPI_STATUS (AE_OK);
427         }
428 
429         /* Mark this Local as referenced */
430 
431         MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_REFERENCED;
432         MethodLocals[RegisterNumber].Op = Op;
433 
434         return_ACPI_STATUS (AE_OK);
435     }
436 
437     /* Check method ArgX variables */
438 
439     if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT)
440     {
441         /* Find parent method Op */
442 
443         NextOp = UtGetParentMethodOp (Op);
444         if (!NextOp)
445         {
446             return_ACPI_STATUS (AE_OK);
447         }
448 
449         /* Get method node */
450 
451         Node = NextOp->Asl.Node;
452 
453         /* Get Arg # */
454 
455         RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */
456         MethodArgs = Node->MethodArgs;
457 
458         /* Mark this Arg as referenced */
459 
460         MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED;
461         MethodArgs[RegisterNumber].Op = Op;
462 
463         if (Op->Asl.CompileFlags & OP_IS_TARGET)
464         {
465             /* Arg is being initialized */
466 
467             MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED;
468         }
469 
470         return_ACPI_STATUS (AE_OK);
471     }
472 
473     /*
474      * After method ArgX and LocalX, we are only interested in opcodes
475      * that have an associated name
476      */
477     if ((!(OpInfo->Flags & AML_NAMED)) &&
478         (!(OpInfo->Flags & AML_CREATE)) &&
479         (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
480         (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
481         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL) &&
482         (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL))
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         (Op->Asl.ParseOpcode == PARSEOP_CONDREFOF))
497     {
498         /*
499          * These are name references, do not push the scope stack
500          * for them.
501          */
502         Flags |= ACPI_NS_DONT_OPEN_SCOPE;
503     }
504 
505     /* Get the NamePath from the appropriate place */
506 
507     if (OpInfo->Flags & AML_NAMED)
508     {
509         /* For nearly all NAMED operators, the name reference is the first child */
510 
511         Path = Op->Asl.Child->Asl.Value.String;
512         if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
513         {
514             /*
515              * ALIAS is the only oddball opcode, the name declaration
516              * (alias name) is the second operand
517              */
518             Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
519         }
520     }
521     else if (OpInfo->Flags & AML_CREATE)
522     {
523         /* Name must appear as the last parameter */
524 
525         NextOp = Op->Asl.Child;
526         while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
527         {
528             NextOp = NextOp->Asl.Next;
529         }
530 
531         Path = NextOp->Asl.Value.String;
532     }
533     else
534     {
535         Path = Op->Asl.Value.String;
536     }
537 
538     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
539     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
540         "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
541 
542     /*
543      * Lookup the name in the namespace. Name must exist at this point, or it
544      * is an invalid reference.
545      *
546      * The namespace is also used as a lookup table for references to resource
547      * descriptors and the fields within them.
548      */
549     AslGbl_NsLookupCount++;
550 
551     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
552         ACPI_IMODE_EXECUTE, Flags, WalkState, &Node);
553     if (ACPI_FAILURE (Status))
554     {
555         if (Status == AE_NOT_FOUND)
556         {
557             /*
558              * We didn't find the name reference by path -- we can qualify this
559              * a little better before we print an error message
560              */
561 
562             if ((Op->Asl.Parent) &&
563                 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
564             {
565                 /*
566                  * One special case: CondRefOf operator - if the name doesn't
567                  * exist at this point, it means that there's no actual or
568                  * external declaration. If the name is not found, just ignore
569                  * it, the point of the operator is to determine if the name
570                  * exists at runtime. We wanted to see if this named object
571                  * exists to facilitate analysis to allow protected usage of
572                  * undeclared externals.
573                  */
574                 return_ACPI_STATUS (AE_OK);
575             }
576             else if (strlen (Path) == ACPI_NAMESEG_SIZE)
577             {
578                 /* A simple, one-segment ACPI name */
579 
580                 if (XfObjectExists (Path))
581                 {
582                     /*
583                      * There exists such a name, but we couldn't get to it
584                      * from this scope
585                      */
586                     AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
587                         Op->Asl.ExternalName);
588                 }
589                 else
590                 {
591                     /* The name doesn't exist, period */
592 
593                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
594                         Op, Op->Asl.ExternalName);
595                 }
596             }
597             else
598             {
599                 /* The NamePath contains multiple NameSegs */
600 
601                 if ((OpInfo->Flags & AML_CREATE) ||
602                     (OpInfo->ObjectType == ACPI_TYPE_LOCAL_ALIAS))
603                 {
604                     /*
605                      * The new name is the last parameter. For the
606                      * CreateXXXXField and Alias operators
607                      */
608                     NextOp = Op->Asl.Child;
609                     while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
610                     {
611                         NextOp = NextOp->Asl.Next;
612                     }
613 
614                     AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, NextOp,
615                         NextOp->Asl.ExternalName);
616                 }
617                 else if (OpInfo->Flags & AML_NAMED)
618                 {
619                     /* The new name is the first parameter */
620 
621                     AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, Op,
622                         Op->Asl.ExternalName);
623                 }
624                 else if (Path[0] == AML_ROOT_PREFIX)
625                 {
626                     /* Full namepath from root, the object does not exist */
627 
628                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
629                         Op->Asl.ExternalName);
630                 }
631                 else
632                 {
633                     /*
634                      * Generic "not found" error. Cannot determine whether it
635                      * doesn't exist or just can't be reached. However, we
636                      * can differentiate between a NameSeg vs. NamePath.
637                      */
638                     if (strlen (Op->Asl.ExternalName) == ACPI_NAMESEG_SIZE)
639                     {
640                         AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
641                             Op->Asl.ExternalName);
642                     }
643                     else
644                     {
645                         AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op,
646                             Op->Asl.ExternalName);
647                     }
648                 }
649             }
650 
651             Status = AE_OK;
652         }
653 
654         return_ACPI_STATUS (Status);
655     }
656 
657     /* Check for an attempt to access an object in another method */
658 
659     if (!XfValidateCrossReference (Op, OpInfo, Node))
660     {
661         AslError (ASL_ERROR, ASL_MSG_TEMPORARY_OBJECT, Op,
662             Op->Asl.ExternalName);
663         return_ACPI_STATUS (Status);
664     }
665 
666    /* Object was found above, check for an illegal forward reference */
667 
668     if (Op->Asl.CompileFlags & OP_NOT_FOUND_DURING_LOAD)
669     {
670         /*
671          * During the load phase, this Op was flagged as a possible
672          * illegal forward reference. In other words, Op is a name path or
673          * name segment that refers to a named object declared after the
674          * reference. In this scinario, Node refers to the actual declaration
675          * and Op is a parse node that references the named object.
676          *
677          * Note:
678          *
679          * Object references inside of control methods are allowed to
680          * refer to objects declared outside of control methods.
681          *
682          * If the declaration and reference are both contained inside of the
683          * same method or outside of any method, this is a forward reference
684          * and should be reported as a compiler error.
685          */
686         DeclarationParentMethod = UtGetParentMethodNode (Node);
687         ReferenceParentMethod = UtGetParentMethodOp (Op);
688 
689         /* case 1: declaration and reference are both outside of method */
690 
691         if (!ReferenceParentMethod && !DeclarationParentMethod)
692         {
693             AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
694                 Op->Asl.ExternalName);
695         }
696 
697         /* case 2: declaration and reference are both inside of the same method */
698 
699         else if (ReferenceParentMethod && DeclarationParentMethod &&
700             ReferenceParentMethod == DeclarationParentMethod->Op)
701         {
702              AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
703                 Op->Asl.ExternalName);
704         }
705     }
706 
707     /* Check for a reference vs. name declaration */
708 
709     if (!(OpInfo->Flags & AML_NAMED) &&
710         !(OpInfo->Flags & AML_CREATE))
711     {
712         /* This node has been referenced, mark it for reference check */
713 
714         Node->Flags |= ANOBJ_IS_REFERENCED;
715     }
716 
717     /*
718      * Attempt to optimize the NamePath
719      *
720      * One special case: CondRefOf operator - not all AML interpreter
721      * implementations expect optimized namepaths as a parameter to this
722      * operator. They require relative name paths with prefix operators or
723      * namepaths starting with the root scope.
724      *
725      * Other AML interpreter implementations do not perform the namespace
726      * search that starts at the current scope and recursively searching the
727      * parent scope until the root scope. The lack of search is only known to
728      * occur for the namestring parameter for the CondRefOf operator.
729      */
730     if ((Op->Asl.Parent) &&
731         (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_CONDREFOF))
732     {
733         OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
734     }
735 
736     /*
737      * 1) Dereference an alias (A name reference that is an alias)
738      *    Aliases are not nested, the alias always points to the final object
739      */
740     if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
741         (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
742     {
743         /* This node points back to the original PARSEOP_ALIAS */
744 
745         NextOp = Node->Op;
746 
747         /* The first child is the alias target op */
748 
749         NextOp = NextOp->Asl.Child;
750 
751         /* That in turn points back to original target alias node */
752 
753         if (NextOp->Asl.Node)
754         {
755             Node = NextOp->Asl.Node;
756         }
757 
758         /* Else - forward reference to alias, will be resolved later */
759     }
760 
761     /* 2) Check for a reference to a resource descriptor */
762 
763     if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
764         (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
765     {
766         /*
767          * This was a reference to a field within a resource descriptor.
768          * Extract the associated field offset (either a bit or byte
769          * offset depending on the field type) and change the named
770          * reference into an integer for AML code generation
771          */
772         Offset = Node->Value;
773         TagBitLength = Node->Length;
774 
775         /*
776          * If a field is being created, generate the length (in bits) of
777          * the field. Note: Opcodes other than CreateXxxField and Index
778          * can come through here. For other opcodes, we just need to
779          * convert the resource tag reference to an integer offset.
780          */
781         switch (Op->Asl.Parent->Asl.AmlOpcode)
782         {
783         case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
784             /*
785              * We know the length operand is an integer constant because
786              * we know that it contains a reference to a resource
787              * descriptor tag.
788              */
789             FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
790             break;
791 
792         case AML_CREATE_BIT_FIELD_OP:
793 
794             FieldBitLength = 1;
795             break;
796 
797         case AML_CREATE_BYTE_FIELD_OP:
798         case AML_INDEX_OP:
799 
800             FieldBitLength = 8;
801             break;
802 
803         case AML_CREATE_WORD_FIELD_OP:
804 
805             FieldBitLength = 16;
806             break;
807 
808         case AML_CREATE_DWORD_FIELD_OP:
809 
810             FieldBitLength = 32;
811             break;
812 
813         case AML_CREATE_QWORD_FIELD_OP:
814 
815             FieldBitLength = 64;
816             break;
817 
818         default:
819 
820             FieldBitLength = 0;
821             break;
822         }
823 
824         /* Check the field length against the length of the resource tag */
825 
826         if (FieldBitLength)
827         {
828             if (TagBitLength < FieldBitLength)
829             {
830                 Message = ASL_MSG_TAG_SMALLER;
831             }
832             else if (TagBitLength > FieldBitLength)
833             {
834                 Message = ASL_MSG_TAG_LARGER;
835             }
836 
837             if (Message)
838             {
839                 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
840                     "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
841                     TagBitLength, (TagBitLength > 1) ? "s" : "",
842                     FieldBitLength, (FieldBitLength > 1) ? "s" : "");
843 
844                 AslError (ASL_WARNING, Message, Op, AslGbl_MsgBuffer);
845             }
846         }
847 
848         /* Convert the BitOffset to a ByteOffset for certain opcodes */
849 
850         switch (Op->Asl.Parent->Asl.AmlOpcode)
851         {
852         case AML_CREATE_BYTE_FIELD_OP:
853         case AML_CREATE_WORD_FIELD_OP:
854         case AML_CREATE_DWORD_FIELD_OP:
855         case AML_CREATE_QWORD_FIELD_OP:
856         case AML_INDEX_OP:
857 
858             Offset = ACPI_DIV_8 (Offset);
859             break;
860 
861         default:
862 
863             break;
864         }
865 
866         /* Now convert this node to an integer whose value is the field offset */
867 
868         Op->Asl.AmlLength = 0;
869         Op->Asl.ParseOpcode = PARSEOP_INTEGER;
870         Op->Asl.Value.Integer = (UINT64) Offset;
871         Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD;
872 
873         OpcGenerateAmlOpcode (Op);
874     }
875 
876     /* 3) Check for a method invocation */
877 
878     else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
879                 (Node->Type == ACPI_TYPE_METHOD) &&
880                 (Op->Asl.Parent) &&
881                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||
882 
883                 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
884     {
885         /*
886          * A reference to a method within one of these opcodes is not an
887          * invocation of the method, it is simply a reference to the method.
888          *
889          * September 2016: Removed DeRefOf from this list
890          * July 2020: Added Alias to this list
891          */
892         if ((Op->Asl.Parent) &&
893             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF)     ||
894             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE)    ||
895             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)||
896             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE) ||
897             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_ALIAS)))
898         {
899             return_ACPI_STATUS (AE_OK);
900         }
901 
902         /*
903          * There are two types of method invocation:
904          * 1) Invocation with arguments -- the parser recognizes this
905          *    as a METHODCALL.
906          * 2) Invocation with no arguments --the parser cannot determine that
907          *    this is a method invocation, therefore we have to figure it out
908          *    here.
909          */
910         if (Node->Type != ACPI_TYPE_METHOD)
911         {
912             snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s is a %s",
913                 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
914 
915             AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, AslGbl_MsgBuffer);
916             return_ACPI_STATUS (AE_OK);
917         }
918 
919         /* Save the method node in the caller's op */
920 
921         Op->Asl.Node = Node;
922         if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
923         {
924             return_ACPI_STATUS (AE_OK);
925         }
926 
927         /*
928          * This is a method invocation, with or without arguments.
929          * Count the number of arguments, each appears as a child
930          * under the parent node
931          */
932         Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
933         UtSetParseOpName (Op);
934 
935         PassedArgs = 0;
936         NextOp = Op->Asl.Child;
937 
938         while (NextOp)
939         {
940             PassedArgs++;
941             NextOp = NextOp->Asl.Next;
942         }
943 
944         if (Node->Value != ASL_EXTERNAL_METHOD_UNKNOWN_PARAMS &&
945             Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL)
946         {
947             /*
948              * Check the parsed arguments with the number expected by the
949              * method declaration itself
950              */
951             if (PassedArgs != Node->Value)
952             {
953                 if (Node->Flags & ANOBJ_IS_EXTERNAL)
954                 {
955                     snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
956                         "according to previous use, %s requires %u",
957                         Op->Asl.ExternalName, Node->Value);
958                 }
959                 else
960                 {
961                     snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
962 			"%s requires %u", Op->Asl.ExternalName,
963                         Node->Value);
964                 }
965 
966                 if (PassedArgs < Node->Value)
967                 {
968                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, AslGbl_MsgBuffer);
969                 }
970                 else
971                 {
972                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, AslGbl_MsgBuffer);
973                 }
974             }
975         }
976 
977         /*
978          * At this point, a method call to an external method has been
979          * detected. As of 11/19/2019, iASL does not support parameter counts
980          * for methods declared as external. Therefore, save the parameter
981          * count of the first method call and use this count check other
982          * method calls to ensure that the methods are being called with the
983          * same amount of parameters.
984          */
985         else if (Node->Type == ACPI_TYPE_METHOD &&
986             (Node->Flags & ANOBJ_IS_EXTERNAL) &&
987             Node->Value == ASL_EXTERNAL_METHOD_UNKNOWN_PARAMS &&
988             Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL)
989         {
990             Node->Value = PassedArgs;
991         }
992     }
993 
994     /* 4) Check for an ASL Field definition */
995 
996     else if ((Op->Asl.Parent) &&
997             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
998              (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
999     {
1000         /*
1001          * Offset checking for fields. If the parent operation region has a
1002          * constant length (known at compile time), we can check fields
1003          * defined in that region against the region length. This will catch
1004          * fields and field units that cannot possibly fit within the region.
1005          *
1006          * Note: Index fields do not directly reference an operation region,
1007          * thus they are not included in this check.
1008          */
1009         if (Op == Op->Asl.Parent->Asl.Child)
1010         {
1011             /*
1012              * This is the first child of the field node, which is
1013              * the name of the region. Get the parse node for the
1014              * region -- which contains the length of the region.
1015              */
1016             OwningOp = Node->Op;
1017             Op->Asl.Parent->Asl.ExtraValue =
1018                 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
1019 
1020             /* Examine the field access width */
1021 
1022             switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
1023             {
1024             case AML_FIELD_ACCESS_ANY:
1025             case AML_FIELD_ACCESS_BYTE:
1026             case AML_FIELD_ACCESS_BUFFER:
1027             default:
1028 
1029                 MinimumLength = 1;
1030                 break;
1031 
1032             case AML_FIELD_ACCESS_WORD:
1033 
1034                 MinimumLength = 2;
1035                 break;
1036 
1037             case AML_FIELD_ACCESS_DWORD:
1038 
1039                 MinimumLength = 4;
1040                 break;
1041 
1042             case AML_FIELD_ACCESS_QWORD:
1043 
1044                 MinimumLength = 8;
1045                 break;
1046             }
1047 
1048             /*
1049              * Is the region at least as big as the access width?
1050              * Note: DataTableRegions have 0 length
1051              */
1052             if (((UINT32) OwningOp->Asl.Value.Integer) &&
1053                 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
1054             {
1055                 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
1056             }
1057 
1058             /*
1059              * Check EC/CMOS/SMBUS fields to make sure that the correct
1060              * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
1061              */
1062             SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
1063             switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
1064             {
1065             case ACPI_ADR_SPACE_EC:
1066             case ACPI_ADR_SPACE_CMOS:
1067             case ACPI_ADR_SPACE_GPIO:
1068 
1069                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
1070                     AML_FIELD_ACCESS_BYTE)
1071                 {
1072                     AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
1073                 }
1074                 break;
1075 
1076             case ACPI_ADR_SPACE_SMBUS:
1077             case ACPI_ADR_SPACE_IPMI:
1078             case ACPI_ADR_SPACE_GSBUS:
1079 
1080                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
1081                     AML_FIELD_ACCESS_BUFFER)
1082                 {
1083                     AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
1084                 }
1085                 break;
1086 
1087             default:
1088 
1089                 /* Nothing to do for other address spaces */
1090 
1091                 break;
1092             }
1093         }
1094         else
1095         {
1096             /*
1097              * This is one element of the field list. Check to make sure
1098              * that it does not go beyond the end of the parent operation region.
1099              *
1100              * In the code below:
1101              *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
1102              *    Op->Asl.ExtraValue                  - Field start offset (bits)
1103              *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
1104              *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
1105              */
1106             if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
1107             {
1108                 XfCheckFieldRange (Op,
1109                     Op->Asl.Parent->Asl.ExtraValue,
1110                     Op->Asl.ExtraValue,
1111                     (UINT32) Op->Asl.Child->Asl.Value.Integer,
1112                     Op->Asl.Child->Asl.ExtraValue);
1113             }
1114         }
1115     }
1116 
1117     /*
1118      * 5) Check for external resolution
1119      *
1120      * By this point, everything should be loaded in the namespace. If a
1121      * namespace lookup results in a namespace node that is an external, it
1122      * means that this named object was not defined in the input ASL. This
1123      * causes issues because there are plenty of incidents where developers
1124      * use the external keyword to suppress compiler errors about undefined
1125      * objects. Note: this only applies when compiling multiple definition
1126      * blocks.
1127      *
1128      * Do not check for external resolution in the following cases:
1129      *
1130      * case 1) External (ABCD)
1131      *
1132      *         This declares ABCD as an external so there is no requirement for
1133      *         ABCD to be loaded in the namespace when analyzing the actual
1134      *         External() statement.
1135      *
1136      * case 2) CondRefOf (ABCD)
1137      *
1138      *         This operator will query the ACPI namespace on the existence of
1139      *         ABCD. If ABCD does not exist, this operator will return a 0
1140      *         without incurring AML runtime errors. Therefore, ABCD is allowed
1141      *         to not exist when analyzing the CondRefOf operator.
1142      *
1143      * case 3) External (ABCD)
1144      *         if (CondRefOf (ABCD))
1145      *         {
1146      *             Store (0, ABCD)
1147      *         }
1148      *
1149      *         In this case, ABCD is accessed only if it exists due to the if
1150      *         statement so there is no need to flag the ABCD nested in the
1151      *         store operator.
1152      */
1153     if (AslGbl_ParseTreeRoot->Asl.Child && AslGbl_ParseTreeRoot->Asl.Child->Asl.Next &&
1154         (Node->Flags & ANOBJ_IS_EXTERNAL) &&
1155         Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL &&
1156         Op->Asl.ParseOpcode != PARSEOP_EXTERNAL &&
1157         Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_CONDREFOF &&
1158         !XfRefIsGuardedByIfCondRefOf (Node, Op))
1159     {
1160         ExternalPath = AcpiNsGetNormalizedPathname (Node, TRUE);
1161         sprintf (AslGbl_MsgBuffer, "full path of external object: %s",
1162             ExternalPath);
1163         AslDualParseOpError (ASL_ERROR, ASL_MSG_UNDEFINED_EXTERNAL, Op, NULL,
1164             ASL_MSG_EXTERNAL_FOUND_HERE, Node->Op, AslGbl_MsgBuffer);
1165         if (ExternalPath)
1166         {
1167             ACPI_FREE (ExternalPath);
1168         }
1169     }
1170 
1171     /* 5) Check for a connection object */
1172 #if 0
1173     else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
1174     {
1175         return_ACPI_STATUS (Status);
1176     }
1177 #endif
1178 
1179     Op->Asl.Node = Node;
1180     return_ACPI_STATUS (Status);
1181 }
1182 
1183 
1184 /*******************************************************************************
1185  *
1186  * FUNCTION:    XfRefIsGuardedByIfCondRefOf
1187  *
1188  * PARAMETERS:  Node        - Named object reference node
1189  *              Op          - Named object reference parse node
1190  *
1191  * RETURN:      BOOLEAN
1192  *
1193  * DESCRIPTION: returns true if Op checked inside if (CondRefOf (...))
1194  *              refers to Node.
1195  *
1196  ******************************************************************************/
1197 
1198 static BOOLEAN
XfRefIsGuardedByIfCondRefOf(ACPI_NAMESPACE_NODE * Node,ACPI_PARSE_OBJECT * Op)1199 XfRefIsGuardedByIfCondRefOf (
1200     ACPI_NAMESPACE_NODE     *Node,
1201     ACPI_PARSE_OBJECT       *Op)
1202 {
1203     ACPI_PARSE_OBJECT       *Parent = Op->Asl.Parent;
1204 
1205 
1206     while (Parent)
1207     {
1208         if (Parent->Asl.ParseOpcode == PARSEOP_IF &&
1209             XfFindCondRefOfName (Node, Parent->Asl.Child))
1210         {
1211             return (TRUE);
1212         }
1213 
1214         Parent = Parent->Asl.Parent;
1215     }
1216 
1217     return (FALSE);
1218 }
1219 
1220 
1221 /*******************************************************************************
1222  *
1223  * FUNCTION:    XfRefIsGuardedByIfCondRefOf
1224  *
1225  * PARAMETERS:  Node        - Named object reference node
1226  *              Op          - Named object reference parse node
1227  *
1228  * RETURN:      BOOLEAN
1229  *
1230  * DESCRIPTION: returns true if Op checked inside if (CondRefOf (...))
1231  *              refers to Node.
1232  *
1233  ******************************************************************************/
1234 
1235 static BOOLEAN
XfFindCondRefOfName(ACPI_NAMESPACE_NODE * Node,ACPI_PARSE_OBJECT * Op)1236 XfFindCondRefOfName (
1237     ACPI_NAMESPACE_NODE     *Node,
1238     ACPI_PARSE_OBJECT       *Op)
1239 {
1240     BOOLEAN                 CondRefOfFound = FALSE;
1241 
1242 
1243     if (!Op)
1244     {
1245         return (FALSE);
1246     }
1247 
1248     switch (Op->Asl.ParseOpcode)
1249     {
1250     case PARSEOP_CONDREFOF:
1251 
1252         return (Op->Asl.Child->Common.Node == Node);
1253         break;
1254 
1255     case PARSEOP_LAND:
1256 
1257         CondRefOfFound = XfFindCondRefOfName (Node, Op->Asl.Child);
1258         if (CondRefOfFound)
1259         {
1260             return (TRUE);
1261         }
1262 
1263         return (XfFindCondRefOfName (Node, Op->Asl.Child->Asl.Next));
1264         break;
1265 
1266     default:
1267 
1268         return (FALSE);
1269         break;
1270     }
1271 }
1272 
1273 
1274 /*******************************************************************************
1275  *
1276  * FUNCTION:    XfNamespaceLocateEnd
1277  *
1278  * PARAMETERS:  ASL_WALK_CALLBACK
1279  *
1280  * RETURN:      Status
1281  *
1282  * DESCRIPTION: Ascending callback used during cross reference. We only
1283  *              need to worry about scope management here.
1284  *
1285  ******************************************************************************/
1286 
1287 static ACPI_STATUS
XfNamespaceLocateEnd(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)1288 XfNamespaceLocateEnd (
1289     ACPI_PARSE_OBJECT       *Op,
1290     UINT32                  Level,
1291     void                    *Context)
1292 {
1293     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
1294     const ACPI_OPCODE_INFO  *OpInfo;
1295 
1296 
1297     ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd);
1298 
1299 
1300     /* We are only interested in opcodes that have an associated name */
1301 
1302     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1303     if (!(OpInfo->Flags & AML_NAMED))
1304     {
1305         return_ACPI_STATUS (AE_OK);
1306     }
1307 
1308     /* Not interested in name references, we did not open a scope for them */
1309 
1310     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
1311         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
1312         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
1313         (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
1314     {
1315         return_ACPI_STATUS (AE_OK);
1316     }
1317 
1318     /* Pop the scope stack if necessary */
1319 
1320     if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
1321     {
1322 
1323         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1324             "%s: Popping scope for Op %p\n",
1325             AcpiUtGetTypeName (OpInfo->ObjectType), Op));
1326 
1327         (void) AcpiDsScopeStackPop (WalkState);
1328     }
1329 
1330     return_ACPI_STATUS (AE_OK);
1331 }
1332 
1333 
1334 /*******************************************************************************
1335  *
1336  * FUNCTION:    XfValidateCrossReference
1337  *
1338  * PARAMETERS:  Op                      - Parse Op that references the object
1339  *              OpInfo                  - Parse Op info struct
1340  *              Node                    - Node for the referenced object
1341  *
1342  * RETURN:      TRUE if the reference is legal, FALSE otherwise
1343  *
1344  * DESCRIPTION: Determine if a reference to another object is allowed.
1345  *
1346  * EXAMPLE:
1347  *      Method (A) {Name (INT1, 1)}     Declaration of object INT1
1348  *      Method (B) (Store (2, \A.INT1)} Illegal reference to object INT1
1349  *                                      (INT1 is temporary, valid only during
1350  *                                      execution of A)
1351  *
1352  * NOTES:
1353  *      A null pointer returned by either UtGetParentMethodOp or
1354  *      UtGetParentMethodNode indicates that the parameter object is not
1355  *      within a control method.
1356  *
1357  *      Five cases are handled: Case(Op, Node)
1358  *      1) Case(0,0): Op is not within a method, Node is not    --> OK
1359  *      2) Case(0,1): Op is not within a method, but Node is    --> Illegal
1360  *      3) Case(1,0): Op is within a method, Node is not        --> OK
1361  *      4) Case(1,1): Both are within the same method           --> OK
1362  *      5) Case(1,1): Both are in methods, but not same method  --> Illegal
1363  *
1364  ******************************************************************************/
1365 
1366 static BOOLEAN
XfValidateCrossReference(ACPI_PARSE_OBJECT * Op,const ACPI_OPCODE_INFO * OpInfo,ACPI_NAMESPACE_NODE * Node)1367 XfValidateCrossReference (
1368     ACPI_PARSE_OBJECT       *Op,
1369     const ACPI_OPCODE_INFO  *OpInfo,
1370     ACPI_NAMESPACE_NODE     *Node)
1371 {
1372     ACPI_PARSE_OBJECT       *ReferencingMethodOp;
1373     ACPI_NAMESPACE_NODE     *ReferencedMethodNode;
1374 
1375 
1376     /* Ignore actual named (and related) object declarations */
1377 
1378     if (OpInfo->Flags & (AML_NAMED | AML_CREATE | AML_DEFER | AML_HAS_ARGS))
1379     {
1380         return (TRUE);
1381     }
1382 
1383     /*
1384      * 1) Search upwards in parse tree for owner of the referencing object
1385      * 2) Search upwards in namespace to find the owner of the referenced object
1386      */
1387     ReferencingMethodOp = UtGetParentMethodOp (Op);
1388     ReferencedMethodNode = UtGetParentMethodNode (Node);
1389 
1390     if (!ReferencingMethodOp && !ReferencedMethodNode)
1391     {
1392         /*
1393          * 1) Case (0,0): Both Op and Node are not within methods
1394          * --> OK
1395          */
1396         return (TRUE);
1397     }
1398 
1399     if (!ReferencingMethodOp && ReferencedMethodNode)
1400     {
1401         /*
1402          * 2) Case (0,1): Op is not in a method, but Node is within a
1403          * method --> illegal
1404          */
1405         return (FALSE);
1406     }
1407     else if (ReferencingMethodOp && !ReferencedMethodNode)
1408     {
1409         /*
1410          * 3) Case (1,0): Op is within a method, but Node is not
1411          * --> OK
1412          */
1413         return (TRUE);
1414     }
1415     else if (ReferencingMethodOp->Asl.Node == ReferencedMethodNode)
1416     {
1417         /*
1418          * 4) Case (1,1): Both Op and Node are within the same method
1419          * --> OK
1420          */
1421         return (TRUE);
1422     }
1423     else
1424     {
1425         /*
1426          * 5) Case (1,1), Op and Node are in different methods
1427          * --> Illegal
1428          */
1429         return (FALSE);
1430     }
1431 }
1432