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