1 /****************************************************************************** 2 * 3 * Module Name: aslxref - Namespace cross-reference 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, 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 ACPI_PARSE_OBJECT * 70 XfGetParentMethod ( 71 ACPI_PARSE_OBJECT *Op); 72 73 static BOOLEAN 74 XfObjectExists ( 75 char *Name); 76 77 static ACPI_STATUS 78 XfCompareOneNamespaceObject ( 79 ACPI_HANDLE ObjHandle, 80 UINT32 Level, 81 void *Context, 82 void **ReturnValue); 83 84 static void 85 XfCheckFieldRange ( 86 ACPI_PARSE_OBJECT *Op, 87 UINT32 RegionBitLength, 88 UINT32 FieldBitOffset, 89 UINT32 FieldBitLength, 90 UINT32 AccessBitWidth); 91 92 93 /******************************************************************************* 94 * 95 * FUNCTION: XfCrossReferenceNamespace 96 * 97 * PARAMETERS: None 98 * 99 * RETURN: Status 100 * 101 * DESCRIPTION: Perform a cross reference check of the parse tree against the 102 * namespace. Every named referenced within the parse tree 103 * should be get resolved with a namespace lookup. If not, the 104 * original reference in the ASL code is invalid -- i.e., refers 105 * to a non-existent object. 106 * 107 * NOTE: The ASL "External" operator causes the name to be inserted into the 108 * namespace so that references to the external name will be resolved 109 * correctly here. 110 * 111 ******************************************************************************/ 112 113 ACPI_STATUS 114 XfCrossReferenceNamespace ( 115 void) 116 { 117 ACPI_WALK_STATE *WalkState; 118 119 120 /* 121 * Create a new walk state for use when looking up names 122 * within the namespace (Passed as context to the callbacks) 123 */ 124 WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); 125 if (!WalkState) 126 { 127 return (AE_NO_MEMORY); 128 } 129 130 /* Walk the entire parse tree */ 131 132 TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE, 133 XfNamespaceLocateBegin, XfNamespaceLocateEnd, WalkState); 134 135 ACPI_FREE (WalkState); 136 return (AE_OK); 137 } 138 139 140 /******************************************************************************* 141 * 142 * FUNCTION: XfObjectExists 143 * 144 * PARAMETERS: Name - 4 char ACPI name 145 * 146 * RETURN: TRUE if name exists in namespace 147 * 148 * DESCRIPTION: Walk the namespace to find an object 149 * 150 ******************************************************************************/ 151 152 static BOOLEAN 153 XfObjectExists ( 154 char *Name) 155 { 156 ACPI_STATUS Status; 157 158 159 /* Walk entire namespace from the supplied root */ 160 161 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 162 ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL, 163 Name, NULL); 164 if (Status == AE_CTRL_TRUE) 165 { 166 /* At least one instance of the name was found */ 167 168 return (TRUE); 169 } 170 171 return (FALSE); 172 } 173 174 175 /******************************************************************************* 176 * 177 * FUNCTION: XfCompareOneNamespaceObject 178 * 179 * PARAMETERS: ACPI_WALK_CALLBACK 180 * 181 * RETURN: Status 182 * 183 * DESCRIPTION: Compare name of one object. 184 * 185 ******************************************************************************/ 186 187 static ACPI_STATUS 188 XfCompareOneNamespaceObject ( 189 ACPI_HANDLE ObjHandle, 190 UINT32 Level, 191 void *Context, 192 void **ReturnValue) 193 { 194 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 195 196 197 /* Simply check the name */ 198 199 if (*((UINT32 *) (Context)) == Node->Name.Integer) 200 { 201 /* Abort walk if we found one instance */ 202 203 return (AE_CTRL_TRUE); 204 } 205 206 return (AE_OK); 207 } 208 209 210 /******************************************************************************* 211 * 212 * FUNCTION: XfCheckFieldRange 213 * 214 * PARAMETERS: RegionBitLength - Length of entire parent region 215 * FieldBitOffset - Start of the field unit (within region) 216 * FieldBitLength - Entire length of field unit 217 * AccessBitWidth - Access width of the field unit 218 * 219 * RETURN: None 220 * 221 * DESCRIPTION: Check one field unit to make sure it fits in the parent 222 * op region. 223 * 224 * Note: AccessBitWidth must be either 8,16,32, or 64 225 * 226 ******************************************************************************/ 227 228 static void 229 XfCheckFieldRange ( 230 ACPI_PARSE_OBJECT *Op, 231 UINT32 RegionBitLength, 232 UINT32 FieldBitOffset, 233 UINT32 FieldBitLength, 234 UINT32 AccessBitWidth) 235 { 236 UINT32 FieldEndBitOffset; 237 238 239 /* 240 * Check each field unit against the region size. The entire 241 * field unit (start offset plus length) must fit within the 242 * region. 243 */ 244 FieldEndBitOffset = FieldBitOffset + FieldBitLength; 245 246 if (FieldEndBitOffset > RegionBitLength) 247 { 248 /* Field definition itself is beyond the end-of-region */ 249 250 AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL); 251 return; 252 } 253 254 /* 255 * Now check that the field plus AccessWidth doesn't go beyond 256 * the end-of-region. Assumes AccessBitWidth is a power of 2 257 */ 258 FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth); 259 260 if (FieldEndBitOffset > RegionBitLength) 261 { 262 /* Field definition combined with the access is beyond EOR */ 263 264 AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL); 265 } 266 } 267 268 269 /******************************************************************************* 270 * 271 * FUNCTION: XfGetParentMethod 272 * 273 * PARAMETERS: Op - Parse Op to be checked 274 * 275 * RETURN: Control method Op if found. NULL otherwise 276 * 277 * DESCRIPTION: Find the control method parent of a parse op. Returns NULL if 278 * the input Op is not within a control method. 279 * 280 ******************************************************************************/ 281 282 static ACPI_PARSE_OBJECT * 283 XfGetParentMethod ( 284 ACPI_PARSE_OBJECT *Op) 285 { 286 ACPI_PARSE_OBJECT *NextOp; 287 288 289 NextOp = Op->Asl.Parent; 290 while (NextOp) 291 { 292 if (NextOp->Asl.AmlOpcode == AML_METHOD_OP) 293 { 294 return (NextOp); 295 } 296 297 NextOp = NextOp->Asl.Parent; 298 } 299 300 return (NULL); /* No parent method found */ 301 } 302 303 /******************************************************************************* 304 * 305 * FUNCTION: XfNamespaceLocateBegin 306 * 307 * PARAMETERS: ASL_WALK_CALLBACK 308 * 309 * RETURN: Status 310 * 311 * DESCRIPTION: Descending callback used during cross-reference. For named 312 * object references, attempt to locate the name in the 313 * namespace. 314 * 315 * NOTE: ASL references to named fields within resource descriptors are 316 * resolved to integer values here. Therefore, this step is an 317 * important part of the code generation. We don't know that the 318 * name refers to a resource descriptor until now. 319 * 320 ******************************************************************************/ 321 322 static ACPI_STATUS 323 XfNamespaceLocateBegin ( 324 ACPI_PARSE_OBJECT *Op, 325 UINT32 Level, 326 void *Context) 327 { 328 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 329 ACPI_NAMESPACE_NODE *Node; 330 ACPI_STATUS Status; 331 ACPI_OBJECT_TYPE ObjectType; 332 char *Path; 333 UINT8 PassedArgs; 334 ACPI_PARSE_OBJECT *NextOp; 335 ACPI_PARSE_OBJECT *OwningOp; 336 ACPI_PARSE_OBJECT *SpaceIdOp; 337 UINT32 MinimumLength; 338 UINT32 Offset; 339 UINT32 FieldBitLength; 340 UINT32 TagBitLength; 341 UINT8 Message = 0; 342 const ACPI_OPCODE_INFO *OpInfo; 343 UINT32 Flags; 344 ASL_METHOD_LOCAL *MethodLocals = NULL; 345 ASL_METHOD_LOCAL *MethodArgs = NULL; 346 int RegisterNumber; 347 UINT32 i; 348 349 350 ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op); 351 352 353 if ((Op->Asl.AmlOpcode == AML_METHOD_OP) && Op->Asl.Node) 354 { 355 Node = Op->Asl.Node; 356 357 /* Support for method LocalX/ArgX analysis */ 358 359 if (!Node->MethodLocals) 360 { 361 /* Create local/arg info blocks */ 362 363 MethodLocals = UtLocalCalloc ( 364 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS); 365 Node->MethodLocals = MethodLocals; 366 367 MethodArgs = UtLocalCalloc ( 368 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS); 369 Node->MethodArgs = MethodArgs; 370 371 /* 372 * Get the method argument count 373 * First, get the name node 374 */ 375 NextOp = Op->Asl.Child; 376 377 /* Get the NumArguments node */ 378 379 NextOp = NextOp->Asl.Next; 380 Node->ArgCount = (UINT8) 381 (((UINT8) NextOp->Asl.Value.Integer) & 0x07); 382 383 /* We will track all posible ArgXs */ 384 385 for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) 386 { 387 if (i < Node->ArgCount) 388 { 389 /* Real Args are always "initialized" */ 390 391 MethodArgs[i].Flags = ASL_ARG_INITIALIZED; 392 } 393 else 394 { 395 /* Other ArgXs can be used as locals */ 396 397 MethodArgs[i].Flags = ASL_ARG_IS_LOCAL; 398 } 399 400 MethodArgs[i].Op = Op; 401 } 402 } 403 } 404 405 /* 406 * If this node is the actual declaration of a name 407 * [such as the XXXX name in "Method (XXXX)"], 408 * we are not interested in it here. We only care about names that are 409 * references to other objects within the namespace and the parent objects 410 * of name declarations 411 */ 412 if (Op->Asl.CompileFlags & OP_IS_NAME_DECLARATION) 413 { 414 return_ACPI_STATUS (AE_OK); 415 } 416 417 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 418 419 /* Check method LocalX variables */ 420 421 if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE) 422 { 423 /* Find parent method Op */ 424 425 NextOp = XfGetParentMethod (Op); 426 if (!NextOp) 427 { 428 return_ACPI_STATUS (AE_OK); 429 } 430 431 /* Get method node */ 432 433 Node = NextOp->Asl.Node; 434 435 RegisterNumber = Op->Asl.AmlOpcode & 0x0007; /* 0x60 through 0x67 */ 436 MethodLocals = Node->MethodLocals; 437 438 if (Op->Asl.CompileFlags & OP_IS_TARGET) 439 { 440 /* Local is being initialized */ 441 442 MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_INITIALIZED; 443 MethodLocals[RegisterNumber].Op = Op; 444 445 return_ACPI_STATUS (AE_OK); 446 } 447 448 /* Mark this Local as referenced */ 449 450 MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_REFERENCED; 451 MethodLocals[RegisterNumber].Op = Op; 452 453 return_ACPI_STATUS (AE_OK); 454 } 455 456 /* Check method ArgX variables */ 457 458 if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT) 459 { 460 /* Find parent method Op */ 461 462 NextOp = XfGetParentMethod (Op); 463 if (!NextOp) 464 { 465 return_ACPI_STATUS (AE_OK); 466 } 467 468 /* Get method node */ 469 470 Node = NextOp->Asl.Node; 471 472 /* Get Arg # */ 473 474 RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */ 475 MethodArgs = Node->MethodArgs; 476 477 /* Mark this Arg as referenced */ 478 479 MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED; 480 MethodArgs[RegisterNumber].Op = Op; 481 482 if (Op->Asl.CompileFlags & OP_IS_TARGET) 483 { 484 /* Arg is being initialized */ 485 486 MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED; 487 } 488 489 return_ACPI_STATUS (AE_OK); 490 } 491 492 /* 493 * After method ArgX and LocalX, we are only interested in opcodes 494 * that have an associated name 495 */ 496 if ((!(OpInfo->Flags & AML_NAMED)) && 497 (!(OpInfo->Flags & AML_CREATE)) && 498 (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) && 499 (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) && 500 (Op->Asl.ParseOpcode != PARSEOP_METHODCALL) && 501 (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL)) 502 { 503 return_ACPI_STATUS (AE_OK); 504 } 505 506 /* 507 * One special case: CondRefOf operator - we don't care if the name exists 508 * or not at this point, just ignore it, the point of the operator is to 509 * determine if the name exists at runtime. 510 */ 511 if ((Op->Asl.Parent) && 512 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)) 513 { 514 return_ACPI_STATUS (AE_OK); 515 } 516 517 /* 518 * We must enable the "search-to-root" for single NameSegs, but 519 * we have to be very careful about opening up scopes 520 */ 521 Flags = ACPI_NS_SEARCH_PARENT; 522 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 523 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 524 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) || 525 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)) 526 { 527 /* 528 * These are name references, do not push the scope stack 529 * for them. 530 */ 531 Flags |= ACPI_NS_DONT_OPEN_SCOPE; 532 } 533 534 /* Get the NamePath from the appropriate place */ 535 536 if (OpInfo->Flags & AML_NAMED) 537 { 538 /* For nearly all NAMED operators, the name reference is the first child */ 539 540 Path = Op->Asl.Child->Asl.Value.String; 541 if (Op->Asl.AmlOpcode == AML_ALIAS_OP) 542 { 543 /* 544 * ALIAS is the only oddball opcode, the name declaration 545 * (alias name) is the second operand 546 */ 547 Path = Op->Asl.Child->Asl.Next->Asl.Value.String; 548 } 549 } 550 else if (OpInfo->Flags & AML_CREATE) 551 { 552 /* Name must appear as the last parameter */ 553 554 NextOp = Op->Asl.Child; 555 while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION)) 556 { 557 NextOp = NextOp->Asl.Next; 558 } 559 560 Path = NextOp->Asl.Value.String; 561 } 562 else 563 { 564 Path = Op->Asl.Value.String; 565 } 566 567 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 568 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 569 "Type=%s\n", AcpiUtGetTypeName (ObjectType))); 570 571 /* 572 * Lookup the name in the namespace. Name must exist at this point, or it 573 * is an invalid reference. 574 * 575 * The namespace is also used as a lookup table for references to resource 576 * descriptors and the fields within them. 577 */ 578 AslGbl_NsLookupCount++; 579 580 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 581 ACPI_IMODE_EXECUTE, Flags, WalkState, &Node); 582 if (ACPI_FAILURE (Status)) 583 { 584 if (Status == AE_NOT_FOUND) 585 { 586 /* 587 * We didn't find the name reference by path -- we can qualify this 588 * a little better before we print an error message 589 */ 590 if (strlen (Path) == ACPI_NAME_SIZE) 591 { 592 /* A simple, one-segment ACPI name */ 593 594 if (XfObjectExists (Path)) 595 { 596 /* 597 * There exists such a name, but we couldn't get to it 598 * from this scope 599 */ 600 AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op, 601 Op->Asl.ExternalName); 602 } 603 else 604 { 605 /* The name doesn't exist, period */ 606 607 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, 608 Op, Op->Asl.ExternalName); 609 } 610 } 611 else 612 { 613 /* The NamePath contains multiple NameSegs */ 614 615 if ((OpInfo->Flags & AML_CREATE) || 616 (OpInfo->ObjectType == ACPI_TYPE_LOCAL_ALIAS)) 617 { 618 /* 619 * The new name is the last parameter. For the 620 * CreateXXXXField and Alias operators 621 */ 622 NextOp = Op->Asl.Child; 623 while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION)) 624 { 625 NextOp = NextOp->Asl.Next; 626 } 627 628 AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, NextOp, 629 NextOp->Asl.ExternalName); 630 } 631 else if (OpInfo->Flags & AML_NAMED) 632 { 633 /* The new name is the first parameter */ 634 635 AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, Op, 636 Op->Asl.ExternalName); 637 } 638 else if (Path[0] == AML_ROOT_PREFIX) 639 { 640 /* Full namepath from root, the object does not exist */ 641 642 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, 643 Op->Asl.ExternalName); 644 } 645 else 646 { 647 /* 648 * Generic "not found" error. Cannot determine whether it 649 * doesn't exist or just can't be reached. However, we 650 * can differentiate between a NameSeg vs. NamePath. 651 */ 652 if (strlen (Op->Asl.ExternalName) == ACPI_NAME_SIZE) 653 { 654 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 655 Op->Asl.ExternalName); 656 } 657 else 658 { 659 AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op, 660 Op->Asl.ExternalName); 661 } 662 } 663 } 664 665 Status = AE_OK; 666 } 667 668 return_ACPI_STATUS (Status); 669 } 670 671 /* Object was found above, check for an illegal forward reference */ 672 673 if (Op->Asl.CompileFlags & OP_NOT_FOUND_DURING_LOAD) 674 { 675 /* 676 * During the load phase, this Op was flagged as a possible 677 * illegal forward reference 678 * 679 * Note: Allow "forward references" from within a method to an 680 * object that is not within any method (module-level code) 681 */ 682 if (!WalkState->ScopeInfo || (UtGetParentMethod (Node) && 683 !UtNodeIsDescendantOf (WalkState->ScopeInfo->Scope.Node, 684 UtGetParentMethod (Node)))) 685 { 686 AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op, 687 Op->Asl.ExternalName); 688 } 689 } 690 691 /* Check for a reference vs. name declaration */ 692 693 if (!(OpInfo->Flags & AML_NAMED) && 694 !(OpInfo->Flags & AML_CREATE)) 695 { 696 /* This node has been referenced, mark it for reference check */ 697 698 Node->Flags |= ANOBJ_IS_REFERENCED; 699 } 700 701 /* Attempt to optimize the NamePath */ 702 703 OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node); 704 705 /* 706 * 1) Dereference an alias (A name reference that is an alias) 707 * Aliases are not nested, the alias always points to the final object 708 */ 709 if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) && 710 (Node->Type == ACPI_TYPE_LOCAL_ALIAS)) 711 { 712 /* This node points back to the original PARSEOP_ALIAS */ 713 714 NextOp = Node->Op; 715 716 /* The first child is the alias target op */ 717 718 NextOp = NextOp->Asl.Child; 719 720 /* That in turn points back to original target alias node */ 721 722 if (NextOp->Asl.Node) 723 { 724 Node = NextOp->Asl.Node; 725 } 726 727 /* Else - forward reference to alias, will be resolved later */ 728 } 729 730 /* 2) Check for a reference to a resource descriptor */ 731 732 if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 733 (Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 734 { 735 /* 736 * This was a reference to a field within a resource descriptor. 737 * Extract the associated field offset (either a bit or byte 738 * offset depending on the field type) and change the named 739 * reference into an integer for AML code generation 740 */ 741 Offset = Node->Value; 742 TagBitLength = Node->Length; 743 744 /* 745 * If a field is being created, generate the length (in bits) of 746 * the field. Note: Opcodes other than CreateXxxField and Index 747 * can come through here. For other opcodes, we just need to 748 * convert the resource tag reference to an integer offset. 749 */ 750 switch (Op->Asl.Parent->Asl.AmlOpcode) 751 { 752 case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */ 753 /* 754 * We know the length operand is an integer constant because 755 * we know that it contains a reference to a resource 756 * descriptor tag. 757 */ 758 FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer; 759 break; 760 761 case AML_CREATE_BIT_FIELD_OP: 762 763 FieldBitLength = 1; 764 break; 765 766 case AML_CREATE_BYTE_FIELD_OP: 767 case AML_INDEX_OP: 768 769 FieldBitLength = 8; 770 break; 771 772 case AML_CREATE_WORD_FIELD_OP: 773 774 FieldBitLength = 16; 775 break; 776 777 case AML_CREATE_DWORD_FIELD_OP: 778 779 FieldBitLength = 32; 780 break; 781 782 case AML_CREATE_QWORD_FIELD_OP: 783 784 FieldBitLength = 64; 785 break; 786 787 default: 788 789 FieldBitLength = 0; 790 break; 791 } 792 793 /* Check the field length against the length of the resource tag */ 794 795 if (FieldBitLength) 796 { 797 if (TagBitLength < FieldBitLength) 798 { 799 Message = ASL_MSG_TAG_SMALLER; 800 } 801 else if (TagBitLength > FieldBitLength) 802 { 803 Message = ASL_MSG_TAG_LARGER; 804 } 805 806 if (Message) 807 { 808 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), 809 "Size mismatch, Tag: %u bit%s, Field: %u bit%s", 810 TagBitLength, (TagBitLength > 1) ? "s" : "", 811 FieldBitLength, (FieldBitLength > 1) ? "s" : ""); 812 813 AslError (ASL_WARNING, Message, Op, AslGbl_MsgBuffer); 814 } 815 } 816 817 /* Convert the BitOffset to a ByteOffset for certain opcodes */ 818 819 switch (Op->Asl.Parent->Asl.AmlOpcode) 820 { 821 case AML_CREATE_BYTE_FIELD_OP: 822 case AML_CREATE_WORD_FIELD_OP: 823 case AML_CREATE_DWORD_FIELD_OP: 824 case AML_CREATE_QWORD_FIELD_OP: 825 case AML_INDEX_OP: 826 827 Offset = ACPI_DIV_8 (Offset); 828 break; 829 830 default: 831 832 break; 833 } 834 835 /* Now convert this node to an integer whose value is the field offset */ 836 837 Op->Asl.AmlLength = 0; 838 Op->Asl.ParseOpcode = PARSEOP_INTEGER; 839 Op->Asl.Value.Integer = (UINT64) Offset; 840 Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD; 841 842 OpcGenerateAmlOpcode (Op); 843 } 844 845 /* 3) Check for a method invocation */ 846 847 else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) && 848 (Node->Type == ACPI_TYPE_METHOD) && 849 (Op->Asl.Parent) && 850 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) || 851 852 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 853 { 854 /* 855 * A reference to a method within one of these opcodes is not an 856 * invocation of the method, it is simply a reference to the method. 857 * 858 * September 2016: Removed DeRefOf from this list 859 */ 860 if ((Op->Asl.Parent) && 861 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) || 862 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE) || 863 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)|| 864 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE))) 865 { 866 return_ACPI_STATUS (AE_OK); 867 } 868 869 /* 870 * There are two types of method invocation: 871 * 1) Invocation with arguments -- the parser recognizes this 872 * as a METHODCALL. 873 * 2) Invocation with no arguments --the parser cannot determine that 874 * this is a method invocation, therefore we have to figure it out 875 * here. 876 */ 877 if (Node->Type != ACPI_TYPE_METHOD) 878 { 879 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s is a %s", 880 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 881 882 AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, AslGbl_MsgBuffer); 883 return_ACPI_STATUS (AE_OK); 884 } 885 886 /* Save the method node in the caller's op */ 887 888 Op->Asl.Node = Node; 889 if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF) 890 { 891 return_ACPI_STATUS (AE_OK); 892 } 893 894 /* 895 * This is a method invocation, with or without arguments. 896 * Count the number of arguments, each appears as a child 897 * under the parent node 898 */ 899 Op->Asl.ParseOpcode = PARSEOP_METHODCALL; 900 UtSetParseOpName (Op); 901 902 PassedArgs = 0; 903 NextOp = Op->Asl.Child; 904 905 while (NextOp) 906 { 907 PassedArgs++; 908 NextOp = NextOp->Asl.Next; 909 } 910 911 if (Node->Value != ASL_EXTERNAL_METHOD && 912 Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL) 913 { 914 /* 915 * Check the parsed arguments with the number expected by the 916 * method declaration itself 917 */ 918 if (PassedArgs != Node->Value) 919 { 920 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s requires %u", Op->Asl.ExternalName, 921 Node->Value); 922 923 if (PassedArgs < Node->Value) 924 { 925 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, AslGbl_MsgBuffer); 926 } 927 else 928 { 929 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, AslGbl_MsgBuffer); 930 } 931 } 932 } 933 } 934 935 /* 4) Check for an ASL Field definition */ 936 937 else if ((Op->Asl.Parent) && 938 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) || 939 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD))) 940 { 941 /* 942 * Offset checking for fields. If the parent operation region has a 943 * constant length (known at compile time), we can check fields 944 * defined in that region against the region length. This will catch 945 * fields and field units that cannot possibly fit within the region. 946 * 947 * Note: Index fields do not directly reference an operation region, 948 * thus they are not included in this check. 949 */ 950 if (Op == Op->Asl.Parent->Asl.Child) 951 { 952 /* 953 * This is the first child of the field node, which is 954 * the name of the region. Get the parse node for the 955 * region -- which contains the length of the region. 956 */ 957 OwningOp = Node->Op; 958 Op->Asl.Parent->Asl.ExtraValue = 959 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer); 960 961 /* Examine the field access width */ 962 963 switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer) 964 { 965 case AML_FIELD_ACCESS_ANY: 966 case AML_FIELD_ACCESS_BYTE: 967 case AML_FIELD_ACCESS_BUFFER: 968 default: 969 970 MinimumLength = 1; 971 break; 972 973 case AML_FIELD_ACCESS_WORD: 974 975 MinimumLength = 2; 976 break; 977 978 case AML_FIELD_ACCESS_DWORD: 979 980 MinimumLength = 4; 981 break; 982 983 case AML_FIELD_ACCESS_QWORD: 984 985 MinimumLength = 8; 986 break; 987 } 988 989 /* 990 * Is the region at least as big as the access width? 991 * Note: DataTableRegions have 0 length 992 */ 993 if (((UINT32) OwningOp->Asl.Value.Integer) && 994 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength)) 995 { 996 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL); 997 } 998 999 /* 1000 * Check EC/CMOS/SMBUS fields to make sure that the correct 1001 * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS) 1002 */ 1003 SpaceIdOp = OwningOp->Asl.Child->Asl.Next; 1004 switch ((UINT32) SpaceIdOp->Asl.Value.Integer) 1005 { 1006 case ACPI_ADR_SPACE_EC: 1007 case ACPI_ADR_SPACE_CMOS: 1008 case ACPI_ADR_SPACE_GPIO: 1009 1010 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != 1011 AML_FIELD_ACCESS_BYTE) 1012 { 1013 AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL); 1014 } 1015 break; 1016 1017 case ACPI_ADR_SPACE_SMBUS: 1018 case ACPI_ADR_SPACE_IPMI: 1019 case ACPI_ADR_SPACE_GSBUS: 1020 1021 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != 1022 AML_FIELD_ACCESS_BUFFER) 1023 { 1024 AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL); 1025 } 1026 break; 1027 1028 default: 1029 1030 /* Nothing to do for other address spaces */ 1031 1032 break; 1033 } 1034 } 1035 else 1036 { 1037 /* 1038 * This is one element of the field list. Check to make sure 1039 * that it does not go beyond the end of the parent operation region. 1040 * 1041 * In the code below: 1042 * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits) 1043 * Op->Asl.ExtraValue - Field start offset (bits) 1044 * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits) 1045 * Op->Asl.Child->Asl.ExtraValue - Field access width (bits) 1046 */ 1047 if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child) 1048 { 1049 XfCheckFieldRange (Op, 1050 Op->Asl.Parent->Asl.ExtraValue, 1051 Op->Asl.ExtraValue, 1052 (UINT32) Op->Asl.Child->Asl.Value.Integer, 1053 Op->Asl.Child->Asl.ExtraValue); 1054 } 1055 } 1056 } 1057 1058 /* 5) Check for a connection object */ 1059 #if 0 1060 else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION) 1061 { 1062 return_ACPI_STATUS (Status); 1063 } 1064 #endif 1065 1066 Op->Asl.Node = Node; 1067 return_ACPI_STATUS (Status); 1068 } 1069 1070 1071 /******************************************************************************* 1072 * 1073 * FUNCTION: XfNamespaceLocateEnd 1074 * 1075 * PARAMETERS: ASL_WALK_CALLBACK 1076 * 1077 * RETURN: Status 1078 * 1079 * DESCRIPTION: Ascending callback used during cross reference. We only 1080 * need to worry about scope management here. 1081 * 1082 ******************************************************************************/ 1083 1084 static ACPI_STATUS 1085 XfNamespaceLocateEnd ( 1086 ACPI_PARSE_OBJECT *Op, 1087 UINT32 Level, 1088 void *Context) 1089 { 1090 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 1091 const ACPI_OPCODE_INFO *OpInfo; 1092 1093 1094 ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd); 1095 1096 1097 /* We are only interested in opcodes that have an associated name */ 1098 1099 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1100 if (!(OpInfo->Flags & AML_NAMED)) 1101 { 1102 return_ACPI_STATUS (AE_OK); 1103 } 1104 1105 /* Not interested in name references, we did not open a scope for them */ 1106 1107 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 1108 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 1109 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) || 1110 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)) 1111 { 1112 return_ACPI_STATUS (AE_OK); 1113 } 1114 1115 /* Pop the scope stack if necessary */ 1116 1117 if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode))) 1118 { 1119 1120 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 1121 "%s: Popping scope for Op %p\n", 1122 AcpiUtGetTypeName (OpInfo->ObjectType), Op)); 1123 1124 (void) AcpiDsScopeStackPop (WalkState); 1125 } 1126 1127 return_ACPI_STATUS (AE_OK); 1128 } 1129