1 /****************************************************************************** 2 * 3 * Module Name: adwalk - Application-level disassembler parse tree walk routines 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/include/acpi.h> 46 #include <contrib/dev/acpica/include/accommon.h> 47 #include <contrib/dev/acpica/include/acparser.h> 48 #include <contrib/dev/acpica/include/amlcode.h> 49 #include <contrib/dev/acpica/include/acdisasm.h> 50 #include <contrib/dev/acpica/include/acdispat.h> 51 #include <contrib/dev/acpica/include/acnamesp.h> 52 #include <contrib/dev/acpica/include/acapps.h> 53 54 55 #define _COMPONENT ACPI_TOOLS 56 ACPI_MODULE_NAME ("adwalk") 57 58 /* 59 * aslmap - opcode mappings and reserved method names 60 */ 61 ACPI_OBJECT_TYPE 62 AslMapNamedOpcodeToDataType ( 63 UINT16 Opcode); 64 65 /* Local prototypes */ 66 67 static ACPI_STATUS 68 AcpiDmFindOrphanDescending ( 69 ACPI_PARSE_OBJECT *Op, 70 UINT32 Level, 71 void *Context); 72 73 static ACPI_STATUS 74 AcpiDmDumpDescending ( 75 ACPI_PARSE_OBJECT *Op, 76 UINT32 Level, 77 void *Context); 78 79 static ACPI_STATUS 80 AcpiDmXrefDescendingOp ( 81 ACPI_PARSE_OBJECT *Op, 82 UINT32 Level, 83 void *Context); 84 85 static ACPI_STATUS 86 AcpiDmCommonAscendingOp ( 87 ACPI_PARSE_OBJECT *Op, 88 UINT32 Level, 89 void *Context); 90 91 static ACPI_STATUS 92 AcpiDmLoadDescendingOp ( 93 ACPI_PARSE_OBJECT *Op, 94 UINT32 Level, 95 void *Context); 96 97 static UINT32 98 AcpiDmInspectPossibleArgs ( 99 UINT32 CurrentOpArgCount, 100 UINT32 TargetCount, 101 ACPI_PARSE_OBJECT *Op); 102 103 static ACPI_STATUS 104 AcpiDmResourceDescendingOp ( 105 ACPI_PARSE_OBJECT *Op, 106 UINT32 Level, 107 void *Context); 108 109 110 /******************************************************************************* 111 * 112 * FUNCTION: AcpiDmDumpTree 113 * 114 * PARAMETERS: Origin - Starting object 115 * 116 * RETURN: None 117 * 118 * DESCRIPTION: Parse tree walk to format and output the nodes 119 * 120 ******************************************************************************/ 121 122 void 123 AcpiDmDumpTree ( 124 ACPI_PARSE_OBJECT *Origin) 125 { 126 ACPI_OP_WALK_INFO Info; 127 128 129 if (!Origin) 130 { 131 return; 132 } 133 134 AcpiOsPrintf ("/*\nAML Parse Tree\n\n"); 135 Info.Flags = 0; 136 Info.Count = 0; 137 Info.Level = 0; 138 Info.WalkState = NULL; 139 AcpiDmWalkParseTree (Origin, AcpiDmDumpDescending, NULL, &Info); 140 AcpiOsPrintf ("*/\n\n"); 141 } 142 143 144 /******************************************************************************* 145 * 146 * FUNCTION: AcpiDmFindOrphanMethods 147 * 148 * PARAMETERS: Origin - Starting object 149 * 150 * RETURN: None 151 * 152 * DESCRIPTION: Parse tree walk to find "orphaned" method invocations -- methods 153 * that are not resolved in the namespace 154 * 155 ******************************************************************************/ 156 157 void 158 AcpiDmFindOrphanMethods ( 159 ACPI_PARSE_OBJECT *Origin) 160 { 161 ACPI_OP_WALK_INFO Info; 162 163 164 if (!Origin) 165 { 166 return; 167 } 168 169 Info.Flags = 0; 170 Info.Level = 0; 171 Info.WalkState = NULL; 172 AcpiDmWalkParseTree (Origin, AcpiDmFindOrphanDescending, NULL, &Info); 173 } 174 175 176 /******************************************************************************* 177 * 178 * FUNCTION: AcpiDmFinishNamespaceLoad 179 * 180 * PARAMETERS: ParseTreeRoot - Root of the parse tree 181 * NamespaceRoot - Root of the internal namespace 182 * OwnerId - OwnerId of the table to be disassembled 183 * 184 * RETURN: None 185 * 186 * DESCRIPTION: Load all namespace items that are created within control 187 * methods. Used before namespace cross reference 188 * 189 ******************************************************************************/ 190 191 void 192 AcpiDmFinishNamespaceLoad ( 193 ACPI_PARSE_OBJECT *ParseTreeRoot, 194 ACPI_NAMESPACE_NODE *NamespaceRoot, 195 ACPI_OWNER_ID OwnerId) 196 { 197 ACPI_STATUS Status; 198 ACPI_OP_WALK_INFO Info; 199 ACPI_WALK_STATE *WalkState; 200 201 202 if (!ParseTreeRoot) 203 { 204 return; 205 } 206 207 /* Create and initialize a new walk state */ 208 209 WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL); 210 if (!WalkState) 211 { 212 return; 213 } 214 215 Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); 216 if (ACPI_FAILURE (Status)) 217 { 218 return; 219 } 220 221 Info.Flags = 0; 222 Info.Level = 0; 223 Info.WalkState = WalkState; 224 AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmLoadDescendingOp, 225 AcpiDmCommonAscendingOp, &Info); 226 ACPI_FREE (WalkState); 227 } 228 229 230 /******************************************************************************* 231 * 232 * FUNCTION: AcpiDmCrossReferenceNamespace 233 * 234 * PARAMETERS: ParseTreeRoot - Root of the parse tree 235 * NamespaceRoot - Root of the internal namespace 236 * OwnerId - OwnerId of the table to be disassembled 237 * 238 * RETURN: None 239 * 240 * DESCRIPTION: Cross reference the namespace to create externals 241 * 242 ******************************************************************************/ 243 244 void 245 AcpiDmCrossReferenceNamespace ( 246 ACPI_PARSE_OBJECT *ParseTreeRoot, 247 ACPI_NAMESPACE_NODE *NamespaceRoot, 248 ACPI_OWNER_ID OwnerId) 249 { 250 ACPI_STATUS Status; 251 ACPI_OP_WALK_INFO Info; 252 ACPI_WALK_STATE *WalkState; 253 254 255 if (!ParseTreeRoot) 256 { 257 return; 258 } 259 260 /* Create and initialize a new walk state */ 261 262 WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL); 263 if (!WalkState) 264 { 265 return; 266 } 267 268 Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); 269 if (ACPI_FAILURE (Status)) 270 { 271 return; 272 } 273 274 Info.Flags = 0; 275 Info.Level = 0; 276 Info.WalkState = WalkState; 277 AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmXrefDescendingOp, 278 AcpiDmCommonAscendingOp, &Info); 279 ACPI_FREE (WalkState); 280 } 281 282 283 /******************************************************************************* 284 * 285 * FUNCTION: AcpiDmConvertResourceIndexes 286 * 287 * PARAMETERS: ParseTreeRoot - Root of the parse tree 288 * NamespaceRoot - Root of the internal namespace 289 * 290 * RETURN: None 291 * 292 * DESCRIPTION: Convert fixed-offset references to resource descriptors to 293 * symbolic references. Should only be called after namespace has 294 * been cross referenced. 295 * 296 ******************************************************************************/ 297 298 void 299 AcpiDmConvertResourceIndexes ( 300 ACPI_PARSE_OBJECT *ParseTreeRoot, 301 ACPI_NAMESPACE_NODE *NamespaceRoot) 302 { 303 ACPI_STATUS Status; 304 ACPI_OP_WALK_INFO Info; 305 ACPI_WALK_STATE *WalkState; 306 307 308 if (!ParseTreeRoot) 309 { 310 return; 311 } 312 313 /* Create and initialize a new walk state */ 314 315 WalkState = AcpiDsCreateWalkState (0, ParseTreeRoot, NULL, NULL); 316 if (!WalkState) 317 { 318 return; 319 } 320 321 Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); 322 if (ACPI_FAILURE (Status)) 323 { 324 return; 325 } 326 327 Info.Flags = 0; 328 Info.Level = 0; 329 Info.WalkState = WalkState; 330 AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmResourceDescendingOp, 331 AcpiDmCommonAscendingOp, &Info); 332 ACPI_FREE (WalkState); 333 return; 334 } 335 336 337 /******************************************************************************* 338 * 339 * FUNCTION: AcpiDmDumpDescending 340 * 341 * PARAMETERS: ASL_WALK_CALLBACK 342 * 343 * RETURN: Status 344 * 345 * DESCRIPTION: Format and print contents of one parse Op. 346 * 347 ******************************************************************************/ 348 349 static ACPI_STATUS 350 AcpiDmDumpDescending ( 351 ACPI_PARSE_OBJECT *Op, 352 UINT32 Level, 353 void *Context) 354 { 355 ACPI_OP_WALK_INFO *Info = Context; 356 char *Path; 357 358 359 if (!Op) 360 { 361 return (AE_OK); 362 } 363 364 /* Most of the information (count, level, name) here */ 365 366 Info->Count++; 367 AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level); 368 AcpiDmIndent (Level); 369 AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode)); 370 371 /* Extra info is helpful */ 372 373 switch (Op->Common.AmlOpcode) 374 { 375 case AML_BYTE_OP: 376 case AML_WORD_OP: 377 case AML_DWORD_OP: 378 AcpiOsPrintf ("%X", (UINT32) Op->Common.Value.Integer); 379 break; 380 381 case AML_INT_NAMEPATH_OP: 382 if (Op->Common.Value.String) 383 { 384 AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String, 385 NULL, &Path); 386 AcpiOsPrintf ("%s %p", Path, Op->Common.Node); 387 ACPI_FREE (Path); 388 } 389 else 390 { 391 AcpiOsPrintf ("[NULL]"); 392 } 393 break; 394 395 case AML_NAME_OP: 396 case AML_METHOD_OP: 397 case AML_DEVICE_OP: 398 case AML_INT_NAMEDFIELD_OP: 399 AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name)); 400 break; 401 402 default: 403 break; 404 } 405 406 AcpiOsPrintf ("\n"); 407 return (AE_OK); 408 } 409 410 411 /******************************************************************************* 412 * 413 * FUNCTION: AcpiDmFindOrphanDescending 414 * 415 * PARAMETERS: ASL_WALK_CALLBACK 416 * 417 * RETURN: Status 418 * 419 * DESCRIPTION: Check namepath Ops for orphaned method invocations 420 * 421 * Note: Experimental. 422 * 423 ******************************************************************************/ 424 425 static ACPI_STATUS 426 AcpiDmFindOrphanDescending ( 427 ACPI_PARSE_OBJECT *Op, 428 UINT32 Level, 429 void *Context) 430 { 431 const ACPI_OPCODE_INFO *OpInfo; 432 ACPI_PARSE_OBJECT *ChildOp; 433 ACPI_PARSE_OBJECT *NextOp; 434 ACPI_PARSE_OBJECT *ParentOp; 435 UINT32 ArgCount; 436 437 438 if (!Op) 439 { 440 return (AE_OK); 441 } 442 443 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 444 445 switch (Op->Common.AmlOpcode) 446 { 447 #ifdef ACPI_UNDER_DEVELOPMENT 448 case AML_ADD_OP: 449 ChildOp = Op->Common.Value.Arg; 450 if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 451 !ChildOp->Common.Node) 452 { 453 AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String, 454 NULL, &Path); 455 AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s */\n", Op->Common.AmlOpName, Path); 456 ACPI_FREE (Path); 457 458 NextOp = Op->Common.Next; 459 if (!NextOp) 460 { 461 /* This NamePath has no args, assume it is an integer */ 462 463 AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 464 return (AE_OK); 465 } 466 467 ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp); 468 AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n", ArgCount, AcpiDmCountChildren (Op)); 469 470 if (ArgCount < 1) 471 { 472 /* One Arg means this is just a Store(Name,Target) */ 473 474 AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 475 return (AE_OK); 476 } 477 478 AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); 479 } 480 break; 481 #endif 482 483 case AML_STORE_OP: 484 485 ChildOp = Op->Common.Value.Arg; 486 if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 487 !ChildOp->Common.Node) 488 { 489 NextOp = Op->Common.Next; 490 if (!NextOp) 491 { 492 /* This NamePath has no args, assume it is an integer */ 493 494 AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 495 return (AE_OK); 496 } 497 498 ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp); 499 if (ArgCount <= 1) 500 { 501 /* One Arg means this is just a Store(Name,Target) */ 502 503 AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 504 return (AE_OK); 505 } 506 507 AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); 508 } 509 break; 510 511 case AML_INT_NAMEPATH_OP: 512 513 /* Must examine parent to see if this namepath is an argument */ 514 515 ParentOp = Op->Common.Parent; 516 OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); 517 518 if ((OpInfo->Class != AML_CLASS_EXECUTE) && 519 (OpInfo->Class != AML_CLASS_CREATE) && 520 (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && 521 !Op->Common.Node) 522 { 523 ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next); 524 525 /* 526 * Check if namepath is a predicate for if/while or lone parameter to 527 * a return. 528 */ 529 if (ArgCount == 0) 530 { 531 if (((ParentOp->Common.AmlOpcode == AML_IF_OP) || 532 (ParentOp->Common.AmlOpcode == AML_WHILE_OP) || 533 (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) && 534 535 /* And namepath is the first argument */ 536 (ParentOp->Common.Value.Arg == Op)) 537 { 538 AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_INTEGER, 0); 539 break; 540 } 541 } 542 543 /* 544 * This is a standalone namestring (not a parameter to another 545 * operator) - it *must* be a method invocation, nothing else is 546 * grammatically possible. 547 */ 548 AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); 549 550 } 551 break; 552 553 default: 554 break; 555 } 556 557 return (AE_OK); 558 } 559 560 561 /******************************************************************************* 562 * 563 * FUNCTION: AcpiDmLoadDescendingOp 564 * 565 * PARAMETERS: ASL_WALK_CALLBACK 566 * 567 * RETURN: Status 568 * 569 * DESCRIPTION: Descending handler for namespace control method object load 570 * 571 ******************************************************************************/ 572 573 static ACPI_STATUS 574 AcpiDmLoadDescendingOp ( 575 ACPI_PARSE_OBJECT *Op, 576 UINT32 Level, 577 void *Context) 578 { 579 ACPI_OP_WALK_INFO *Info = Context; 580 const ACPI_OPCODE_INFO *OpInfo; 581 ACPI_WALK_STATE *WalkState; 582 ACPI_OBJECT_TYPE ObjectType; 583 ACPI_STATUS Status; 584 char *Path = NULL; 585 ACPI_PARSE_OBJECT *NextOp; 586 ACPI_NAMESPACE_NODE *Node; 587 char FieldPath[5]; 588 BOOLEAN PreDefined = FALSE; 589 UINT8 PreDefineIndex = 0; 590 591 592 WalkState = Info->WalkState; 593 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 594 ObjectType = OpInfo->ObjectType; 595 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 596 597 /* Only interested in operators that create new names */ 598 599 if (!(OpInfo->Flags & AML_NAMED) && 600 !(OpInfo->Flags & AML_CREATE)) 601 { 602 goto Exit; 603 } 604 605 /* Get the NamePath from the appropriate place */ 606 607 if (OpInfo->Flags & AML_NAMED) 608 { 609 /* For all named operators, get the new name */ 610 611 Path = (char *) Op->Named.Path; 612 613 if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) 614 { 615 *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name; 616 FieldPath[4] = 0; 617 Path = FieldPath; 618 } 619 } 620 else if (OpInfo->Flags & AML_CREATE) 621 { 622 /* New name is the last child */ 623 624 NextOp = Op->Common.Value.Arg; 625 626 while (NextOp->Common.Next) 627 { 628 NextOp = NextOp->Common.Next; 629 } 630 Path = NextOp->Common.Value.String; 631 } 632 633 if (!Path) 634 { 635 goto Exit; 636 } 637 638 /* Insert the name into the namespace */ 639 640 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 641 ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE, 642 WalkState, &Node); 643 644 Op->Common.Node = Node; 645 646 if (ACPI_SUCCESS (Status)) 647 { 648 /* Check if it's a predefined node */ 649 650 while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name) 651 { 652 if (!ACPI_STRNCMP (Node->Name.Ascii, 653 AcpiGbl_PreDefinedNames[PreDefineIndex].Name, 4)) 654 { 655 PreDefined = TRUE; 656 break; 657 } 658 659 PreDefineIndex++; 660 } 661 662 /* 663 * Set node owner id if it satisfies all the following conditions: 664 * 1) Not a predefined node, _SB_ etc 665 * 2) Not the root node 666 * 3) Not a node created by Scope 667 */ 668 669 if (!PreDefined && Node != AcpiGbl_RootNode && 670 Op->Common.AmlOpcode != AML_SCOPE_OP) 671 { 672 Node->OwnerId = WalkState->OwnerId; 673 } 674 } 675 676 677 Exit: 678 679 if (AcpiNsOpensScope (ObjectType)) 680 { 681 if (Op->Common.Node) 682 { 683 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 684 if (ACPI_FAILURE (Status)) 685 { 686 return (Status); 687 } 688 } 689 } 690 691 return (AE_OK); 692 } 693 694 695 /******************************************************************************* 696 * 697 * FUNCTION: AcpiDmXrefDescendingOp 698 * 699 * PARAMETERS: ASL_WALK_CALLBACK 700 * 701 * RETURN: Status 702 * 703 * DESCRIPTION: Descending handler for namespace cross reference 704 * 705 ******************************************************************************/ 706 707 static ACPI_STATUS 708 AcpiDmXrefDescendingOp ( 709 ACPI_PARSE_OBJECT *Op, 710 UINT32 Level, 711 void *Context) 712 { 713 ACPI_OP_WALK_INFO *Info = Context; 714 const ACPI_OPCODE_INFO *OpInfo; 715 ACPI_WALK_STATE *WalkState; 716 ACPI_OBJECT_TYPE ObjectType; 717 ACPI_OBJECT_TYPE ObjectType2; 718 ACPI_STATUS Status; 719 char *Path = NULL; 720 ACPI_PARSE_OBJECT *NextOp; 721 ACPI_NAMESPACE_NODE *Node; 722 ACPI_OPERAND_OBJECT *Object; 723 UINT32 ParamCount = 0; 724 725 726 WalkState = Info->WalkState; 727 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 728 ObjectType = OpInfo->ObjectType; 729 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 730 731 if ((!(OpInfo->Flags & AML_NAMED)) && 732 (!(OpInfo->Flags & AML_CREATE)) && 733 (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) 734 { 735 goto Exit; 736 } 737 738 /* Get the NamePath from the appropriate place */ 739 740 if (OpInfo->Flags & AML_NAMED) 741 { 742 if ((Op->Common.AmlOpcode == AML_ALIAS_OP) || 743 (Op->Common.AmlOpcode == AML_SCOPE_OP)) 744 { 745 /* 746 * Only these two operators refer to an existing name, 747 * first argument 748 */ 749 Path = (char *) Op->Named.Path; 750 } 751 } 752 else if (OpInfo->Flags & AML_CREATE) 753 { 754 /* Referenced Buffer Name is the first child */ 755 756 NextOp = Op->Common.Value.Arg; 757 if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 758 { 759 Path = NextOp->Common.Value.String; 760 } 761 } 762 else 763 { 764 Path = Op->Common.Value.String; 765 } 766 767 if (!Path) 768 { 769 goto Exit; 770 } 771 772 /* 773 * Lookup the name in the namespace. Name must exist at this point, or it 774 * is an invalid reference. 775 * 776 * The namespace is also used as a lookup table for references to resource 777 * descriptors and the fields within them. 778 */ 779 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 780 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 781 WalkState, &Node); 782 if (ACPI_FAILURE (Status)) 783 { 784 if (Status == AE_NOT_FOUND) 785 { 786 AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType, 0); 787 788 /* 789 * We could install this into the namespace, but we catch duplicate 790 * externals when they are added to the list. 791 */ 792 #if 0 793 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 794 ACPI_IMODE_LOAD_PASS1, ACPI_NS_DONT_OPEN_SCOPE, 795 WalkState, &Node); 796 #endif 797 } 798 } 799 800 /* 801 * Found the node in external table, add it to external list 802 * Node->OwnerId == 0 indicates built-in ACPI Names, _OS_ etc 803 */ 804 else if (Node->OwnerId && WalkState->OwnerId != Node->OwnerId) 805 { 806 ObjectType2 = ObjectType; 807 808 Object = AcpiNsGetAttachedObject (Node); 809 if (Object) 810 { 811 ObjectType2 = Object->Common.Type; 812 if (ObjectType2 == ACPI_TYPE_METHOD) 813 { 814 ParamCount = Object->Method.ParamCount; 815 } 816 } 817 818 AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType2, ParamCount); 819 Op->Common.Node = Node; 820 } 821 else 822 { 823 Op->Common.Node = Node; 824 } 825 826 827 Exit: 828 /* Open new scope if necessary */ 829 830 if (AcpiNsOpensScope (ObjectType)) 831 { 832 if (Op->Common.Node) 833 { 834 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 835 if (ACPI_FAILURE (Status)) 836 { 837 return (Status); 838 } 839 } 840 } 841 842 return (AE_OK); 843 } 844 845 846 /******************************************************************************* 847 * 848 * FUNCTION: AcpiDmResourceDescendingOp 849 * 850 * PARAMETERS: ASL_WALK_CALLBACK 851 * 852 * RETURN: None 853 * 854 * DESCRIPTION: Process one parse op during symbolic resource index conversion. 855 * 856 ******************************************************************************/ 857 858 static ACPI_STATUS 859 AcpiDmResourceDescendingOp ( 860 ACPI_PARSE_OBJECT *Op, 861 UINT32 Level, 862 void *Context) 863 { 864 ACPI_OP_WALK_INFO *Info = Context; 865 const ACPI_OPCODE_INFO *OpInfo; 866 ACPI_WALK_STATE *WalkState; 867 ACPI_OBJECT_TYPE ObjectType; 868 ACPI_STATUS Status; 869 870 871 WalkState = Info->WalkState; 872 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 873 874 /* Open new scope if necessary */ 875 876 ObjectType = OpInfo->ObjectType; 877 if (AcpiNsOpensScope (ObjectType)) 878 { 879 if (Op->Common.Node) 880 { 881 882 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 883 if (ACPI_FAILURE (Status)) 884 { 885 return (Status); 886 } 887 } 888 } 889 890 /* 891 * Check if this operator contains a reference to a resource descriptor. 892 * If so, convert the reference into a symbolic reference. 893 */ 894 AcpiDmCheckResourceReference (Op, WalkState); 895 return (AE_OK); 896 } 897 898 899 /******************************************************************************* 900 * 901 * FUNCTION: AcpiDmCommonAscendingOp 902 * 903 * PARAMETERS: ASL_WALK_CALLBACK 904 * 905 * RETURN: None 906 * 907 * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes 908 * scope if necessary. 909 * 910 ******************************************************************************/ 911 912 static ACPI_STATUS 913 AcpiDmCommonAscendingOp ( 914 ACPI_PARSE_OBJECT *Op, 915 UINT32 Level, 916 void *Context) 917 { 918 ACPI_OP_WALK_INFO *Info = Context; 919 const ACPI_OPCODE_INFO *OpInfo; 920 ACPI_OBJECT_TYPE ObjectType; 921 922 923 /* Close scope if necessary */ 924 925 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 926 ObjectType = OpInfo->ObjectType; 927 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 928 929 if (AcpiNsOpensScope (ObjectType)) 930 { 931 (void) AcpiDsScopeStackPop (Info->WalkState); 932 } 933 934 return (AE_OK); 935 } 936 937 938 /******************************************************************************* 939 * 940 * FUNCTION: AcpiDmInspectPossibleArgs 941 * 942 * PARAMETERS: CurrentOpArgCount - Which arg of the current op was the 943 * possible method invocation found 944 * TargetCount - Number of targets (0,1,2) for this op 945 * Op - Parse op 946 * 947 * RETURN: Status 948 * 949 * DESCRIPTION: Examine following args and next ops for possible arguments 950 * for an unrecognized method invocation. 951 * 952 ******************************************************************************/ 953 954 static UINT32 955 AcpiDmInspectPossibleArgs ( 956 UINT32 CurrentOpArgCount, 957 UINT32 TargetCount, 958 ACPI_PARSE_OBJECT *Op) 959 { 960 const ACPI_OPCODE_INFO *OpInfo; 961 UINT32 i; 962 UINT32 Last = 0; 963 UINT32 Lookahead; 964 965 966 Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount; 967 968 /* Lookahead for the maximum number of possible arguments */ 969 970 for (i = 0; i < Lookahead; i++) 971 { 972 if (!Op) 973 { 974 break; 975 } 976 977 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 978 979 /* 980 * Any one of these operators is "very probably" not a method arg 981 */ 982 if ((Op->Common.AmlOpcode == AML_STORE_OP) || 983 (Op->Common.AmlOpcode == AML_NOTIFY_OP)) 984 { 985 break; 986 } 987 988 if ((OpInfo->Class != AML_CLASS_EXECUTE) && 989 (OpInfo->Class != AML_CLASS_CONTROL)) 990 { 991 Last = i+1; 992 } 993 994 Op = Op->Common.Next; 995 } 996 997 return (Last); 998 } 999 1000 1001