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