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