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