1 /****************************************************************************** 2 * 3 * Module Name: asllookup- Namespace lookup 4 * $Revision: 1.103 $ 5 * 6 *****************************************************************************/ 7 8 /****************************************************************************** 9 * 10 * 1. Copyright Notice 11 * 12 * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp. 13 * All rights reserved. 14 * 15 * 2. License 16 * 17 * 2.1. This is your license from Intel Corp. under its intellectual property 18 * rights. You may have additional license terms from the party that provided 19 * you this software, covering your right to use that party's intellectual 20 * property rights. 21 * 22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 23 * copy of the source code appearing in this file ("Covered Code") an 24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 25 * base code distributed originally by Intel ("Original Intel Code") to copy, 26 * make derivatives, distribute, use and display any portion of the Covered 27 * Code in any form, with the right to sublicense such rights; and 28 * 29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 30 * license (with the right to sublicense), under only those claims of Intel 31 * patents that are infringed by the Original Intel Code, to make, use, sell, 32 * offer to sell, and import the Covered Code and derivative works thereof 33 * solely to the minimum extent necessary to exercise the above copyright 34 * license, and in no event shall the patent license extend to any additions 35 * to or modifications of the Original Intel Code. No other license or right 36 * is granted directly or by implication, estoppel or otherwise; 37 * 38 * The above copyright and patent license is granted only if the following 39 * conditions are met: 40 * 41 * 3. Conditions 42 * 43 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 44 * Redistribution of source code of any substantial portion of the Covered 45 * Code or modification with rights to further distribute source must include 46 * the above Copyright Notice, the above License, this list of Conditions, 47 * and the following Disclaimer and Export Compliance provision. In addition, 48 * Licensee must cause all Covered Code to which Licensee contributes to 49 * contain a file documenting the changes Licensee made to create that Covered 50 * Code and the date of any change. Licensee must include in that file the 51 * documentation of any changes made by any predecessor Licensee. Licensee 52 * must include a prominent statement that the modification is derived, 53 * directly or indirectly, from Original Intel Code. 54 * 55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 56 * Redistribution of source code of any substantial portion of the Covered 57 * Code or modification without rights to further distribute source must 58 * include the following Disclaimer and Export Compliance provision in the 59 * documentation and/or other materials provided with distribution. In 60 * addition, Licensee may not authorize further sublicense of source of any 61 * portion of the Covered Code, and must include terms to the effect that the 62 * license from Licensee to its licensee is limited to the intellectual 63 * property embodied in the software Licensee provides to its licensee, and 64 * not to intellectual property embodied in modifications its licensee may 65 * make. 66 * 67 * 3.3. Redistribution of Executable. Redistribution in executable form of any 68 * substantial portion of the Covered Code or modification must reproduce the 69 * above Copyright Notice, and the following Disclaimer and Export Compliance 70 * provision in the documentation and/or other materials provided with the 71 * distribution. 72 * 73 * 3.4. Intel retains all right, title, and interest in and to the Original 74 * Intel Code. 75 * 76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 77 * Intel shall be used in advertising or otherwise to promote the sale, use or 78 * other dealings in products derived from or relating to the Covered Code 79 * without prior written authorization from Intel. 80 * 81 * 4. Disclaimer and Export Compliance 82 * 83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 84 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 86 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 87 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89 * PARTICULAR PURPOSE. 90 * 91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98 * LIMITED REMEDY. 99 * 100 * 4.3. Licensee shall not export, either directly or indirectly, any of this 101 * software or system incorporating such software without first obtaining any 102 * required license or other approval from the U. S. Department of Commerce or 103 * any other agency or department of the United States Government. In the 104 * event Licensee exports any such software from the United States or 105 * re-exports any such software from a foreign destination, Licensee shall 106 * ensure that the distribution and export/re-export of the software is in 107 * compliance with all laws, regulations, orders, or other restrictions of the 108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109 * any of its subsidiaries will export/re-export any technical data, process, 110 * software, or service, directly or indirectly, to any country for which the 111 * United States government or any agency thereof requires an export license, 112 * other governmental approval, or letter of assurance, without first obtaining 113 * such license, approval or letter. 114 * 115 *****************************************************************************/ 116 117 118 #include <contrib/dev/acpica/compiler/aslcompiler.h> 119 #include "aslcompiler.y.h" 120 121 #include <contrib/dev/acpica/acparser.h> 122 #include <contrib/dev/acpica/amlcode.h> 123 #include <contrib/dev/acpica/acnamesp.h> 124 #include <contrib/dev/acpica/acdispat.h> 125 126 127 #define _COMPONENT ACPI_COMPILER 128 ACPI_MODULE_NAME ("asllookup") 129 130 /* Local prototypes */ 131 132 static ACPI_STATUS 133 LsCompareOneNamespaceObject ( 134 ACPI_HANDLE ObjHandle, 135 UINT32 Level, 136 void *Context, 137 void **ReturnValue); 138 139 static ACPI_STATUS 140 LsDoOneNamespaceObject ( 141 ACPI_HANDLE ObjHandle, 142 UINT32 Level, 143 void *Context, 144 void **ReturnValue); 145 146 static BOOLEAN 147 LkObjectExists ( 148 char *Name); 149 150 static void 151 LkCheckFieldRange ( 152 ACPI_PARSE_OBJECT *Op, 153 UINT32 RegionBitLength, 154 UINT32 FieldBitOffset, 155 UINT32 FieldBitLength, 156 UINT32 AccessBitWidth); 157 158 static ACPI_STATUS 159 LkNamespaceLocateBegin ( 160 ACPI_PARSE_OBJECT *Op, 161 UINT32 Level, 162 void *Context); 163 164 static ACPI_STATUS 165 LkNamespaceLocateEnd ( 166 ACPI_PARSE_OBJECT *Op, 167 UINT32 Level, 168 void *Context); 169 170 static ACPI_STATUS 171 LkIsObjectUsed ( 172 ACPI_HANDLE ObjHandle, 173 UINT32 Level, 174 void *Context, 175 void **ReturnValue); 176 177 178 /******************************************************************************* 179 * 180 * FUNCTION: LsDoOneNamespaceObject 181 * 182 * PARAMETERS: ACPI_WALK_CALLBACK 183 * 184 * RETURN: Status 185 * 186 * DESCRIPTION: Dump a namespace object to the namespace output file. 187 * Called during the walk of the namespace to dump all objects. 188 * 189 ******************************************************************************/ 190 191 static ACPI_STATUS 192 LsDoOneNamespaceObject ( 193 ACPI_HANDLE ObjHandle, 194 UINT32 Level, 195 void *Context, 196 void **ReturnValue) 197 { 198 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 199 ACPI_OPERAND_OBJECT *ObjDesc; 200 ACPI_PARSE_OBJECT *Op; 201 202 203 Gbl_NumNamespaceObjects++; 204 205 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%5d [%d] %*s %4.4s - %s", 206 Gbl_NumNamespaceObjects, Level, (Level * 3), " ", 207 &Node->Name, 208 AcpiUtGetTypeName (Node->Type)); 209 210 Op = Node->Op; 211 ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Node->Object); 212 213 if (!Op) 214 { 215 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n"); 216 return (AE_OK); 217 } 218 219 220 if ((ObjDesc) && 221 (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND)) 222 { 223 switch (Node->Type) 224 { 225 case ACPI_TYPE_INTEGER: 226 227 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 228 " [Initial Value 0x%8.8X%8.8X]", 229 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); 230 break; 231 232 233 case ACPI_TYPE_STRING: 234 235 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 236 " [Initial Value \"%s\"]", 237 ObjDesc->String.Pointer); 238 break; 239 240 default: 241 /* Nothing to do for other types */ 242 break; 243 } 244 245 } 246 else 247 { 248 switch (Node->Type) 249 { 250 case ACPI_TYPE_INTEGER: 251 252 if (Op->Asl.ParseOpcode == PARSEOP_NAME) 253 { 254 Op = Op->Asl.Child; 255 } 256 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 257 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) 258 { 259 Op = Op->Asl.Next; 260 } 261 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 262 " [Initial Value 0x%8.8X%8.8X]", 263 ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer)); 264 break; 265 266 267 case ACPI_TYPE_STRING: 268 269 if (Op->Asl.ParseOpcode == PARSEOP_NAME) 270 { 271 Op = Op->Asl.Child; 272 } 273 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 274 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) 275 { 276 Op = Op->Asl.Next; 277 } 278 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 279 " [Initial Value \"%s\"]", 280 Op->Asl.Value.String); 281 break; 282 283 284 case ACPI_TYPE_LOCAL_REGION_FIELD: 285 286 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 287 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) 288 { 289 Op = Op->Asl.Child; 290 } 291 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 292 " [Offset 0x%04X Length 0x%04X bits]", 293 Op->Asl.Parent->Asl.ExtraValue, (UINT32) Op->Asl.Value.Integer); 294 break; 295 296 297 case ACPI_TYPE_BUFFER_FIELD: 298 299 switch (Op->Asl.ParseOpcode) 300 { 301 case PARSEOP_CREATEBYTEFIELD: 302 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BYTE ( 8 bit)]"); 303 break; 304 305 case PARSEOP_CREATEDWORDFIELD: 306 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [DWORD (32 bit)]"); 307 break; 308 309 case PARSEOP_CREATEQWORDFIELD: 310 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [QWORD (64 bit)]"); 311 break; 312 313 case PARSEOP_CREATEWORDFIELD: 314 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [WORD (16 bit)]"); 315 break; 316 317 case PARSEOP_CREATEBITFIELD: 318 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BIT ( 1 bit)]"); 319 break; 320 321 case PARSEOP_CREATEFIELD: 322 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [Arbitrary Bit Field]"); 323 break; 324 325 default: 326 break; 327 328 } 329 break; 330 331 332 case ACPI_TYPE_PACKAGE: 333 334 if (Op->Asl.ParseOpcode == PARSEOP_NAME) 335 { 336 Op = Op->Asl.Child; 337 } 338 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 339 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) 340 { 341 Op = Op->Asl.Next; 342 } 343 Op = Op->Asl.Child; 344 345 if ((Op->Asl.ParseOpcode == PARSEOP_BYTECONST) || 346 (Op->Asl.ParseOpcode == PARSEOP_RAW_DATA)) 347 { 348 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 349 " [Initial Length 0x%.2X elements]", 350 Op->Asl.Value.Integer); 351 } 352 break; 353 354 355 case ACPI_TYPE_BUFFER: 356 357 if (Op->Asl.ParseOpcode == PARSEOP_NAME) 358 { 359 Op = Op->Asl.Child; 360 } 361 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 362 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) 363 { 364 Op = Op->Asl.Next; 365 } 366 Op = Op->Asl.Child; 367 368 if (Op && (Op->Asl.ParseOpcode == PARSEOP_INTEGER)) 369 { 370 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 371 " [Initial Length 0x%.2X bytes]", 372 Op->Asl.Value.Integer); 373 } 374 break; 375 376 377 case ACPI_TYPE_METHOD: 378 379 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 380 " [Code Length 0x%.4X bytes]", 381 Op->Asl.AmlSubtreeLength); 382 break; 383 384 385 case ACPI_TYPE_LOCAL_RESOURCE: 386 387 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 388 " [Desc Offset 0x%.4X Bytes]", Node->Value); 389 break; 390 391 392 case ACPI_TYPE_LOCAL_RESOURCE_FIELD: 393 394 if (Node->Flags & 0x80) 395 { 396 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 397 " [Field Offset 0x%.4X Bits 0x%.4X Bytes]", 398 Node->Value, Node->Value / 8); 399 } 400 else 401 { 402 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, 403 " [Field Offset 0x%.4X Bytes]", Node->Value); 404 } 405 break; 406 407 408 default: 409 /* Nothing to do for other types */ 410 break; 411 } 412 } 413 414 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n"); 415 return (AE_OK); 416 } 417 418 419 void 420 LsSetupNsList (void * Handle) 421 { 422 423 Gbl_NsOutputFlag = TRUE; 424 Gbl_Files[ASL_FILE_NAMESPACE_OUTPUT].Handle = Handle; 425 } 426 427 428 /******************************************************************************* 429 * 430 * FUNCTION: LsDisplayNamespace 431 * 432 * PARAMETERS: None 433 * 434 * RETURN: Status 435 * 436 * DESCRIPTION: Walk the namespace an display information about each node 437 * in the tree. Information is written to the optional 438 * namespace output file. 439 * 440 ******************************************************************************/ 441 442 ACPI_STATUS 443 LsDisplayNamespace ( 444 void) 445 { 446 ACPI_STATUS Status; 447 448 449 if (!Gbl_NsOutputFlag) 450 { 451 return (AE_OK); 452 } 453 454 Gbl_NumNamespaceObjects = 0; 455 456 /* File header */ 457 458 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Contents of ACPI Namespace\n\n"); 459 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Count Depth Name - Type\n\n"); 460 461 /* Walk entire namespace from the root */ 462 463 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 464 ACPI_UINT32_MAX, FALSE, LsDoOneNamespaceObject, 465 NULL, NULL); 466 return (Status); 467 } 468 469 470 /******************************************************************************* 471 * 472 * FUNCTION: LsCompareOneNamespaceObject 473 * 474 * PARAMETERS: ACPI_WALK_CALLBACK 475 * 476 * RETURN: Status 477 * 478 * DESCRIPTION: Compare name of one object. 479 * 480 ******************************************************************************/ 481 482 static ACPI_STATUS 483 LsCompareOneNamespaceObject ( 484 ACPI_HANDLE ObjHandle, 485 UINT32 Level, 486 void *Context, 487 void **ReturnValue) 488 { 489 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 490 491 492 /* Simply check the name */ 493 494 if (*((UINT32 *) (Context)) == Node->Name.Integer) 495 { 496 /* Abort walk if we found one instance */ 497 498 return (AE_CTRL_TRUE); 499 } 500 501 return (AE_OK); 502 } 503 504 505 /******************************************************************************* 506 * 507 * FUNCTION: LkObjectExists 508 * 509 * PARAMETERS: Name - 4 char ACPI name 510 * 511 * RETURN: TRUE if name exists in namespace 512 * 513 * DESCRIPTION: Walk the namespace to find an object 514 * 515 ******************************************************************************/ 516 517 static BOOLEAN 518 LkObjectExists ( 519 char *Name) 520 { 521 ACPI_STATUS Status; 522 523 524 /* Walk entire namespace from the supplied root */ 525 526 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 527 ACPI_UINT32_MAX, FALSE, LsCompareOneNamespaceObject, 528 Name, NULL); 529 if (Status == AE_CTRL_TRUE) 530 { 531 /* At least one instance of the name was found */ 532 533 return (TRUE); 534 } 535 536 return (FALSE); 537 } 538 539 540 /******************************************************************************* 541 * 542 * FUNCTION: LkGetNameOp 543 * 544 * PARAMETERS: Op - Current Op 545 * 546 * RETURN: NameOp associated with the input op 547 * 548 * DESCRIPTION: Find the name declaration op associated with the operator 549 * 550 ******************************************************************************/ 551 552 ACPI_PARSE_OBJECT * 553 LkGetNameOp ( 554 ACPI_PARSE_OBJECT *Op) 555 { 556 const ACPI_OPCODE_INFO *OpInfo; 557 ACPI_PARSE_OBJECT *NameOp = Op; 558 559 560 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 561 562 563 /* Get the NamePath from the appropriate place */ 564 565 if (OpInfo->Flags & AML_NAMED) 566 { 567 /* For nearly all NAMED operators, the name reference is the first child */ 568 569 NameOp = Op->Asl.Child; 570 if (Op->Asl.AmlOpcode == AML_ALIAS_OP) 571 { 572 /* 573 * ALIAS is the only oddball opcode, the name declaration 574 * (alias name) is the second operand 575 */ 576 NameOp = Op->Asl.Child->Asl.Next; 577 } 578 } 579 else if (OpInfo->Flags & AML_CREATE) 580 { 581 /* Name must appear as the last parameter */ 582 583 NameOp = Op->Asl.Child; 584 while (!(NameOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) 585 { 586 NameOp = NameOp->Asl.Next; 587 } 588 } 589 590 return (NameOp); 591 } 592 593 594 /******************************************************************************* 595 * 596 * FUNCTION: LkIsObjectUsed 597 * 598 * PARAMETERS: ACPI_WALK_CALLBACK 599 * 600 * RETURN: Status 601 * 602 * DESCRIPTION: Check for an unreferenced namespace object and emit a warning. 603 * We have to be careful, because some types and names are 604 * typically or always unreferenced, we don't want to issue 605 * excessive warnings. 606 * 607 ******************************************************************************/ 608 609 static ACPI_STATUS 610 LkIsObjectUsed ( 611 ACPI_HANDLE ObjHandle, 612 UINT32 Level, 613 void *Context, 614 void **ReturnValue) 615 { 616 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); 617 618 619 /* Referenced flag is set during the namespace xref */ 620 621 if (Node->Flags & ANOBJ_IS_REFERENCED) 622 { 623 return (AE_OK); 624 } 625 626 /* 627 * Ignore names that start with an underscore, 628 * these are the reserved ACPI names and are typically not referenced, 629 * they are called by the host OS. 630 */ 631 if (Node->Name.Ascii[0] == '_') 632 { 633 return (AE_OK); 634 } 635 636 /* There are some types that are typically not referenced, ignore them */ 637 638 switch (Node->Type) 639 { 640 case ACPI_TYPE_DEVICE: 641 case ACPI_TYPE_PROCESSOR: 642 case ACPI_TYPE_POWER: 643 case ACPI_TYPE_LOCAL_RESOURCE: 644 return (AE_OK); 645 646 default: 647 break; 648 } 649 650 /* All others are valid unreferenced namespace objects */ 651 652 if (Node->Op) 653 { 654 AslError (ASL_WARNING2, ASL_MSG_NOT_REFERENCED, LkGetNameOp (Node->Op), NULL); 655 } 656 return (AE_OK); 657 } 658 659 660 /******************************************************************************* 661 * 662 * FUNCTION: LkFindUnreferencedObjects 663 * 664 * PARAMETERS: None 665 * 666 * RETURN: None 667 * 668 * DESCRIPTION: Namespace walk to find objects that are not referenced in any 669 * way. Must be called after the namespace has been cross 670 * referenced. 671 * 672 ******************************************************************************/ 673 674 void 675 LkFindUnreferencedObjects ( 676 void) 677 { 678 679 /* Walk entire namespace from the supplied root */ 680 681 (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 682 ACPI_UINT32_MAX, FALSE, LkIsObjectUsed, 683 NULL, NULL); 684 } 685 686 687 /******************************************************************************* 688 * 689 * FUNCTION: LkCrossReferenceNamespace 690 * 691 * PARAMETERS: None 692 * 693 * RETURN: Status 694 * 695 * DESCRIPTION: Perform a cross reference check of the parse tree against the 696 * namespace. Every named referenced within the parse tree 697 * should be get resolved with a namespace lookup. If not, the 698 * original reference in the ASL code is invalid -- i.e., refers 699 * to a non-existent object. 700 * 701 * NOTE: The ASL "External" operator causes the name to be inserted into the 702 * namespace so that references to the external name will be resolved 703 * correctly here. 704 * 705 ******************************************************************************/ 706 707 ACPI_STATUS 708 LkCrossReferenceNamespace ( 709 void) 710 { 711 ACPI_WALK_STATE *WalkState; 712 713 714 DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n"); 715 716 /* 717 * Create a new walk state for use when looking up names 718 * within the namespace (Passed as context to the callbacks) 719 */ 720 WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); 721 if (!WalkState) 722 { 723 return AE_NO_MEMORY; 724 } 725 726 /* Walk the entire parse tree */ 727 728 TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, LkNamespaceLocateBegin, 729 LkNamespaceLocateEnd, WalkState); 730 return AE_OK; 731 } 732 733 734 /******************************************************************************* 735 * 736 * FUNCTION: LkCheckFieldRange 737 * 738 * PARAMETERS: RegionBitLength - Length of entire parent region 739 * FieldBitOffset - Start of the field unit (within region) 740 * FieldBitLength - Entire length of field unit 741 * AccessBitWidth - Access width of the field unit 742 * 743 * RETURN: None 744 * 745 * DESCRIPTION: Check one field unit to make sure it fits in the parent 746 * op region. 747 * 748 * Note: AccessBitWidth must be either 8,16,32, or 64 749 * 750 ******************************************************************************/ 751 752 static void 753 LkCheckFieldRange ( 754 ACPI_PARSE_OBJECT *Op, 755 UINT32 RegionBitLength, 756 UINT32 FieldBitOffset, 757 UINT32 FieldBitLength, 758 UINT32 AccessBitWidth) 759 { 760 UINT32 FieldEndBitOffset; 761 762 763 /* 764 * Check each field unit against the region size. The entire 765 * field unit (start offset plus length) must fit within the 766 * region. 767 */ 768 FieldEndBitOffset = FieldBitOffset + FieldBitLength; 769 770 if (FieldEndBitOffset > RegionBitLength) 771 { 772 /* Field definition itself is beyond the end-of-region */ 773 774 AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL); 775 return; 776 } 777 778 /* 779 * Now check that the field plus AccessWidth doesn't go beyond 780 * the end-of-region. Assumes AccessBitWidth is a power of 2 781 */ 782 FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth); 783 784 if (FieldEndBitOffset > RegionBitLength) 785 { 786 /* Field definition combined with the access is beyond EOR */ 787 788 AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL); 789 } 790 } 791 792 /******************************************************************************* 793 * 794 * FUNCTION: LkNamespaceLocateBegin 795 * 796 * PARAMETERS: ASL_WALK_CALLBACK 797 * 798 * RETURN: Status 799 * 800 * DESCRIPTION: Descending callback used during cross-reference. For named 801 * object references, attempt to locate the name in the 802 * namespace. 803 * 804 * NOTE: ASL references to named fields within resource descriptors are 805 * resolved to integer values here. Therefore, this step is an 806 * important part of the code generation. We don't know that the 807 * name refers to a resource descriptor until now. 808 * 809 ******************************************************************************/ 810 811 static ACPI_STATUS 812 LkNamespaceLocateBegin ( 813 ACPI_PARSE_OBJECT *Op, 814 UINT32 Level, 815 void *Context) 816 { 817 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 818 ACPI_NAMESPACE_NODE *Node; 819 ACPI_STATUS Status; 820 ACPI_OBJECT_TYPE ObjectType; 821 char *Path; 822 UINT8 PassedArgs; 823 ACPI_PARSE_OBJECT *NextOp; 824 ACPI_PARSE_OBJECT *OwningOp; 825 ACPI_PARSE_OBJECT *SpaceIdOp; 826 UINT32 MinimumLength; 827 UINT32 Temp; 828 const ACPI_OPCODE_INFO *OpInfo; 829 UINT32 Flags; 830 831 832 ACPI_FUNCTION_TRACE_PTR (LkNamespaceLocateBegin, Op); 833 834 /* 835 * If this node is the actual declaration of a name 836 * [such as the XXXX name in "Method (XXXX)"], 837 * we are not interested in it here. We only care about names that are 838 * references to other objects within the namespace and the parent objects 839 * of name declarations 840 */ 841 if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION) 842 { 843 return (AE_OK); 844 } 845 846 /* We are only interested in opcodes that have an associated name */ 847 848 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 849 850 if ((!(OpInfo->Flags & AML_NAMED)) && 851 (!(OpInfo->Flags & AML_CREATE)) && 852 (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) && 853 (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) && 854 (Op->Asl.ParseOpcode != PARSEOP_METHODCALL)) 855 { 856 return (AE_OK); 857 } 858 859 /* 860 * We must enable the "search-to-root" for single NameSegs, but 861 * we have to be very careful about opening up scopes 862 */ 863 Flags = ACPI_NS_SEARCH_PARENT; 864 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 865 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 866 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 867 { 868 /* 869 * These are name references, do not push the scope stack 870 * for them. 871 */ 872 Flags |= ACPI_NS_DONT_OPEN_SCOPE; 873 } 874 875 /* Get the NamePath from the appropriate place */ 876 877 if (OpInfo->Flags & AML_NAMED) 878 { 879 /* For nearly all NAMED operators, the name reference is the first child */ 880 881 Path = Op->Asl.Child->Asl.Value.String; 882 if (Op->Asl.AmlOpcode == AML_ALIAS_OP) 883 { 884 /* 885 * ALIAS is the only oddball opcode, the name declaration 886 * (alias name) is the second operand 887 */ 888 Path = Op->Asl.Child->Asl.Next->Asl.Value.String; 889 } 890 } 891 else if (OpInfo->Flags & AML_CREATE) 892 { 893 /* Name must appear as the last parameter */ 894 895 NextOp = Op->Asl.Child; 896 while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) 897 { 898 NextOp = NextOp->Asl.Next; 899 } 900 Path = NextOp->Asl.Value.String; 901 } 902 else 903 { 904 Path = Op->Asl.Value.String; 905 } 906 907 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 908 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 909 "Type=%s\n", AcpiUtGetTypeName (ObjectType))); 910 911 /* 912 * Lookup the name in the namespace. Name must exist at this point, or it 913 * is an invalid reference. 914 * 915 * The namespace is also used as a lookup table for references to resource 916 * descriptors and the fields within them. 917 */ 918 Gbl_NsLookupCount++; 919 920 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 921 ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node)); 922 if (ACPI_FAILURE (Status)) 923 { 924 if (Status == AE_NOT_FOUND) 925 { 926 /* 927 * We didn't find the name reference by path -- we can qualify this 928 * a little better before we print an error message 929 */ 930 if (strlen (Path) == ACPI_NAME_SIZE) 931 { 932 /* A simple, one-segment ACPI name */ 933 934 if (LkObjectExists (Path)) 935 { 936 /* 937 * There exists such a name, but we couldn't get to it 938 * from this scope 939 */ 940 AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op, 941 Op->Asl.ExternalName); 942 } 943 else 944 { 945 /* The name doesn't exist, period */ 946 947 if ((Op->Asl.Parent) && 948 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)) 949 { 950 /* Ignore not found if parent is CondRefOf */ 951 952 return (AE_OK); 953 } 954 955 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, 956 Op, Op->Asl.ExternalName); 957 } 958 } 959 else 960 { 961 /* Check for a fully qualified path */ 962 963 if (Path[0] == AML_ROOT_PREFIX) 964 { 965 /* Gave full path, the object does not exist */ 966 967 if ((Op->Asl.Parent) && 968 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)) 969 { 970 /* Ignore not found if parent is CondRefOf */ 971 972 return (AE_OK); 973 } 974 975 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, 976 Op->Asl.ExternalName); 977 } 978 else 979 { 980 /* 981 * We can't tell whether it doesn't exist or just 982 * can't be reached. 983 */ 984 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 985 Op->Asl.ExternalName); 986 } 987 } 988 989 Status = AE_OK; 990 } 991 return (Status); 992 } 993 994 /* Check for a reference vs. name declaration */ 995 996 if (!(OpInfo->Flags & AML_NAMED) && 997 !(OpInfo->Flags & AML_CREATE)) 998 { 999 /* This node has been referenced, mark it for reference check */ 1000 1001 Node->Flags |= ANOBJ_IS_REFERENCED; 1002 } 1003 1004 /* Attempt to optimize the NamePath */ 1005 1006 OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node); 1007 1008 /* 1009 * 1) Dereference an alias (A name reference that is an alias) 1010 * Aliases are not nested, the alias always points to the final object 1011 */ 1012 if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) && 1013 (Node->Type == ACPI_TYPE_LOCAL_ALIAS)) 1014 { 1015 /* This node points back to the original PARSEOP_ALIAS */ 1016 1017 NextOp = Node->Op; 1018 1019 /* The first child is the alias target op */ 1020 1021 NextOp = NextOp->Asl.Child; 1022 1023 /* That in turn points back to original target alias node */ 1024 1025 if (NextOp->Asl.Node) 1026 { 1027 Node = NextOp->Asl.Node; 1028 } 1029 1030 /* Else - forward reference to alias, will be resolved later */ 1031 } 1032 1033 /* 2) Check for a reference to a resource descriptor */ 1034 1035 if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 1036 (Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 1037 { 1038 /* 1039 * This was a reference to a field within a resource descriptor. Extract 1040 * the associated field offset (either a bit or byte offset depending on 1041 * the field type) and change the named reference into an integer for 1042 * AML code generation 1043 */ 1044 Temp = Node->Value; 1045 if (Node->Flags & ANOBJ_IS_BIT_OFFSET) 1046 { 1047 Op->Asl.CompileFlags |= NODE_IS_BIT_OFFSET; 1048 } 1049 1050 /* Perform BitOffset <--> ByteOffset conversion if necessary */ 1051 1052 switch (Op->Asl.Parent->Asl.AmlOpcode) 1053 { 1054 case AML_CREATE_FIELD_OP: 1055 1056 /* We allow a Byte offset to Bit Offset conversion for this op */ 1057 1058 if (!(Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET)) 1059 { 1060 /* Simply multiply byte offset times 8 to get bit offset */ 1061 1062 Temp = ACPI_MUL_8 (Temp); 1063 } 1064 break; 1065 1066 1067 case AML_CREATE_BIT_FIELD_OP: 1068 1069 /* This op requires a Bit Offset */ 1070 1071 if (!(Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET)) 1072 { 1073 AslError (ASL_ERROR, ASL_MSG_BYTES_TO_BITS, Op, NULL); 1074 } 1075 break; 1076 1077 1078 case AML_CREATE_BYTE_FIELD_OP: 1079 case AML_CREATE_WORD_FIELD_OP: 1080 case AML_CREATE_DWORD_FIELD_OP: 1081 case AML_CREATE_QWORD_FIELD_OP: 1082 case AML_INDEX_OP: 1083 1084 /* These Ops require Byte offsets */ 1085 1086 if (Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET) 1087 { 1088 AslError (ASL_ERROR, ASL_MSG_BITS_TO_BYTES, Op, NULL); 1089 } 1090 break; 1091 1092 1093 default: 1094 /* Nothing to do for other opcodes */ 1095 break; 1096 } 1097 1098 /* Now convert this node to an integer whose value is the field offset */ 1099 1100 Op->Asl.AmlLength = 0; 1101 Op->Asl.ParseOpcode = PARSEOP_INTEGER; 1102 Op->Asl.Value.Integer = (UINT64) Temp; 1103 Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD; 1104 1105 OpcGenerateAmlOpcode (Op); 1106 } 1107 1108 /* 3) Check for a method invocation */ 1109 1110 else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) && 1111 (Node->Type == ACPI_TYPE_METHOD) && 1112 (Op->Asl.Parent) && 1113 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) || 1114 1115 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 1116 { 1117 1118 /* 1119 * A reference to a method within one of these opcodes is not an 1120 * invocation of the method, it is simply a reference to the method. 1121 */ 1122 if ((Op->Asl.Parent) && 1123 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) || 1124 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF) || 1125 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE))) 1126 { 1127 return (AE_OK); 1128 } 1129 /* 1130 * There are two types of method invocation: 1131 * 1) Invocation with arguments -- the parser recognizes this 1132 * as a METHODCALL. 1133 * 2) Invocation with no arguments --the parser cannot determine that 1134 * this is a method invocation, therefore we have to figure it out 1135 * here. 1136 */ 1137 if (Node->Type != ACPI_TYPE_METHOD) 1138 { 1139 sprintf (MsgBuffer, "%s is a %s", 1140 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 1141 1142 AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer); 1143 return (AE_OK); 1144 } 1145 1146 /* Save the method node in the caller's op */ 1147 1148 Op->Asl.Node = Node; 1149 if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF) 1150 { 1151 return (AE_OK); 1152 } 1153 1154 /* 1155 * This is a method invocation, with or without arguments. 1156 * Count the number of arguments, each appears as a child 1157 * under the parent node 1158 */ 1159 Op->Asl.ParseOpcode = PARSEOP_METHODCALL; 1160 UtSetParseOpName (Op); 1161 1162 PassedArgs = 0; 1163 NextOp = Op->Asl.Child; 1164 1165 while (NextOp) 1166 { 1167 PassedArgs++; 1168 NextOp = NextOp->Asl.Next; 1169 } 1170 1171 if (Node->Value != ASL_EXTERNAL_METHOD) 1172 { 1173 /* 1174 * Check the parsed arguments with the number expected by the 1175 * method declaration itself 1176 */ 1177 if (PassedArgs != Node->Value) 1178 { 1179 sprintf (MsgBuffer, "%s requires %d", Op->Asl.ExternalName, 1180 Node->Value); 1181 1182 if (PassedArgs < Node->Value) 1183 { 1184 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer); 1185 } 1186 else 1187 { 1188 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer); 1189 } 1190 } 1191 } 1192 } 1193 1194 /* 4) Check for an ASL Field definition */ 1195 1196 else if ((Op->Asl.Parent) && 1197 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) || 1198 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD))) 1199 { 1200 /* 1201 * Offset checking for fields. If the parent operation region has a 1202 * constant length (known at compile time), we can check fields 1203 * defined in that region against the region length. This will catch 1204 * fields and field units that cannot possibly fit within the region. 1205 * 1206 * Note: Index fields do not directly reference an operation region, 1207 * thus they are not included in this check. 1208 */ 1209 if (Op == Op->Asl.Parent->Asl.Child) 1210 { 1211 /* 1212 * This is the first child of the field node, which is 1213 * the name of the region. Get the parse node for the 1214 * region -- which contains the length of the region. 1215 */ 1216 OwningOp = Node->Op; 1217 Op->Asl.Parent->Asl.ExtraValue = 1218 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer); 1219 1220 /* Examine the field access width */ 1221 1222 switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer) 1223 { 1224 case AML_FIELD_ACCESS_ANY: 1225 case AML_FIELD_ACCESS_BYTE: 1226 case AML_FIELD_ACCESS_BUFFER: 1227 default: 1228 MinimumLength = 1; 1229 break; 1230 1231 case AML_FIELD_ACCESS_WORD: 1232 MinimumLength = 2; 1233 break; 1234 1235 case AML_FIELD_ACCESS_DWORD: 1236 MinimumLength = 4; 1237 break; 1238 1239 case AML_FIELD_ACCESS_QWORD: 1240 MinimumLength = 8; 1241 break; 1242 } 1243 1244 /* 1245 * Is the region at least as big as the access width? 1246 * Note: DataTableRegions have 0 length 1247 */ 1248 if (((UINT32) OwningOp->Asl.Value.Integer) && 1249 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength)) 1250 { 1251 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL); 1252 } 1253 1254 /* 1255 * Check EC/CMOS/SMBUS fields to make sure that the correct 1256 * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS) 1257 */ 1258 SpaceIdOp = OwningOp->Asl.Child->Asl.Next; 1259 switch ((UINT32) SpaceIdOp->Asl.Value.Integer) 1260 { 1261 case REGION_EC: 1262 case REGION_CMOS: 1263 1264 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE) 1265 { 1266 AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL); 1267 } 1268 break; 1269 1270 case REGION_SMBUS: 1271 1272 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER) 1273 { 1274 AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL); 1275 } 1276 break; 1277 1278 default: 1279 1280 /* Nothing to do for other address spaces */ 1281 break; 1282 } 1283 } 1284 else 1285 { 1286 /* 1287 * This is one element of the field list. Check to make sure 1288 * that it does not go beyond the end of the parent operation region. 1289 * 1290 * In the code below: 1291 * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits) 1292 * Op->Asl.ExtraValue - Field start offset (bits) 1293 * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits) 1294 * Op->Asl.Child->Asl.ExtraValue - Field access width (bits) 1295 */ 1296 if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child) 1297 { 1298 LkCheckFieldRange (Op, 1299 Op->Asl.Parent->Asl.ExtraValue, 1300 Op->Asl.ExtraValue, 1301 (UINT32) Op->Asl.Child->Asl.Value.Integer, 1302 Op->Asl.Child->Asl.ExtraValue); 1303 } 1304 } 1305 } 1306 1307 Op->Asl.Node = Node; 1308 return (Status); 1309 } 1310 1311 1312 /******************************************************************************* 1313 * 1314 * FUNCTION: LkNamespaceLocateEnd 1315 * 1316 * PARAMETERS: ASL_WALK_CALLBACK 1317 * 1318 * RETURN: Status 1319 * 1320 * DESCRIPTION: Ascending callback used during cross reference. We only 1321 * need to worry about scope management here. 1322 * 1323 ******************************************************************************/ 1324 1325 static ACPI_STATUS 1326 LkNamespaceLocateEnd ( 1327 ACPI_PARSE_OBJECT *Op, 1328 UINT32 Level, 1329 void *Context) 1330 { 1331 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 1332 const ACPI_OPCODE_INFO *OpInfo; 1333 1334 1335 ACPI_FUNCTION_TRACE (LkNamespaceLocateEnd); 1336 1337 1338 /* We are only interested in opcodes that have an associated name */ 1339 1340 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1341 if (!(OpInfo->Flags & AML_NAMED)) 1342 { 1343 return (AE_OK); 1344 } 1345 1346 /* Not interested in name references, we did not open a scope for them */ 1347 1348 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 1349 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 1350 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 1351 { 1352 return (AE_OK); 1353 } 1354 1355 /* Pop the scope stack if necessary */ 1356 1357 if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode))) 1358 { 1359 1360 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 1361 "%s: Popping scope for Op %p\n", 1362 AcpiUtGetTypeName (OpInfo->ObjectType), Op)); 1363 1364 (void) AcpiDsScopeStackPop (WalkState); 1365 } 1366 1367 return (AE_OK); 1368 } 1369 1370 1371