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