1 /****************************************************************************** 2 * 3 * Module Name: aslxref - Namespace cross-reference 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, 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 /* Mark this Arg as referenced */ 494 495 MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED; 496 MethodArgs[RegisterNumber].Op = Op; 497 498 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 499 { 500 /* Arg is being initialized */ 501 502 MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED; 503 } 504 505 return_ACPI_STATUS (AE_OK); 506 } 507 508 /* 509 * After method ArgX and LocalX, we are only interested in opcodes 510 * that have an associated name 511 */ 512 if ((!(OpInfo->Flags & AML_NAMED)) && 513 (!(OpInfo->Flags & AML_CREATE)) && 514 (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) && 515 (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) && 516 (Op->Asl.ParseOpcode != PARSEOP_METHODCALL)) 517 { 518 return_ACPI_STATUS (AE_OK); 519 } 520 521 /* 522 * One special case: CondRefOf operator - we don't care if the name exists 523 * or not at this point, just ignore it, the point of the operator is to 524 * determine if the name exists at runtime. 525 */ 526 if ((Op->Asl.Parent) && 527 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)) 528 { 529 return_ACPI_STATUS (AE_OK); 530 } 531 532 /* 533 * We must enable the "search-to-root" for single NameSegs, but 534 * we have to be very careful about opening up scopes 535 */ 536 Flags = ACPI_NS_SEARCH_PARENT; 537 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 538 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 539 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 540 { 541 /* 542 * These are name references, do not push the scope stack 543 * for them. 544 */ 545 Flags |= ACPI_NS_DONT_OPEN_SCOPE; 546 } 547 548 /* Get the NamePath from the appropriate place */ 549 550 if (OpInfo->Flags & AML_NAMED) 551 { 552 /* For nearly all NAMED operators, the name reference is the first child */ 553 554 Path = Op->Asl.Child->Asl.Value.String; 555 if (Op->Asl.AmlOpcode == AML_ALIAS_OP) 556 { 557 /* 558 * ALIAS is the only oddball opcode, the name declaration 559 * (alias name) is the second operand 560 */ 561 Path = Op->Asl.Child->Asl.Next->Asl.Value.String; 562 } 563 } 564 else if (OpInfo->Flags & AML_CREATE) 565 { 566 /* Name must appear as the last parameter */ 567 568 NextOp = Op->Asl.Child; 569 while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) 570 { 571 NextOp = NextOp->Asl.Next; 572 } 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 #ifdef __UNDER_DEVELOPMENT 663 664 /* Check for an illegal reference */ 665 666 XfCheckIllegalReference (Op, Node); 667 #endif 668 } 669 670 /* Attempt to optimize the NamePath */ 671 672 OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node); 673 674 /* 675 * 1) Dereference an alias (A name reference that is an alias) 676 * Aliases are not nested, the alias always points to the final object 677 */ 678 if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) && 679 (Node->Type == ACPI_TYPE_LOCAL_ALIAS)) 680 { 681 /* This node points back to the original PARSEOP_ALIAS */ 682 683 NextOp = Node->Op; 684 685 /* The first child is the alias target op */ 686 687 NextOp = NextOp->Asl.Child; 688 689 /* That in turn points back to original target alias node */ 690 691 if (NextOp->Asl.Node) 692 { 693 Node = NextOp->Asl.Node; 694 } 695 696 /* Else - forward reference to alias, will be resolved later */ 697 } 698 699 /* 2) Check for a reference to a resource descriptor */ 700 701 if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 702 (Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 703 { 704 /* 705 * This was a reference to a field within a resource descriptor. 706 * Extract the associated field offset (either a bit or byte 707 * offset depending on the field type) and change the named 708 * reference into an integer for AML code generation 709 */ 710 Offset = Node->Value; 711 TagBitLength = Node->Length; 712 713 /* 714 * If a field is being created, generate the length (in bits) of 715 * the field. Note: Opcodes other than CreateXxxField and Index 716 * can come through here. For other opcodes, we just need to 717 * convert the resource tag reference to an integer offset. 718 */ 719 switch (Op->Asl.Parent->Asl.AmlOpcode) 720 { 721 case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */ 722 /* 723 * We know the length operand is an integer constant because 724 * we know that it contains a reference to a resource 725 * descriptor tag. 726 */ 727 FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer; 728 break; 729 730 case AML_CREATE_BIT_FIELD_OP: 731 732 FieldBitLength = 1; 733 break; 734 735 case AML_CREATE_BYTE_FIELD_OP: 736 case AML_INDEX_OP: 737 738 FieldBitLength = 8; 739 break; 740 741 case AML_CREATE_WORD_FIELD_OP: 742 743 FieldBitLength = 16; 744 break; 745 746 case AML_CREATE_DWORD_FIELD_OP: 747 748 FieldBitLength = 32; 749 break; 750 751 case AML_CREATE_QWORD_FIELD_OP: 752 753 FieldBitLength = 64; 754 break; 755 756 default: 757 758 FieldBitLength = 0; 759 break; 760 } 761 762 /* Check the field length against the length of the resource tag */ 763 764 if (FieldBitLength) 765 { 766 if (TagBitLength < FieldBitLength) 767 { 768 Message = ASL_MSG_TAG_SMALLER; 769 } 770 else if (TagBitLength > FieldBitLength) 771 { 772 Message = ASL_MSG_TAG_LARGER; 773 } 774 775 if (Message) 776 { 777 sprintf (MsgBuffer, 778 "Size mismatch, Tag: %u bit%s, Field: %u bit%s", 779 TagBitLength, (TagBitLength > 1) ? "s" : "", 780 FieldBitLength, (FieldBitLength > 1) ? "s" : ""); 781 782 AslError (ASL_WARNING, Message, Op, MsgBuffer); 783 } 784 } 785 786 /* Convert the BitOffset to a ByteOffset for certain opcodes */ 787 788 switch (Op->Asl.Parent->Asl.AmlOpcode) 789 { 790 case AML_CREATE_BYTE_FIELD_OP: 791 case AML_CREATE_WORD_FIELD_OP: 792 case AML_CREATE_DWORD_FIELD_OP: 793 case AML_CREATE_QWORD_FIELD_OP: 794 case AML_INDEX_OP: 795 796 Offset = ACPI_DIV_8 (Offset); 797 break; 798 799 default: 800 801 break; 802 } 803 804 /* Now convert this node to an integer whose value is the field offset */ 805 806 Op->Asl.AmlLength = 0; 807 Op->Asl.ParseOpcode = PARSEOP_INTEGER; 808 Op->Asl.Value.Integer = (UINT64) Offset; 809 Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD; 810 811 OpcGenerateAmlOpcode (Op); 812 } 813 814 /* 3) Check for a method invocation */ 815 816 else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) && 817 (Node->Type == ACPI_TYPE_METHOD) && 818 (Op->Asl.Parent) && 819 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) || 820 821 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 822 { 823 /* 824 * A reference to a method within one of these opcodes is not an 825 * invocation of the method, it is simply a reference to the method. 826 * 827 * September 2016: Removed DeRefOf from this list 828 */ 829 if ((Op->Asl.Parent) && 830 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) || 831 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE) || 832 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)|| 833 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE))) 834 { 835 return_ACPI_STATUS (AE_OK); 836 } 837 838 /* 839 * There are two types of method invocation: 840 * 1) Invocation with arguments -- the parser recognizes this 841 * as a METHODCALL. 842 * 2) Invocation with no arguments --the parser cannot determine that 843 * this is a method invocation, therefore we have to figure it out 844 * here. 845 */ 846 if (Node->Type != ACPI_TYPE_METHOD) 847 { 848 sprintf (MsgBuffer, "%s is a %s", 849 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 850 851 AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer); 852 return_ACPI_STATUS (AE_OK); 853 } 854 855 /* Save the method node in the caller's op */ 856 857 Op->Asl.Node = Node; 858 if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF) 859 { 860 return_ACPI_STATUS (AE_OK); 861 } 862 863 /* 864 * This is a method invocation, with or without arguments. 865 * Count the number of arguments, each appears as a child 866 * under the parent node 867 */ 868 Op->Asl.ParseOpcode = PARSEOP_METHODCALL; 869 UtSetParseOpName (Op); 870 871 PassedArgs = 0; 872 NextOp = Op->Asl.Child; 873 874 while (NextOp) 875 { 876 PassedArgs++; 877 NextOp = NextOp->Asl.Next; 878 } 879 880 if (Node->Value != ASL_EXTERNAL_METHOD && 881 Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL) 882 { 883 /* 884 * Check the parsed arguments with the number expected by the 885 * method declaration itself 886 */ 887 if (PassedArgs != Node->Value) 888 { 889 sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName, 890 Node->Value); 891 892 if (PassedArgs < Node->Value) 893 { 894 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer); 895 } 896 else 897 { 898 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer); 899 } 900 } 901 } 902 } 903 904 /* 4) Check for an ASL Field definition */ 905 906 else if ((Op->Asl.Parent) && 907 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) || 908 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD))) 909 { 910 /* 911 * Offset checking for fields. If the parent operation region has a 912 * constant length (known at compile time), we can check fields 913 * defined in that region against the region length. This will catch 914 * fields and field units that cannot possibly fit within the region. 915 * 916 * Note: Index fields do not directly reference an operation region, 917 * thus they are not included in this check. 918 */ 919 if (Op == Op->Asl.Parent->Asl.Child) 920 { 921 /* 922 * This is the first child of the field node, which is 923 * the name of the region. Get the parse node for the 924 * region -- which contains the length of the region. 925 */ 926 OwningOp = Node->Op; 927 Op->Asl.Parent->Asl.ExtraValue = 928 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer); 929 930 /* Examine the field access width */ 931 932 switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer) 933 { 934 case AML_FIELD_ACCESS_ANY: 935 case AML_FIELD_ACCESS_BYTE: 936 case AML_FIELD_ACCESS_BUFFER: 937 default: 938 939 MinimumLength = 1; 940 break; 941 942 case AML_FIELD_ACCESS_WORD: 943 944 MinimumLength = 2; 945 break; 946 947 case AML_FIELD_ACCESS_DWORD: 948 949 MinimumLength = 4; 950 break; 951 952 case AML_FIELD_ACCESS_QWORD: 953 954 MinimumLength = 8; 955 break; 956 } 957 958 /* 959 * Is the region at least as big as the access width? 960 * Note: DataTableRegions have 0 length 961 */ 962 if (((UINT32) OwningOp->Asl.Value.Integer) && 963 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength)) 964 { 965 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL); 966 } 967 968 /* 969 * Check EC/CMOS/SMBUS fields to make sure that the correct 970 * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS) 971 */ 972 SpaceIdOp = OwningOp->Asl.Child->Asl.Next; 973 switch ((UINT32) SpaceIdOp->Asl.Value.Integer) 974 { 975 case ACPI_ADR_SPACE_EC: 976 case ACPI_ADR_SPACE_CMOS: 977 case ACPI_ADR_SPACE_GPIO: 978 979 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != 980 AML_FIELD_ACCESS_BYTE) 981 { 982 AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL); 983 } 984 break; 985 986 case ACPI_ADR_SPACE_SMBUS: 987 case ACPI_ADR_SPACE_IPMI: 988 case ACPI_ADR_SPACE_GSBUS: 989 990 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != 991 AML_FIELD_ACCESS_BUFFER) 992 { 993 AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL); 994 } 995 break; 996 997 default: 998 999 /* Nothing to do for other address spaces */ 1000 1001 break; 1002 } 1003 } 1004 else 1005 { 1006 /* 1007 * This is one element of the field list. Check to make sure 1008 * that it does not go beyond the end of the parent operation region. 1009 * 1010 * In the code below: 1011 * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits) 1012 * Op->Asl.ExtraValue - Field start offset (bits) 1013 * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits) 1014 * Op->Asl.Child->Asl.ExtraValue - Field access width (bits) 1015 */ 1016 if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child) 1017 { 1018 XfCheckFieldRange (Op, 1019 Op->Asl.Parent->Asl.ExtraValue, 1020 Op->Asl.ExtraValue, 1021 (UINT32) Op->Asl.Child->Asl.Value.Integer, 1022 Op->Asl.Child->Asl.ExtraValue); 1023 } 1024 } 1025 } 1026 1027 /* 5) Check for a connection object */ 1028 #if 0 1029 else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION) 1030 { 1031 return_ACPI_STATUS (Status); 1032 } 1033 #endif 1034 1035 Op->Asl.Node = Node; 1036 return_ACPI_STATUS (Status); 1037 } 1038 1039 1040 /******************************************************************************* 1041 * 1042 * FUNCTION: XfNamespaceLocateEnd 1043 * 1044 * PARAMETERS: ASL_WALK_CALLBACK 1045 * 1046 * RETURN: Status 1047 * 1048 * DESCRIPTION: Ascending callback used during cross reference. We only 1049 * need to worry about scope management here. 1050 * 1051 ******************************************************************************/ 1052 1053 static ACPI_STATUS 1054 XfNamespaceLocateEnd ( 1055 ACPI_PARSE_OBJECT *Op, 1056 UINT32 Level, 1057 void *Context) 1058 { 1059 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 1060 const ACPI_OPCODE_INFO *OpInfo; 1061 1062 1063 ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd); 1064 1065 1066 /* We are only interested in opcodes that have an associated name */ 1067 1068 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1069 if (!(OpInfo->Flags & AML_NAMED)) 1070 { 1071 return_ACPI_STATUS (AE_OK); 1072 } 1073 1074 /* Not interested in name references, we did not open a scope for them */ 1075 1076 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 1077 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 1078 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 1079 { 1080 return_ACPI_STATUS (AE_OK); 1081 } 1082 1083 /* Pop the scope stack if necessary */ 1084 1085 if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode))) 1086 { 1087 1088 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 1089 "%s: Popping scope for Op %p\n", 1090 AcpiUtGetTypeName (OpInfo->ObjectType), Op)); 1091 1092 (void) AcpiDsScopeStackPop (WalkState); 1093 } 1094 1095 return_ACPI_STATUS (AE_OK); 1096 } 1097 1098 1099 #ifdef __UNDER_DEVELOPMENT 1100 /******************************************************************************* 1101 * 1102 * FUNCTION: XfIsObjectParental 1103 * 1104 * PARAMETERS: ChildOp - Op to be checked 1105 * PossibleParentOp - Determine if this op is in the family 1106 * 1107 * RETURN: TRUE if ChildOp is a descendent of PossibleParentOp 1108 * 1109 * DESCRIPTION: Determine if an Op is a descendent of another Op. Used to 1110 * detect if a method is declared within another method. 1111 * 1112 ******************************************************************************/ 1113 1114 static BOOLEAN 1115 XfIsObjectParental ( 1116 ACPI_PARSE_OBJECT *ChildOp, 1117 ACPI_PARSE_OBJECT *PossibleParentOp) 1118 { 1119 ACPI_PARSE_OBJECT *ParentOp; 1120 1121 1122 /* Search upwards through the tree for possible parent */ 1123 1124 ParentOp = ChildOp; 1125 while (ParentOp) 1126 { 1127 if (ParentOp == PossibleParentOp) 1128 { 1129 return (TRUE); 1130 } 1131 1132 ParentOp = ParentOp->Asl.Parent; 1133 } 1134 1135 return (FALSE); 1136 } 1137 1138 1139 /******************************************************************************* 1140 * 1141 * FUNCTION: XfGetParentMethod 1142 * 1143 * PARAMETERS: Op - Op to be checked 1144 * 1145 * RETURN: Op for parent method. NULL if object is not within a method. 1146 * 1147 * DESCRIPTION: Determine if an object is within a control method. Used to 1148 * implement special rules for named references from within a 1149 * control method. 1150 * 1151 * NOTE: It would be better to have the parser set a flag in the Op if possible. 1152 * 1153 ******************************************************************************/ 1154 1155 static ACPI_PARSE_OBJECT * 1156 XfGetParentMethod ( 1157 ACPI_PARSE_OBJECT *Op) 1158 { 1159 ACPI_PARSE_OBJECT *ParentOp; 1160 1161 1162 if (!Op) 1163 { 1164 return (NULL); 1165 } 1166 1167 if (Op->Asl.ParseOpcode == PARSEOP_METHOD) 1168 { 1169 return (NULL); 1170 } 1171 1172 /* Walk upwards through the parse tree, up to the root if necessary */ 1173 1174 ParentOp = Op; 1175 while (ParentOp) 1176 { 1177 if (ParentOp->Asl.ParseOpcode == PARSEOP_METHOD) 1178 { 1179 return (ParentOp); 1180 } 1181 1182 ParentOp = ParentOp->Asl.Parent; 1183 } 1184 1185 /* Object is not within a method */ 1186 1187 return (NULL); 1188 } 1189 1190 1191 /******************************************************************************* 1192 * 1193 * FUNCTION: XfCheckIllegalReference 1194 * 1195 * PARAMETERS: Op - Op referring to the target 1196 * TargetNode - Target of the reference 1197 * 1198 * RETURN: None. Emits error message for an illegal reference 1199 * 1200 * DESCRIPTION: Determine if a named reference is legal. A "named" reference 1201 * is something like: Store(ABCD, ...), where ABCD is an AML 1202 * Nameseg or Namepath. 1203 * 1204 * NOTE: Caller must ensure that the name Op is in fact a reference, and not 1205 * an actual name declaration (creation of a named object). 1206 * 1207 ******************************************************************************/ 1208 1209 static void 1210 XfCheckIllegalReference ( 1211 ACPI_PARSE_OBJECT *Op, 1212 ACPI_NAMESPACE_NODE *TargetNode) 1213 { 1214 ACPI_PARSE_OBJECT *MethodOp1; 1215 ACPI_PARSE_OBJECT *MethodOp2; 1216 ACPI_PARSE_OBJECT *TargetOp; 1217 1218 1219 /* 1220 * Check for an illegal reference to a named object: 1221 * 1222 * 1) References from one control method to another, non-parent 1223 * method are not allowed, they will fail at runtime. 1224 * 1225 * 2) Forward references within a control method are not allowed. 1226 * AML interpreters use a one-pass parse of control methods 1227 * so these forward references will fail at runtime. 1228 */ 1229 TargetOp = TargetNode->Op; 1230 1231 MethodOp1 = XfGetParentMethod (Op); 1232 MethodOp2 = XfGetParentMethod (TargetOp); 1233 1234 /* Are both objects within control method(s)? */ 1235 1236 if (!MethodOp1 || !MethodOp2) 1237 { 1238 return; 1239 } 1240 1241 /* Objects not in the same method? */ 1242 1243 if (MethodOp1 != MethodOp2) 1244 { 1245 /* 1246 * 1) Cross-method named reference 1247 * 1248 * This is OK if and only if the target reference is within in a 1249 * method that is a parent of current method 1250 */ 1251 if (!XfIsObjectParental (MethodOp1, MethodOp2)) 1252 { 1253 AslError (ASL_ERROR, ASL_MSG_ILLEGAL_METHOD_REF, Op, 1254 Op->Asl.ExternalName); 1255 } 1256 } 1257 1258 /* 1259 * 2) Both reference and target are in the same method. Check if this is 1260 * an (illegal) forward reference by examining the exact source code 1261 * location of each (the referenced object and the object declaration). 1262 * This is a bit nasty, yet effective. 1263 */ 1264 else if (Op->Asl.LogicalByteOffset < TargetOp->Asl.LogicalByteOffset) 1265 { 1266 AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op, 1267 Op->Asl.ExternalName); 1268 } 1269 1270 } 1271 #endif 1272