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 Temp; 826 const ACPI_OPCODE_INFO *OpInfo; 827 UINT32 Flags; 828 829 830 ACPI_FUNCTION_TRACE_PTR (LkNamespaceLocateBegin, Op); 831 832 /* 833 * If this node is the actual declaration of a name 834 * [such as the XXXX name in "Method (XXXX)"], 835 * we are not interested in it here. We only care about names that are 836 * references to other objects within the namespace and the parent objects 837 * of name declarations 838 */ 839 if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION) 840 { 841 return (AE_OK); 842 } 843 844 /* We are only interested in opcodes that have an associated name */ 845 846 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 847 848 if ((!(OpInfo->Flags & AML_NAMED)) && 849 (!(OpInfo->Flags & AML_CREATE)) && 850 (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) && 851 (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) && 852 (Op->Asl.ParseOpcode != PARSEOP_METHODCALL)) 853 { 854 return (AE_OK); 855 } 856 857 /* 858 * One special case: CondRefOf operator - we don't care if the name exists 859 * or not at this point, just ignore it, the point of the operator is to 860 * determine if the name exists at runtime. 861 */ 862 if ((Op->Asl.Parent) && 863 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)) 864 { 865 return (AE_OK); 866 } 867 868 /* 869 * We must enable the "search-to-root" for single NameSegs, but 870 * we have to be very careful about opening up scopes 871 */ 872 Flags = ACPI_NS_SEARCH_PARENT; 873 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 874 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 875 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 876 { 877 /* 878 * These are name references, do not push the scope stack 879 * for them. 880 */ 881 Flags |= ACPI_NS_DONT_OPEN_SCOPE; 882 } 883 884 /* Get the NamePath from the appropriate place */ 885 886 if (OpInfo->Flags & AML_NAMED) 887 { 888 /* For nearly all NAMED operators, the name reference is the first child */ 889 890 Path = Op->Asl.Child->Asl.Value.String; 891 if (Op->Asl.AmlOpcode == AML_ALIAS_OP) 892 { 893 /* 894 * ALIAS is the only oddball opcode, the name declaration 895 * (alias name) is the second operand 896 */ 897 Path = Op->Asl.Child->Asl.Next->Asl.Value.String; 898 } 899 } 900 else if (OpInfo->Flags & AML_CREATE) 901 { 902 /* Name must appear as the last parameter */ 903 904 NextOp = Op->Asl.Child; 905 while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) 906 { 907 NextOp = NextOp->Asl.Next; 908 } 909 Path = NextOp->Asl.Value.String; 910 } 911 else 912 { 913 Path = Op->Asl.Value.String; 914 } 915 916 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 917 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 918 "Type=%s\n", AcpiUtGetTypeName (ObjectType))); 919 920 /* 921 * Lookup the name in the namespace. Name must exist at this point, or it 922 * is an invalid reference. 923 * 924 * The namespace is also used as a lookup table for references to resource 925 * descriptors and the fields within them. 926 */ 927 Gbl_NsLookupCount++; 928 929 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 930 ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node)); 931 if (ACPI_FAILURE (Status)) 932 { 933 if (Status == AE_NOT_FOUND) 934 { 935 /* 936 * We didn't find the name reference by path -- we can qualify this 937 * a little better before we print an error message 938 */ 939 if (strlen (Path) == ACPI_NAME_SIZE) 940 { 941 /* A simple, one-segment ACPI name */ 942 943 if (LkObjectExists (Path)) 944 { 945 /* 946 * There exists such a name, but we couldn't get to it 947 * from this scope 948 */ 949 AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op, 950 Op->Asl.ExternalName); 951 } 952 else 953 { 954 /* The name doesn't exist, period */ 955 956 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, 957 Op, Op->Asl.ExternalName); 958 } 959 } 960 else 961 { 962 /* Check for a fully qualified path */ 963 964 if (Path[0] == AML_ROOT_PREFIX) 965 { 966 /* Gave full path, the object does not exist */ 967 968 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, 969 Op->Asl.ExternalName); 970 } 971 else 972 { 973 /* 974 * We can't tell whether it doesn't exist or just 975 * can't be reached. 976 */ 977 AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 978 Op->Asl.ExternalName); 979 } 980 } 981 982 Status = AE_OK; 983 } 984 return (Status); 985 } 986 987 /* Check for a reference vs. name declaration */ 988 989 if (!(OpInfo->Flags & AML_NAMED) && 990 !(OpInfo->Flags & AML_CREATE)) 991 { 992 /* This node has been referenced, mark it for reference check */ 993 994 Node->Flags |= ANOBJ_IS_REFERENCED; 995 } 996 997 /* Attempt to optimize the NamePath */ 998 999 OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node); 1000 1001 /* 1002 * 1) Dereference an alias (A name reference that is an alias) 1003 * Aliases are not nested, the alias always points to the final object 1004 */ 1005 if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) && 1006 (Node->Type == ACPI_TYPE_LOCAL_ALIAS)) 1007 { 1008 /* This node points back to the original PARSEOP_ALIAS */ 1009 1010 NextOp = Node->Op; 1011 1012 /* The first child is the alias target op */ 1013 1014 NextOp = NextOp->Asl.Child; 1015 1016 /* That in turn points back to original target alias node */ 1017 1018 if (NextOp->Asl.Node) 1019 { 1020 Node = NextOp->Asl.Node; 1021 } 1022 1023 /* Else - forward reference to alias, will be resolved later */ 1024 } 1025 1026 /* 2) Check for a reference to a resource descriptor */ 1027 1028 if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 1029 (Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 1030 { 1031 /* 1032 * This was a reference to a field within a resource descriptor. Extract 1033 * the associated field offset (either a bit or byte offset depending on 1034 * the field type) and change the named reference into an integer for 1035 * AML code generation 1036 */ 1037 Temp = Node->Value; 1038 if (Node->Flags & ANOBJ_IS_BIT_OFFSET) 1039 { 1040 Op->Asl.CompileFlags |= NODE_IS_BIT_OFFSET; 1041 } 1042 1043 /* Perform BitOffset <--> ByteOffset conversion if necessary */ 1044 1045 switch (Op->Asl.Parent->Asl.AmlOpcode) 1046 { 1047 case AML_CREATE_FIELD_OP: 1048 1049 /* We allow a Byte offset to Bit Offset conversion for this op */ 1050 1051 if (!(Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET)) 1052 { 1053 /* Simply multiply byte offset times 8 to get bit offset */ 1054 1055 Temp = ACPI_MUL_8 (Temp); 1056 } 1057 break; 1058 1059 1060 case AML_CREATE_BIT_FIELD_OP: 1061 1062 /* This op requires a Bit Offset */ 1063 1064 if (!(Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET)) 1065 { 1066 AslError (ASL_ERROR, ASL_MSG_BYTES_TO_BITS, Op, NULL); 1067 } 1068 break; 1069 1070 1071 case AML_CREATE_BYTE_FIELD_OP: 1072 case AML_CREATE_WORD_FIELD_OP: 1073 case AML_CREATE_DWORD_FIELD_OP: 1074 case AML_CREATE_QWORD_FIELD_OP: 1075 case AML_INDEX_OP: 1076 1077 /* These Ops require Byte offsets */ 1078 1079 if (Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET) 1080 { 1081 AslError (ASL_ERROR, ASL_MSG_BITS_TO_BYTES, Op, NULL); 1082 } 1083 break; 1084 1085 1086 default: 1087 /* Nothing to do for other opcodes */ 1088 break; 1089 } 1090 1091 /* Now convert this node to an integer whose value is the field offset */ 1092 1093 Op->Asl.AmlLength = 0; 1094 Op->Asl.ParseOpcode = PARSEOP_INTEGER; 1095 Op->Asl.Value.Integer = (UINT64) Temp; 1096 Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD; 1097 1098 OpcGenerateAmlOpcode (Op); 1099 } 1100 1101 /* 3) Check for a method invocation */ 1102 1103 else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) && 1104 (Node->Type == ACPI_TYPE_METHOD) && 1105 (Op->Asl.Parent) && 1106 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) || 1107 1108 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 1109 { 1110 1111 /* 1112 * A reference to a method within one of these opcodes is not an 1113 * invocation of the method, it is simply a reference to the method. 1114 */ 1115 if ((Op->Asl.Parent) && 1116 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) || 1117 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF) || 1118 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE))) 1119 { 1120 return (AE_OK); 1121 } 1122 /* 1123 * There are two types of method invocation: 1124 * 1) Invocation with arguments -- the parser recognizes this 1125 * as a METHODCALL. 1126 * 2) Invocation with no arguments --the parser cannot determine that 1127 * this is a method invocation, therefore we have to figure it out 1128 * here. 1129 */ 1130 if (Node->Type != ACPI_TYPE_METHOD) 1131 { 1132 sprintf (MsgBuffer, "%s is a %s", 1133 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 1134 1135 AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer); 1136 return (AE_OK); 1137 } 1138 1139 /* Save the method node in the caller's op */ 1140 1141 Op->Asl.Node = Node; 1142 if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF) 1143 { 1144 return (AE_OK); 1145 } 1146 1147 /* 1148 * This is a method invocation, with or without arguments. 1149 * Count the number of arguments, each appears as a child 1150 * under the parent node 1151 */ 1152 Op->Asl.ParseOpcode = PARSEOP_METHODCALL; 1153 UtSetParseOpName (Op); 1154 1155 PassedArgs = 0; 1156 NextOp = Op->Asl.Child; 1157 1158 while (NextOp) 1159 { 1160 PassedArgs++; 1161 NextOp = NextOp->Asl.Next; 1162 } 1163 1164 if (Node->Value != ASL_EXTERNAL_METHOD) 1165 { 1166 /* 1167 * Check the parsed arguments with the number expected by the 1168 * method declaration itself 1169 */ 1170 if (PassedArgs != Node->Value) 1171 { 1172 sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName, 1173 Node->Value); 1174 1175 if (PassedArgs < Node->Value) 1176 { 1177 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer); 1178 } 1179 else 1180 { 1181 AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer); 1182 } 1183 } 1184 } 1185 } 1186 1187 /* 4) Check for an ASL Field definition */ 1188 1189 else if ((Op->Asl.Parent) && 1190 ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) || 1191 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD))) 1192 { 1193 /* 1194 * Offset checking for fields. If the parent operation region has a 1195 * constant length (known at compile time), we can check fields 1196 * defined in that region against the region length. This will catch 1197 * fields and field units that cannot possibly fit within the region. 1198 * 1199 * Note: Index fields do not directly reference an operation region, 1200 * thus they are not included in this check. 1201 */ 1202 if (Op == Op->Asl.Parent->Asl.Child) 1203 { 1204 /* 1205 * This is the first child of the field node, which is 1206 * the name of the region. Get the parse node for the 1207 * region -- which contains the length of the region. 1208 */ 1209 OwningOp = Node->Op; 1210 Op->Asl.Parent->Asl.ExtraValue = 1211 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer); 1212 1213 /* Examine the field access width */ 1214 1215 switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer) 1216 { 1217 case AML_FIELD_ACCESS_ANY: 1218 case AML_FIELD_ACCESS_BYTE: 1219 case AML_FIELD_ACCESS_BUFFER: 1220 default: 1221 MinimumLength = 1; 1222 break; 1223 1224 case AML_FIELD_ACCESS_WORD: 1225 MinimumLength = 2; 1226 break; 1227 1228 case AML_FIELD_ACCESS_DWORD: 1229 MinimumLength = 4; 1230 break; 1231 1232 case AML_FIELD_ACCESS_QWORD: 1233 MinimumLength = 8; 1234 break; 1235 } 1236 1237 /* 1238 * Is the region at least as big as the access width? 1239 * Note: DataTableRegions have 0 length 1240 */ 1241 if (((UINT32) OwningOp->Asl.Value.Integer) && 1242 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength)) 1243 { 1244 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL); 1245 } 1246 1247 /* 1248 * Check EC/CMOS/SMBUS fields to make sure that the correct 1249 * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS) 1250 */ 1251 SpaceIdOp = OwningOp->Asl.Child->Asl.Next; 1252 switch ((UINT32) SpaceIdOp->Asl.Value.Integer) 1253 { 1254 case ACPI_ADR_SPACE_EC: 1255 case ACPI_ADR_SPACE_CMOS: 1256 1257 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE) 1258 { 1259 AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL); 1260 } 1261 break; 1262 1263 case ACPI_ADR_SPACE_SMBUS: 1264 case ACPI_ADR_SPACE_IPMI: 1265 1266 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER) 1267 { 1268 AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL); 1269 } 1270 break; 1271 1272 default: 1273 1274 /* Nothing to do for other address spaces */ 1275 break; 1276 } 1277 } 1278 else 1279 { 1280 /* 1281 * This is one element of the field list. Check to make sure 1282 * that it does not go beyond the end of the parent operation region. 1283 * 1284 * In the code below: 1285 * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits) 1286 * Op->Asl.ExtraValue - Field start offset (bits) 1287 * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits) 1288 * Op->Asl.Child->Asl.ExtraValue - Field access width (bits) 1289 */ 1290 if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child) 1291 { 1292 LkCheckFieldRange (Op, 1293 Op->Asl.Parent->Asl.ExtraValue, 1294 Op->Asl.ExtraValue, 1295 (UINT32) Op->Asl.Child->Asl.Value.Integer, 1296 Op->Asl.Child->Asl.ExtraValue); 1297 } 1298 } 1299 } 1300 1301 Op->Asl.Node = Node; 1302 return (Status); 1303 } 1304 1305 1306 /******************************************************************************* 1307 * 1308 * FUNCTION: LkNamespaceLocateEnd 1309 * 1310 * PARAMETERS: ASL_WALK_CALLBACK 1311 * 1312 * RETURN: Status 1313 * 1314 * DESCRIPTION: Ascending callback used during cross reference. We only 1315 * need to worry about scope management here. 1316 * 1317 ******************************************************************************/ 1318 1319 static ACPI_STATUS 1320 LkNamespaceLocateEnd ( 1321 ACPI_PARSE_OBJECT *Op, 1322 UINT32 Level, 1323 void *Context) 1324 { 1325 ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 1326 const ACPI_OPCODE_INFO *OpInfo; 1327 1328 1329 ACPI_FUNCTION_TRACE (LkNamespaceLocateEnd); 1330 1331 1332 /* We are only interested in opcodes that have an associated name */ 1333 1334 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1335 if (!(OpInfo->Flags & AML_NAMED)) 1336 { 1337 return (AE_OK); 1338 } 1339 1340 /* Not interested in name references, we did not open a scope for them */ 1341 1342 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 1343 (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 1344 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 1345 { 1346 return (AE_OK); 1347 } 1348 1349 /* Pop the scope stack if necessary */ 1350 1351 if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode))) 1352 { 1353 1354 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 1355 "%s: Popping scope for Op %p\n", 1356 AcpiUtGetTypeName (OpInfo->ObjectType), Op)); 1357 1358 (void) AcpiDsScopeStackPop (WalkState); 1359 } 1360 1361 return (AE_OK); 1362 } 1363 1364 1365