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 (Gbl_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 Gbl_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 /* Check for a fully qualified path */ 614 615 if (Path[0] == AML_ROOT_PREFIX) 616 { 617 /* Gave full path, the object does not exist */ 618 619 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, 620 Op->Asl.ExternalName); 621 } 622 else 623 { 624 /* 625 * We can't tell whether it doesn't exist or just 626 * can't be reached. 627 */ 628 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 629 Op->Asl.ExternalName); 630 } 631 } 632 633 Status = AE_OK; 634 } 635 636 return_ACPI_STATUS (Status); 637 } 638 639 /* Object was found above, check for an illegal forward reference */ 640 641 if (Op->Asl.CompileFlags & OP_NOT_FOUND_DURING_LOAD) 642 { 643 /* 644 * During the load phase, this Op was flagged as a possible 645 * illegal forward reference 646 * 647 * Note: Allow "forward references" from within a method to an 648 * object that is not within any method (module-level code) 649 */ 650 if (!WalkState->ScopeInfo || (UtGetParentMethod (Node) && 651 !UtNodeIsDescendantOf (WalkState->ScopeInfo->Scope.Node, 652 UtGetParentMethod (Node)))) 653 { 654 AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op, 655 Op->Asl.ExternalName); 656 } 657 } 658 659 /* Check for a reference vs. name declaration */ 660 661 if (!(OpInfo->Flags & AML_NAMED) && 662 !(OpInfo->Flags & AML_CREATE)) 663 { 664 /* This node has been referenced, mark it for reference check */ 665 666 Node->Flags |= ANOBJ_IS_REFERENCED; 667 } 668 669 /* Attempt to optimize the NamePath */ 670 671 OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node); 672 673 /* 674 * 1) Dereference an alias (A name reference that is an alias) 675 * Aliases are not nested, the alias always points to the final object 676 */ 677 if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) && 678 (Node->Type == ACPI_TYPE_LOCAL_ALIAS)) 679 { 680 /* This node points back to the original PARSEOP_ALIAS */ 681 682 NextOp = Node->Op; 683 684 /* The first child is the alias target op */ 685 686 NextOp = NextOp->Asl.Child; 687 688 /* That in turn points back to original target alias node */ 689 690 if (NextOp->Asl.Node) 691 { 692 Node = NextOp->Asl.Node; 693 } 694 695 /* Else - forward reference to alias, will be resolved later */ 696 } 697 698 /* 2) Check for a reference to a resource descriptor */ 699 700 if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 701 (Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 702 { 703 /* 704 * This was a reference to a field within a resource descriptor. 705 * Extract the associated field offset (either a bit or byte 706 * offset depending on the field type) and change the named 707 * reference into an integer for AML code generation 708 */ 709 Offset = Node->Value; 710 TagBitLength = Node->Length; 711 712 /* 713 * If a field is being created, generate the length (in bits) of 714 * the field. Note: Opcodes other than CreateXxxField and Index 715 * can come through here. For other opcodes, we just need to 716 * convert the resource tag reference to an integer offset. 717 */ 718 switch (Op->Asl.Parent->Asl.AmlOpcode) 719 { 720 case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */ 721 /* 722 * We know the length operand is an integer constant because 723 * we know that it contains a reference to a resource 724 * descriptor tag. 725 */ 726 FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer; 727 break; 728 729 case AML_CREATE_BIT_FIELD_OP: 730 731 FieldBitLength = 1; 732 break; 733 734 case AML_CREATE_BYTE_FIELD_OP: 735 case AML_INDEX_OP: 736 737 FieldBitLength = 8; 738 break; 739 740 case AML_CREATE_WORD_FIELD_OP: 741 742 FieldBitLength = 16; 743 break; 744 745 case AML_CREATE_DWORD_FIELD_OP: 746 747 FieldBitLength = 32; 748 break; 749 750 case AML_CREATE_QWORD_FIELD_OP: 751 752 FieldBitLength = 64; 753 break; 754 755 default: 756 757 FieldBitLength = 0; 758 break; 759 } 760 761 /* Check the field length against the length of the resource tag */ 762 763 if (FieldBitLength) 764 { 765 if (TagBitLength < FieldBitLength) 766 { 767 Message = ASL_MSG_TAG_SMALLER; 768 } 769 else if (TagBitLength > FieldBitLength) 770 { 771 Message = ASL_MSG_TAG_LARGER; 772 } 773 774 if (Message) 775 { 776 snprintf (MsgBuffer, sizeof(MsgBuffer), 777 "Size mismatch, Tag: %u bit%s, Field: %u bit%s", 778 TagBitLength, (TagBitLength > 1) ? "s" : "", 779 FieldBitLength, (FieldBitLength > 1) ? "s" : ""); 780 781 AslError (ASL_WARNING, Message, Op, MsgBuffer); 782 } 783 } 784 785 /* Convert the BitOffset to a ByteOffset for certain opcodes */ 786 787 switch (Op->Asl.Parent->Asl.AmlOpcode) 788 { 789 case AML_CREATE_BYTE_FIELD_OP: 790 case AML_CREATE_WORD_FIELD_OP: 791 case AML_CREATE_DWORD_FIELD_OP: 792 case AML_CREATE_QWORD_FIELD_OP: 793 case AML_INDEX_OP: 794 795 Offset = ACPI_DIV_8 (Offset); 796 break; 797 798 default: 799 800 break; 801 } 802 803 /* Now convert this node to an integer whose value is the field offset */ 804 805 Op->Asl.AmlLength = 0; 806 Op->Asl.ParseOpcode = PARSEOP_INTEGER; 807 Op->Asl.Value.Integer = (UINT64) Offset; 808 Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD; 809 810 OpcGenerateAmlOpcode (Op); 811 } 812 813 /* 3) Check for a method invocation */ 814 815 else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) && 816 (Node->Type == ACPI_TYPE_METHOD) && 817 (Op->Asl.Parent) && 818 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) || 819 820 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 821 { 822 /* 823 * A reference to a method within one of these opcodes is not an 824 * invocation of the method, it is simply a reference to the method. 825 * 826 * September 2016: Removed DeRefOf from this list 827 */ 828 if ((Op->Asl.Parent) && 829 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) || 830 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE) || 831 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)|| 832 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE))) 833 { 834 return_ACPI_STATUS (AE_OK); 835 } 836 837 /* 838 * There are two types of method invocation: 839 * 1) Invocation with arguments -- the parser recognizes this 840 * as a METHODCALL. 841 * 2) Invocation with no arguments --the parser cannot determine that 842 * this is a method invocation, therefore we have to figure it out 843 * here. 844 */ 845 if (Node->Type != ACPI_TYPE_METHOD) 846 { 847 snprintf (MsgBuffer, sizeof(MsgBuffer), "%s is a %s", 848 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 849 850 AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer); 851 return_ACPI_STATUS (AE_OK); 852 } 853 854 /* Save the method node in the caller's op */ 855 856 Op->Asl.Node = Node; 857 if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF) 858 { 859 return_ACPI_STATUS (AE_OK); 860 } 861 862 /* 863 * This is a method invocation, with or without arguments. 864 * Count the number of arguments, each appears as a child 865 * under the parent node 866 */ 867 Op->Asl.ParseOpcode = PARSEOP_METHODCALL; 868 UtSetParseOpName (Op); 869 870 PassedArgs = 0; 871 NextOp = Op->Asl.Child; 872 873 while (NextOp) 874 { 875 PassedArgs++; 876 NextOp = NextOp->Asl.Next; 877 } 878 879 if (Node->Value != ASL_EXTERNAL_METHOD && 880 Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL) 881 { 882 /* 883 * Check the parsed arguments with the number expected by the 884 * method declaration itself 885 */ 886 if (PassedArgs != Node->Value) 887 { 888 snprintf (MsgBuffer, sizeof(MsgBuffer), "%s requires %u", Op->Asl.ExternalName, 889 Node->Value); 890 891 if (PassedArgs < Node->Value) 892 { 893 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer); 894 } 895 else 896 { 897 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer); 898 } 899 } 900 } 901 } 902 903 /* 4) Check for an ASL Field definition */ 904 905 else if ((Op->Asl.Parent) && 906 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) || 907 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD))) 908 { 909 /* 910 * Offset checking for fields. If the parent operation region has a 911 * constant length (known at compile time), we can check fields 912 * defined in that region against the region length. This will catch 913 * fields and field units that cannot possibly fit within the region. 914 * 915 * Note: Index fields do not directly reference an operation region, 916 * thus they are not included in this check. 917 */ 918 if (Op == Op->Asl.Parent->Asl.Child) 919 { 920 /* 921 * This is the first child of the field node, which is 922 * the name of the region. Get the parse node for the 923 * region -- which contains the length of the region. 924 */ 925 OwningOp = Node->Op; 926 Op->Asl.Parent->Asl.ExtraValue = 927 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer); 928 929 /* Examine the field access width */ 930 931 switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer) 932 { 933 case AML_FIELD_ACCESS_ANY: 934 case AML_FIELD_ACCESS_BYTE: 935 case AML_FIELD_ACCESS_BUFFER: 936 default: 937 938 MinimumLength = 1; 939 break; 940 941 case AML_FIELD_ACCESS_WORD: 942 943 MinimumLength = 2; 944 break; 945 946 case AML_FIELD_ACCESS_DWORD: 947 948 MinimumLength = 4; 949 break; 950 951 case AML_FIELD_ACCESS_QWORD: 952 953 MinimumLength = 8; 954 break; 955 } 956 957 /* 958 * Is the region at least as big as the access width? 959 * Note: DataTableRegions have 0 length 960 */ 961 if (((UINT32) OwningOp->Asl.Value.Integer) && 962 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength)) 963 { 964 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL); 965 } 966 967 /* 968 * Check EC/CMOS/SMBUS fields to make sure that the correct 969 * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS) 970 */ 971 SpaceIdOp = OwningOp->Asl.Child->Asl.Next; 972 switch ((UINT32) SpaceIdOp->Asl.Value.Integer) 973 { 974 case ACPI_ADR_SPACE_EC: 975 case ACPI_ADR_SPACE_CMOS: 976 case ACPI_ADR_SPACE_GPIO: 977 978 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != 979 AML_FIELD_ACCESS_BYTE) 980 { 981 AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL); 982 } 983 break; 984 985 case ACPI_ADR_SPACE_SMBUS: 986 case ACPI_ADR_SPACE_IPMI: 987 case ACPI_ADR_SPACE_GSBUS: 988 989 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != 990 AML_FIELD_ACCESS_BUFFER) 991 { 992 AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL); 993 } 994 break; 995 996 default: 997 998 /* Nothing to do for other address spaces */ 999 1000 break; 1001 } 1002 } 1003 else 1004 { 1005 /* 1006 * This is one element of the field list. Check to make sure 1007 * that it does not go beyond the end of the parent operation region. 1008 * 1009 * In the code below: 1010 * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits) 1011 * Op->Asl.ExtraValue - Field start offset (bits) 1012 * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits) 1013 * Op->Asl.Child->Asl.ExtraValue - Field access width (bits) 1014 */ 1015 if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child) 1016 { 1017 XfCheckFieldRange (Op, 1018 Op->Asl.Parent->Asl.ExtraValue, 1019 Op->Asl.ExtraValue, 1020 (UINT32) Op->Asl.Child->Asl.Value.Integer, 1021 Op->Asl.Child->Asl.ExtraValue); 1022 } 1023 } 1024 } 1025 1026 /* 5) Check for a connection object */ 1027 #if 0 1028 else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION) 1029 { 1030 return_ACPI_STATUS (Status); 1031 } 1032 #endif 1033 1034 Op->Asl.Node = Node; 1035 return_ACPI_STATUS (Status); 1036 } 1037 1038 1039 /******************************************************************************* 1040 * 1041 * FUNCTION: XfNamespaceLocateEnd 1042 * 1043 * PARAMETERS: ASL_WALK_CALLBACK 1044 * 1045 * RETURN: Status 1046 * 1047 * DESCRIPTION: Ascending callback used during cross reference. We only 1048 * need to worry about scope management here. 1049 * 1050 ******************************************************************************/ 1051 1052 static ACPI_STATUS 1053 XfNamespaceLocateEnd ( 1054 ACPI_PARSE_OBJECT *Op, 1055 UINT32 Level, 1056 void *Context) 1057 { 1058 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 1059 const ACPI_OPCODE_INFO *OpInfo; 1060 1061 1062 ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd); 1063 1064 1065 /* We are only interested in opcodes that have an associated name */ 1066 1067 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1068 if (!(OpInfo->Flags & AML_NAMED)) 1069 { 1070 return_ACPI_STATUS (AE_OK); 1071 } 1072 1073 /* Not interested in name references, we did not open a scope for them */ 1074 1075 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 1076 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 1077 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) || 1078 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)) 1079 { 1080 return_ACPI_STATUS (AE_OK); 1081 } 1082 1083 /* Pop the scope stack if necessary */ 1084 1085 if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode))) 1086 { 1087 1088 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 1089 "%s: Popping scope for Op %p\n", 1090 AcpiUtGetTypeName (OpInfo->ObjectType), Op)); 1091 1092 (void) AcpiDsScopeStackPop (WalkState); 1093 } 1094 1095 return_ACPI_STATUS (AE_OK); 1096 } 1097