1 /****************************************************************************** 2 * 3 * Module Name: aslxref - Namespace cross-reference 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 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 Path = NextOp->Asl.Value.String; 579 } 580 else 581 { 582 Path = Op->Asl.Value.String; 583 } 584 585 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 586 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 587 "Type=%s\n", AcpiUtGetTypeName (ObjectType))); 588 589 /* 590 * Lookup the name in the namespace. Name must exist at this point, or it 591 * is an invalid reference. 592 * 593 * The namespace is also used as a lookup table for references to resource 594 * descriptors and the fields within them. 595 */ 596 Gbl_NsLookupCount++; 597 598 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 599 ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node)); 600 if (ACPI_FAILURE (Status)) 601 { 602 if (Status == AE_NOT_FOUND) 603 { 604 /* 605 * We didn't find the name reference by path -- we can qualify this 606 * a little better before we print an error message 607 */ 608 if (strlen (Path) == ACPI_NAME_SIZE) 609 { 610 /* A simple, one-segment ACPI name */ 611 612 if (XfObjectExists (Path)) 613 { 614 /* 615 * There exists such a name, but we couldn't get to it 616 * from this scope 617 */ 618 AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op, 619 Op->Asl.ExternalName); 620 } 621 else 622 { 623 /* The name doesn't exist, period */ 624 625 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, 626 Op, Op->Asl.ExternalName); 627 } 628 } 629 else 630 { 631 /* Check for a fully qualified path */ 632 633 if (Path[0] == AML_ROOT_PREFIX) 634 { 635 /* Gave full path, the object does not exist */ 636 637 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, 638 Op->Asl.ExternalName); 639 } 640 else 641 { 642 /* 643 * We can't tell whether it doesn't exist or just 644 * can't be reached. 645 */ 646 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 647 Op->Asl.ExternalName); 648 } 649 } 650 651 Status = AE_OK; 652 } 653 654 return_ACPI_STATUS (Status); 655 } 656 657 /* Check for a reference vs. name declaration */ 658 659 if (!(OpInfo->Flags & AML_NAMED) && 660 !(OpInfo->Flags & AML_CREATE)) 661 { 662 /* This node has been referenced, mark it for reference check */ 663 664 Node->Flags |= ANOBJ_IS_REFERENCED; 665 666 #ifdef __UNDER_DEVELOPMENT 667 668 /* Check for an illegal reference */ 669 670 XfCheckIllegalReference (Op, Node); 671 #endif 672 } 673 674 /* Attempt to optimize the NamePath */ 675 676 OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node); 677 678 /* 679 * 1) Dereference an alias (A name reference that is an alias) 680 * Aliases are not nested, the alias always points to the final object 681 */ 682 if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) && 683 (Node->Type == ACPI_TYPE_LOCAL_ALIAS)) 684 { 685 /* This node points back to the original PARSEOP_ALIAS */ 686 687 NextOp = Node->Op; 688 689 /* The first child is the alias target op */ 690 691 NextOp = NextOp->Asl.Child; 692 693 /* That in turn points back to original target alias node */ 694 695 if (NextOp->Asl.Node) 696 { 697 Node = NextOp->Asl.Node; 698 } 699 700 /* Else - forward reference to alias, will be resolved later */ 701 } 702 703 /* 2) Check for a reference to a resource descriptor */ 704 705 if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 706 (Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 707 { 708 /* 709 * This was a reference to a field within a resource descriptor. 710 * Extract the associated field offset (either a bit or byte 711 * offset depending on the field type) and change the named 712 * reference into an integer for AML code generation 713 */ 714 Offset = Node->Value; 715 TagBitLength = Node->Length; 716 717 /* 718 * If a field is being created, generate the length (in bits) of 719 * the field. Note: Opcodes other than CreateXxxField and Index 720 * can come through here. For other opcodes, we just need to 721 * convert the resource tag reference to an integer offset. 722 */ 723 switch (Op->Asl.Parent->Asl.AmlOpcode) 724 { 725 case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */ 726 /* 727 * We know the length operand is an integer constant because 728 * we know that it contains a reference to a resource 729 * descriptor tag. 730 */ 731 FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer; 732 break; 733 734 case AML_CREATE_BIT_FIELD_OP: 735 736 FieldBitLength = 1; 737 break; 738 739 case AML_CREATE_BYTE_FIELD_OP: 740 case AML_INDEX_OP: 741 742 FieldBitLength = 8; 743 break; 744 745 case AML_CREATE_WORD_FIELD_OP: 746 747 FieldBitLength = 16; 748 break; 749 750 case AML_CREATE_DWORD_FIELD_OP: 751 752 FieldBitLength = 32; 753 break; 754 755 case AML_CREATE_QWORD_FIELD_OP: 756 757 FieldBitLength = 64; 758 break; 759 760 default: 761 762 FieldBitLength = 0; 763 break; 764 } 765 766 /* Check the field length against the length of the resource tag */ 767 768 if (FieldBitLength) 769 { 770 if (TagBitLength < FieldBitLength) 771 { 772 Message = ASL_MSG_TAG_SMALLER; 773 } 774 else if (TagBitLength > FieldBitLength) 775 { 776 Message = ASL_MSG_TAG_LARGER; 777 } 778 779 if (Message) 780 { 781 sprintf (MsgBuffer, "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 if ((Op->Asl.Parent) && 831 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) || 832 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF) || 833 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE) || 834 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)|| 835 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE))) 836 { 837 return_ACPI_STATUS (AE_OK); 838 } 839 /* 840 * There are two types of method invocation: 841 * 1) Invocation with arguments -- the parser recognizes this 842 * as a METHODCALL. 843 * 2) Invocation with no arguments --the parser cannot determine that 844 * this is a method invocation, therefore we have to figure it out 845 * here. 846 */ 847 if (Node->Type != ACPI_TYPE_METHOD) 848 { 849 sprintf (MsgBuffer, "%s is a %s", 850 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 851 852 AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer); 853 return_ACPI_STATUS (AE_OK); 854 } 855 856 /* Save the method node in the caller's op */ 857 858 Op->Asl.Node = Node; 859 if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF) 860 { 861 return_ACPI_STATUS (AE_OK); 862 } 863 864 /* 865 * This is a method invocation, with or without arguments. 866 * Count the number of arguments, each appears as a child 867 * under the parent node 868 */ 869 Op->Asl.ParseOpcode = PARSEOP_METHODCALL; 870 UtSetParseOpName (Op); 871 872 PassedArgs = 0; 873 NextOp = Op->Asl.Child; 874 875 while (NextOp) 876 { 877 PassedArgs++; 878 NextOp = NextOp->Asl.Next; 879 } 880 881 if (Node->Value != ASL_EXTERNAL_METHOD) 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 != AML_FIELD_ACCESS_BYTE) 980 { 981 AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL); 982 } 983 break; 984 985 case ACPI_ADR_SPACE_SMBUS: 986 case ACPI_ADR_SPACE_IPMI: 987 case ACPI_ADR_SPACE_GSBUS: 988 989 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER) 990 { 991 AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL); 992 } 993 break; 994 995 default: 996 997 /* Nothing to do for other address spaces */ 998 999 break; 1000 } 1001 } 1002 else 1003 { 1004 /* 1005 * This is one element of the field list. Check to make sure 1006 * that it does not go beyond the end of the parent operation region. 1007 * 1008 * In the code below: 1009 * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits) 1010 * Op->Asl.ExtraValue - Field start offset (bits) 1011 * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits) 1012 * Op->Asl.Child->Asl.ExtraValue - Field access width (bits) 1013 */ 1014 if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child) 1015 { 1016 XfCheckFieldRange (Op, 1017 Op->Asl.Parent->Asl.ExtraValue, 1018 Op->Asl.ExtraValue, 1019 (UINT32) Op->Asl.Child->Asl.Value.Integer, 1020 Op->Asl.Child->Asl.ExtraValue); 1021 } 1022 } 1023 } 1024 1025 /* 5) Check for a connection object */ 1026 #if 0 1027 else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION) 1028 { 1029 return_ACPI_STATUS (Status); 1030 } 1031 #endif 1032 1033 Op->Asl.Node = Node; 1034 return_ACPI_STATUS (Status); 1035 } 1036 1037 1038 /******************************************************************************* 1039 * 1040 * FUNCTION: XfNamespaceLocateEnd 1041 * 1042 * PARAMETERS: ASL_WALK_CALLBACK 1043 * 1044 * RETURN: Status 1045 * 1046 * DESCRIPTION: Ascending callback used during cross reference. We only 1047 * need to worry about scope management here. 1048 * 1049 ******************************************************************************/ 1050 1051 static ACPI_STATUS 1052 XfNamespaceLocateEnd ( 1053 ACPI_PARSE_OBJECT *Op, 1054 UINT32 Level, 1055 void *Context) 1056 { 1057 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 1058 const ACPI_OPCODE_INFO *OpInfo; 1059 1060 1061 ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd); 1062 1063 1064 /* We are only interested in opcodes that have an associated name */ 1065 1066 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1067 if (!(OpInfo->Flags & AML_NAMED)) 1068 { 1069 return_ACPI_STATUS (AE_OK); 1070 } 1071 1072 /* Not interested in name references, we did not open a scope for them */ 1073 1074 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 1075 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 1076 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 1077 { 1078 return_ACPI_STATUS (AE_OK); 1079 } 1080 1081 /* Pop the scope stack if necessary */ 1082 1083 if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode))) 1084 { 1085 1086 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 1087 "%s: Popping scope for Op %p\n", 1088 AcpiUtGetTypeName (OpInfo->ObjectType), Op)); 1089 1090 (void) AcpiDsScopeStackPop (WalkState); 1091 } 1092 1093 return_ACPI_STATUS (AE_OK); 1094 } 1095 1096 1097 #ifdef __UNDER_DEVELOPMENT 1098 /******************************************************************************* 1099 * 1100 * FUNCTION: XfIsObjectParental 1101 * 1102 * PARAMETERS: ChildOp - Op to be checked 1103 * PossibleParentOp - Determine if this op is in the family 1104 * 1105 * RETURN: TRUE if ChildOp is a descendent of PossibleParentOp 1106 * 1107 * DESCRIPTION: Determine if an Op is a descendent of another Op. Used to 1108 * detect if a method is declared within another method. 1109 * 1110 ******************************************************************************/ 1111 1112 static BOOLEAN 1113 XfIsObjectParental ( 1114 ACPI_PARSE_OBJECT *ChildOp, 1115 ACPI_PARSE_OBJECT *PossibleParentOp) 1116 { 1117 ACPI_PARSE_OBJECT *ParentOp; 1118 1119 1120 /* Search upwards through the tree for possible parent */ 1121 1122 ParentOp = ChildOp; 1123 while (ParentOp) 1124 { 1125 if (ParentOp == PossibleParentOp) 1126 { 1127 return (TRUE); 1128 } 1129 1130 ParentOp = ParentOp->Asl.Parent; 1131 } 1132 1133 return (FALSE); 1134 } 1135 1136 1137 /******************************************************************************* 1138 * 1139 * FUNCTION: XfGetParentMethod 1140 * 1141 * PARAMETERS: Op - Op to be checked 1142 * 1143 * RETURN: Op for parent method. NULL if object is not within a method. 1144 * 1145 * DESCRIPTION: Determine if an object is within a control method. Used to 1146 * implement special rules for named references from within a 1147 * control method. 1148 * 1149 * NOTE: It would be better to have the parser set a flag in the Op if possible. 1150 * 1151 ******************************************************************************/ 1152 1153 static ACPI_PARSE_OBJECT * 1154 XfGetParentMethod ( 1155 ACPI_PARSE_OBJECT *Op) 1156 { 1157 ACPI_PARSE_OBJECT *ParentOp; 1158 1159 1160 if (!Op) 1161 { 1162 return (NULL); 1163 } 1164 1165 if (Op->Asl.ParseOpcode == PARSEOP_METHOD) 1166 { 1167 return (NULL); 1168 } 1169 1170 /* Walk upwards through the parse tree, up to the root if necessary */ 1171 1172 ParentOp = Op; 1173 while (ParentOp) 1174 { 1175 if (ParentOp->Asl.ParseOpcode == PARSEOP_METHOD) 1176 { 1177 return (ParentOp); 1178 } 1179 1180 ParentOp = ParentOp->Asl.Parent; 1181 } 1182 1183 /* Object is not within a method */ 1184 1185 return (NULL); 1186 } 1187 1188 1189 /******************************************************************************* 1190 * 1191 * FUNCTION: XfCheckIllegalReference 1192 * 1193 * PARAMETERS: Op - Op referring to the target 1194 * TargetNode - Target of the reference 1195 * 1196 * RETURN: None. Emits error message for an illegal reference 1197 * 1198 * DESCRIPTION: Determine if a named reference is legal. A "named" reference 1199 * is something like: Store(ABCD, ...), where ABCD is an AML 1200 * Nameseg or Namepath. 1201 * 1202 * NOTE: Caller must ensure that the name Op is in fact a reference, and not 1203 * an actual name declaration (creation of a named object). 1204 * 1205 ******************************************************************************/ 1206 1207 static void 1208 XfCheckIllegalReference ( 1209 ACPI_PARSE_OBJECT *Op, 1210 ACPI_NAMESPACE_NODE *TargetNode) 1211 { 1212 ACPI_PARSE_OBJECT *MethodOp1; 1213 ACPI_PARSE_OBJECT *MethodOp2; 1214 ACPI_PARSE_OBJECT *TargetOp; 1215 1216 1217 /* 1218 * Check for an illegal reference to a named object: 1219 * 1220 * 1) References from one control method to another, non-parent 1221 * method are not allowed, they will fail at runtime. 1222 * 1223 * 2) Forward references within a control method are not allowed. 1224 * AML interpreters use a one-pass parse of control methods 1225 * so these forward references will fail at runtime. 1226 */ 1227 TargetOp = TargetNode->Op; 1228 1229 MethodOp1 = XfGetParentMethod (Op); 1230 MethodOp2 = XfGetParentMethod (TargetOp); 1231 1232 /* Are both objects within control method(s)? */ 1233 1234 if (!MethodOp1 || !MethodOp2) 1235 { 1236 return; 1237 } 1238 1239 /* Objects not in the same method? */ 1240 1241 if (MethodOp1 != MethodOp2) 1242 { 1243 /* 1244 * 1) Cross-method named reference 1245 * 1246 * This is OK if and only if the target reference is within in a 1247 * method that is a parent of current method 1248 */ 1249 if (!XfIsObjectParental (MethodOp1, MethodOp2)) 1250 { 1251 AslError (ASL_ERROR, ASL_MSG_ILLEGAL_METHOD_REF, Op, 1252 Op->Asl.ExternalName); 1253 } 1254 } 1255 1256 /* 1257 * 2) Both reference and target are in the same method. Check if this is 1258 * an (illegal) forward reference by examining the exact source code 1259 * location of each (the referenced object and the object declaration). 1260 * This is a bit nasty, yet effective. 1261 */ 1262 else if (Op->Asl.LogicalByteOffset < TargetOp->Asl.LogicalByteOffset) 1263 { 1264 AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op, 1265 Op->Asl.ExternalName); 1266 } 1267 1268 } 1269 #endif 1270