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