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 126 XfCrossReferenceNamespace ( 127 void) 128 { 129 ACPI_WALK_STATE *WalkState; 130 131 132 /* 133 * Create a new walk state for use when looking up names 134 * within the namespace (Passed as context to the callbacks) 135 */ 136 WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); 137 if (!WalkState) 138 { 139 return (AE_NO_MEMORY); 140 } 141 142 /* Walk the entire parse tree */ 143 144 TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE, 145 XfNamespaceLocateBegin, XfNamespaceLocateEnd, WalkState); 146 147 ACPI_FREE (WalkState); 148 return (AE_OK); 149 } 150 151 152 /******************************************************************************* 153 * 154 * FUNCTION: XfObjectExists 155 * 156 * PARAMETERS: Name - 4 char ACPI name 157 * 158 * RETURN: TRUE if name exists in namespace 159 * 160 * DESCRIPTION: Walk the namespace to find an object 161 * 162 ******************************************************************************/ 163 164 static BOOLEAN 165 XfObjectExists ( 166 char *Name) 167 { 168 ACPI_STATUS Status; 169 170 171 /* Walk entire namespace from the supplied root */ 172 173 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 174 ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL, 175 Name, NULL); 176 if (Status == AE_CTRL_TRUE) 177 { 178 /* At least one instance of the name was found */ 179 180 return (TRUE); 181 } 182 183 return (FALSE); 184 } 185 186 187 /******************************************************************************* 188 * 189 * FUNCTION: XfCompareOneNamespaceObject 190 * 191 * PARAMETERS: ACPI_WALK_CALLBACK 192 * 193 * RETURN: Status 194 * 195 * DESCRIPTION: Compare name of one object. 196 * 197 ******************************************************************************/ 198 199 static ACPI_STATUS 200 XfCompareOneNamespaceObject ( 201 ACPI_HANDLE ObjHandle, 202 UINT32 Level, 203 void *Context, 204 void **ReturnValue) 205 { 206 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 207 208 209 /* Simply check the name */ 210 211 if (*((UINT32 *) (Context)) == Node->Name.Integer) 212 { 213 /* Abort walk if we found one instance */ 214 215 return (AE_CTRL_TRUE); 216 } 217 218 return (AE_OK); 219 } 220 221 222 /******************************************************************************* 223 * 224 * FUNCTION: XfCheckFieldRange 225 * 226 * PARAMETERS: RegionBitLength - Length of entire parent region 227 * FieldBitOffset - Start of the field unit (within region) 228 * FieldBitLength - Entire length of field unit 229 * AccessBitWidth - Access width of the field unit 230 * 231 * RETURN: None 232 * 233 * DESCRIPTION: Check one field unit to make sure it fits in the parent 234 * op region. 235 * 236 * Note: AccessBitWidth must be either 8,16,32, or 64 237 * 238 ******************************************************************************/ 239 240 static void 241 XfCheckFieldRange ( 242 ACPI_PARSE_OBJECT *Op, 243 UINT32 RegionBitLength, 244 UINT32 FieldBitOffset, 245 UINT32 FieldBitLength, 246 UINT32 AccessBitWidth) 247 { 248 UINT32 FieldEndBitOffset; 249 250 251 /* 252 * Check each field unit against the region size. The entire 253 * field unit (start offset plus length) must fit within the 254 * region. 255 */ 256 FieldEndBitOffset = FieldBitOffset + FieldBitLength; 257 258 if (FieldEndBitOffset > RegionBitLength) 259 { 260 /* Field definition itself is beyond the end-of-region */ 261 262 AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL); 263 return; 264 } 265 266 /* 267 * Now check that the field plus AccessWidth doesn't go beyond 268 * the end-of-region. Assumes AccessBitWidth is a power of 2 269 */ 270 FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth); 271 272 if (FieldEndBitOffset > RegionBitLength) 273 { 274 /* Field definition combined with the access is beyond EOR */ 275 276 AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL); 277 } 278 } 279 280 281 /******************************************************************************* 282 * 283 * FUNCTION: XfNamespaceLocateBegin 284 * 285 * PARAMETERS: ASL_WALK_CALLBACK 286 * 287 * RETURN: Status 288 * 289 * DESCRIPTION: Descending callback used during cross-reference. For named 290 * object references, attempt to locate the name in the 291 * namespace. 292 * 293 * NOTE: ASL references to named fields within resource descriptors are 294 * resolved to integer values here. Therefore, this step is an 295 * important part of the code generation. We don't know that the 296 * name refers to a resource descriptor until now. 297 * 298 ******************************************************************************/ 299 300 static ACPI_STATUS 301 XfNamespaceLocateBegin ( 302 ACPI_PARSE_OBJECT *Op, 303 UINT32 Level, 304 void *Context) 305 { 306 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 307 ACPI_NAMESPACE_NODE *Node; 308 ACPI_STATUS Status; 309 ACPI_OBJECT_TYPE ObjectType; 310 char *Path; 311 UINT8 PassedArgs; 312 ACPI_PARSE_OBJECT *NextOp; 313 ACPI_PARSE_OBJECT *OwningOp; 314 ACPI_PARSE_OBJECT *SpaceIdOp; 315 UINT32 MinimumLength; 316 UINT32 Offset; 317 UINT32 FieldBitLength; 318 UINT32 TagBitLength; 319 UINT8 Message = 0; 320 const ACPI_OPCODE_INFO *OpInfo; 321 UINT32 Flags; 322 ASL_METHOD_LOCAL *MethodLocals = NULL; 323 ASL_METHOD_LOCAL *MethodArgs = NULL; 324 int RegisterNumber; 325 UINT32 i; 326 ACPI_NAMESPACE_NODE *DeclarationParentMethod; 327 ACPI_PARSE_OBJECT *ReferenceParentMethod; 328 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 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 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 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 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