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