1 /****************************************************************************** 2 * 3 * Module Name: adwalk - Application-level disassembler parse tree walk routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, 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 "acpi.h" 46 #include "accommon.h" 47 #include "acparser.h" 48 #include "amlcode.h" 49 #include "acdisasm.h" 50 #include "acdispat.h" 51 #include "acnamesp.h" 52 #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 377 AcpiOsPrintf ("%2.2X", (UINT32) Op->Common.Value.Integer); 378 break; 379 380 case AML_WORD_OP: 381 382 AcpiOsPrintf ("%4.4X", (UINT32) Op->Common.Value.Integer); 383 break; 384 385 case AML_DWORD_OP: 386 387 AcpiOsPrintf ("%8.8X", (UINT32) Op->Common.Value.Integer); 388 break; 389 390 case AML_QWORD_OP: 391 392 AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer)); 393 break; 394 395 case AML_INT_NAMEPATH_OP: 396 397 if (Op->Common.Value.String) 398 { 399 AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String, 400 NULL, &Path); 401 AcpiOsPrintf ("%s %p", Path, Op->Common.Node); 402 ACPI_FREE (Path); 403 } 404 else 405 { 406 AcpiOsPrintf ("[NULL]"); 407 } 408 break; 409 410 case AML_NAME_OP: 411 case AML_METHOD_OP: 412 case AML_DEVICE_OP: 413 case AML_INT_NAMEDFIELD_OP: 414 415 AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name)); 416 break; 417 418 default: 419 420 break; 421 } 422 423 AcpiOsPrintf ("\n"); 424 return (AE_OK); 425 } 426 427 428 /******************************************************************************* 429 * 430 * FUNCTION: AcpiDmFindOrphanDescending 431 * 432 * PARAMETERS: ASL_WALK_CALLBACK 433 * 434 * RETURN: Status 435 * 436 * DESCRIPTION: Check namepath Ops for orphaned method invocations 437 * 438 * Note: Experimental. 439 * 440 ******************************************************************************/ 441 442 static ACPI_STATUS 443 AcpiDmFindOrphanDescending ( 444 ACPI_PARSE_OBJECT *Op, 445 UINT32 Level, 446 void *Context) 447 { 448 const ACPI_OPCODE_INFO *OpInfo; 449 ACPI_PARSE_OBJECT *ChildOp; 450 ACPI_PARSE_OBJECT *NextOp; 451 ACPI_PARSE_OBJECT *ParentOp; 452 UINT32 ArgCount; 453 454 455 if (!Op) 456 { 457 return (AE_OK); 458 } 459 460 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 461 462 switch (Op->Common.AmlOpcode) 463 { 464 #ifdef ACPI_UNDER_DEVELOPMENT 465 case AML_ADD_OP: 466 467 ChildOp = Op->Common.Value.Arg; 468 if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 469 !ChildOp->Common.Node) 470 { 471 AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String, 472 NULL, &Path); 473 AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s */\n", 474 Op->Common.AmlOpName, Path); 475 ACPI_FREE (Path); 476 477 NextOp = Op->Common.Next; 478 if (!NextOp) 479 { 480 /* This NamePath has no args, assume it is an integer */ 481 482 AcpiDmAddOpToExternalList (ChildOp, 483 ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0); 484 return (AE_OK); 485 } 486 487 ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp); 488 AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n", 489 ArgCount, AcpiDmCountChildren (Op)); 490 491 if (ArgCount < 1) 492 { 493 /* One Arg means this is just a Store(Name,Target) */ 494 495 AcpiDmAddOpToExternalList (ChildOp, 496 ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0); 497 return (AE_OK); 498 } 499 500 AcpiDmAddOpToExternalList (ChildOp, 501 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0); 502 } 503 break; 504 #endif 505 506 case AML_STORE_OP: 507 508 ChildOp = Op->Common.Value.Arg; 509 if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 510 !ChildOp->Common.Node) 511 { 512 NextOp = Op->Common.Next; 513 if (!NextOp) 514 { 515 /* This NamePath has no args, assume it is an integer */ 516 517 AcpiDmAddOpToExternalList (ChildOp, 518 ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0); 519 return (AE_OK); 520 } 521 522 ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp); 523 if (ArgCount <= 1) 524 { 525 /* One Arg means this is just a Store(Name,Target) */ 526 527 AcpiDmAddOpToExternalList (ChildOp, 528 ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0); 529 return (AE_OK); 530 } 531 532 AcpiDmAddOpToExternalList (ChildOp, 533 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0); 534 } 535 break; 536 537 case AML_INT_NAMEPATH_OP: 538 539 /* Must examine parent to see if this namepath is an argument */ 540 541 ParentOp = Op->Common.Parent; 542 OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); 543 544 if ((OpInfo->Class != AML_CLASS_EXECUTE) && 545 (OpInfo->Class != AML_CLASS_CREATE) && 546 (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) && 547 (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && 548 !Op->Common.Node) 549 { 550 ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next); 551 552 /* 553 * Check if namepath is a predicate for if/while or lone parameter to 554 * a return. 555 */ 556 if (ArgCount == 0) 557 { 558 if (((ParentOp->Common.AmlOpcode == AML_IF_OP) || 559 (ParentOp->Common.AmlOpcode == AML_WHILE_OP) || 560 (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) && 561 562 /* And namepath is the first argument */ 563 (ParentOp->Common.Value.Arg == Op)) 564 { 565 AcpiDmAddOpToExternalList (Op, 566 Op->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0); 567 break; 568 } 569 } 570 571 /* 572 * This is a standalone namestring (not a parameter to another 573 * operator) - it *must* be a method invocation, nothing else is 574 * grammatically possible. 575 */ 576 AcpiDmAddOpToExternalList (Op, 577 Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0); 578 } 579 break; 580 581 default: 582 583 break; 584 } 585 586 return (AE_OK); 587 } 588 589 590 /******************************************************************************* 591 * 592 * FUNCTION: AcpiDmLoadDescendingOp 593 * 594 * PARAMETERS: ASL_WALK_CALLBACK 595 * 596 * RETURN: Status 597 * 598 * DESCRIPTION: Descending handler for namespace control method object load 599 * 600 ******************************************************************************/ 601 602 static ACPI_STATUS 603 AcpiDmLoadDescendingOp ( 604 ACPI_PARSE_OBJECT *Op, 605 UINT32 Level, 606 void *Context) 607 { 608 ACPI_OP_WALK_INFO *Info = Context; 609 const ACPI_OPCODE_INFO *OpInfo; 610 ACPI_WALK_STATE *WalkState; 611 ACPI_OBJECT_TYPE ObjectType; 612 ACPI_STATUS Status; 613 char *Path = NULL; 614 ACPI_PARSE_OBJECT *NextOp; 615 ACPI_NAMESPACE_NODE *Node; 616 char FieldPath[5]; 617 BOOLEAN PreDefined = FALSE; 618 UINT8 PreDefineIndex = 0; 619 620 621 WalkState = Info->WalkState; 622 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 623 ObjectType = OpInfo->ObjectType; 624 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 625 626 /* Only interested in operators that create new names */ 627 628 if (!(OpInfo->Flags & AML_NAMED) && 629 !(OpInfo->Flags & AML_CREATE)) 630 { 631 goto Exit; 632 } 633 634 /* Get the NamePath from the appropriate place */ 635 636 if (OpInfo->Flags & AML_NAMED) 637 { 638 /* For all named operators, get the new name */ 639 640 Path = (char *) Op->Named.Path; 641 642 if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) 643 { 644 *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name; 645 FieldPath[4] = 0; 646 Path = FieldPath; 647 } 648 } 649 else if (OpInfo->Flags & AML_CREATE) 650 { 651 /* New name is the last child */ 652 653 NextOp = Op->Common.Value.Arg; 654 655 while (NextOp->Common.Next) 656 { 657 NextOp = NextOp->Common.Next; 658 } 659 Path = NextOp->Common.Value.String; 660 } 661 662 if (!Path) 663 { 664 goto Exit; 665 } 666 667 /* Insert the name into the namespace */ 668 669 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 670 ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE, 671 WalkState, &Node); 672 673 Op->Common.Node = Node; 674 675 if (ACPI_SUCCESS (Status)) 676 { 677 /* Check if it's a predefined node */ 678 679 while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name) 680 { 681 if (ACPI_COMPARE_NAME (Node->Name.Ascii, 682 AcpiGbl_PreDefinedNames[PreDefineIndex].Name)) 683 { 684 PreDefined = TRUE; 685 break; 686 } 687 688 PreDefineIndex++; 689 } 690 691 /* 692 * Set node owner id if it satisfies all the following conditions: 693 * 1) Not a predefined node, _SB_ etc 694 * 2) Not the root node 695 * 3) Not a node created by Scope 696 */ 697 698 if (!PreDefined && Node != AcpiGbl_RootNode && 699 Op->Common.AmlOpcode != AML_SCOPE_OP) 700 { 701 Node->OwnerId = WalkState->OwnerId; 702 } 703 } 704 705 706 Exit: 707 708 if (AcpiNsOpensScope (ObjectType)) 709 { 710 if (Op->Common.Node) 711 { 712 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 713 if (ACPI_FAILURE (Status)) 714 { 715 return (Status); 716 } 717 } 718 } 719 720 return (AE_OK); 721 } 722 723 724 /******************************************************************************* 725 * 726 * FUNCTION: AcpiDmXrefDescendingOp 727 * 728 * PARAMETERS: ASL_WALK_CALLBACK 729 * 730 * RETURN: Status 731 * 732 * DESCRIPTION: Descending handler for namespace cross reference 733 * 734 ******************************************************************************/ 735 736 static ACPI_STATUS 737 AcpiDmXrefDescendingOp ( 738 ACPI_PARSE_OBJECT *Op, 739 UINT32 Level, 740 void *Context) 741 { 742 ACPI_OP_WALK_INFO *Info = Context; 743 const ACPI_OPCODE_INFO *OpInfo; 744 ACPI_WALK_STATE *WalkState; 745 ACPI_OBJECT_TYPE ObjectType; 746 ACPI_OBJECT_TYPE ObjectType2; 747 ACPI_STATUS Status; 748 char *Path = NULL; 749 ACPI_PARSE_OBJECT *NextOp; 750 ACPI_NAMESPACE_NODE *Node; 751 ACPI_OPERAND_OBJECT *Object; 752 UINT32 ParamCount = 0; 753 char *Pathname; 754 755 756 WalkState = Info->WalkState; 757 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 758 ObjectType = OpInfo->ObjectType; 759 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 760 761 if ((!(OpInfo->Flags & AML_NAMED)) && 762 (!(OpInfo->Flags & AML_CREATE)) && 763 (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) 764 { 765 goto Exit; 766 } 767 768 /* Get the NamePath from the appropriate place */ 769 770 if (OpInfo->Flags & AML_NAMED) 771 { 772 /* 773 * Only these two operators (Alias, Scope) refer to an existing 774 * name, it is the first argument 775 */ 776 if (Op->Common.AmlOpcode == AML_ALIAS_OP) 777 { 778 ObjectType = ACPI_TYPE_ANY; 779 780 NextOp = Op->Common.Value.Arg; 781 NextOp = NextOp->Common.Value.Arg; 782 if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 783 { 784 Path = NextOp->Common.Value.String; 785 } 786 } 787 else if (Op->Common.AmlOpcode == AML_SCOPE_OP) 788 { 789 Path = (char *) Op->Named.Path; 790 } 791 } 792 else if (OpInfo->Flags & AML_CREATE) 793 { 794 /* Referenced Buffer Name is the first child */ 795 796 ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */ 797 798 NextOp = Op->Common.Value.Arg; 799 if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 800 { 801 Path = NextOp->Common.Value.String; 802 } 803 } 804 else 805 { 806 Path = Op->Common.Value.String; 807 } 808 809 if (!Path) 810 { 811 goto Exit; 812 } 813 814 /* 815 * Lookup the name in the namespace. Name must exist at this point, or it 816 * is an invalid reference. 817 * 818 * The namespace is also used as a lookup table for references to resource 819 * descriptors and the fields within them. 820 */ 821 Node = NULL; 822 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 823 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 824 WalkState, &Node); 825 if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL)) 826 { 827 /* Node was created by an External() statement */ 828 829 Status = AE_NOT_FOUND; 830 } 831 832 if (ACPI_FAILURE (Status)) 833 { 834 if (Status == AE_NOT_FOUND) 835 { 836 /* 837 * Add this symbol as an external declaration, except if the 838 * parent is a CondRefOf operator. For this operator, we do not 839 * need an external, nor do we want one, since this can cause 840 * disassembly problems if the symbol is actually a control 841 * method. 842 */ 843 if (!(Op->Asl.Parent && 844 (Op->Asl.Parent->Asl.AmlOpcode == AML_COND_REF_OF_OP))) 845 { 846 if (Node) 847 { 848 AcpiDmAddNodeToExternalList (Node, 849 (UINT8) ObjectType, 0, 0); 850 } 851 else 852 { 853 AcpiDmAddOpToExternalList (Op, Path, 854 (UINT8) ObjectType, 0, 0); 855 } 856 } 857 } 858 } 859 860 /* 861 * Found the node, but check if it came from an external table. 862 * Add it to external list. Note: Node->OwnerId == 0 indicates 863 * one of the built-in ACPI Names (_OS_ etc.) which can safely 864 * be ignored. 865 */ 866 else if (Node->OwnerId && 867 (WalkState->OwnerId != Node->OwnerId)) 868 { 869 ObjectType2 = ObjectType; 870 871 Object = AcpiNsGetAttachedObject (Node); 872 if (Object) 873 { 874 ObjectType2 = Object->Common.Type; 875 if (ObjectType2 == ACPI_TYPE_METHOD) 876 { 877 ParamCount = Object->Method.ParamCount; 878 } 879 } 880 881 Pathname = AcpiNsGetExternalPathname (Node); 882 if (!Pathname) 883 { 884 return (AE_NO_MEMORY); 885 } 886 887 AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2, 888 ParamCount, ACPI_EXT_RESOLVED_REFERENCE); 889 890 ACPI_FREE (Pathname); 891 Op->Common.Node = Node; 892 } 893 else 894 { 895 Op->Common.Node = Node; 896 } 897 898 899 Exit: 900 /* Open new scope if necessary */ 901 902 if (AcpiNsOpensScope (ObjectType)) 903 { 904 if (Op->Common.Node) 905 { 906 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 907 if (ACPI_FAILURE (Status)) 908 { 909 return (Status); 910 } 911 } 912 } 913 914 return (AE_OK); 915 } 916 917 918 /******************************************************************************* 919 * 920 * FUNCTION: AcpiDmResourceDescendingOp 921 * 922 * PARAMETERS: ASL_WALK_CALLBACK 923 * 924 * RETURN: None 925 * 926 * DESCRIPTION: Process one parse op during symbolic resource index conversion. 927 * 928 ******************************************************************************/ 929 930 static ACPI_STATUS 931 AcpiDmResourceDescendingOp ( 932 ACPI_PARSE_OBJECT *Op, 933 UINT32 Level, 934 void *Context) 935 { 936 ACPI_OP_WALK_INFO *Info = Context; 937 const ACPI_OPCODE_INFO *OpInfo; 938 ACPI_WALK_STATE *WalkState; 939 ACPI_OBJECT_TYPE ObjectType; 940 ACPI_STATUS Status; 941 942 943 WalkState = Info->WalkState; 944 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 945 946 /* Open new scope if necessary */ 947 948 ObjectType = OpInfo->ObjectType; 949 if (AcpiNsOpensScope (ObjectType)) 950 { 951 if (Op->Common.Node) 952 { 953 954 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 955 if (ACPI_FAILURE (Status)) 956 { 957 return (Status); 958 } 959 } 960 } 961 962 /* 963 * Check if this operator contains a reference to a resource descriptor. 964 * If so, convert the reference into a symbolic reference. 965 */ 966 AcpiDmCheckResourceReference (Op, WalkState); 967 return (AE_OK); 968 } 969 970 971 /******************************************************************************* 972 * 973 * FUNCTION: AcpiDmCommonAscendingOp 974 * 975 * PARAMETERS: ASL_WALK_CALLBACK 976 * 977 * RETURN: None 978 * 979 * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes 980 * scope if necessary. 981 * 982 ******************************************************************************/ 983 984 static ACPI_STATUS 985 AcpiDmCommonAscendingOp ( 986 ACPI_PARSE_OBJECT *Op, 987 UINT32 Level, 988 void *Context) 989 { 990 ACPI_OP_WALK_INFO *Info = Context; 991 const ACPI_OPCODE_INFO *OpInfo; 992 ACPI_OBJECT_TYPE ObjectType; 993 994 995 /* Close scope if necessary */ 996 997 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 998 ObjectType = OpInfo->ObjectType; 999 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 1000 1001 if (AcpiNsOpensScope (ObjectType)) 1002 { 1003 (void) AcpiDsScopeStackPop (Info->WalkState); 1004 } 1005 1006 return (AE_OK); 1007 } 1008 1009 1010 /******************************************************************************* 1011 * 1012 * FUNCTION: AcpiDmInspectPossibleArgs 1013 * 1014 * PARAMETERS: CurrentOpArgCount - Which arg of the current op was the 1015 * possible method invocation found 1016 * TargetCount - Number of targets (0,1,2) for this op 1017 * Op - Parse op 1018 * 1019 * RETURN: Status 1020 * 1021 * DESCRIPTION: Examine following args and next ops for possible arguments 1022 * for an unrecognized method invocation. 1023 * 1024 ******************************************************************************/ 1025 1026 static UINT32 1027 AcpiDmInspectPossibleArgs ( 1028 UINT32 CurrentOpArgCount, 1029 UINT32 TargetCount, 1030 ACPI_PARSE_OBJECT *Op) 1031 { 1032 const ACPI_OPCODE_INFO *OpInfo; 1033 UINT32 i; 1034 UINT32 Last = 0; 1035 UINT32 Lookahead; 1036 1037 1038 Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount; 1039 1040 /* Lookahead for the maximum number of possible arguments */ 1041 1042 for (i = 0; i < Lookahead; i++) 1043 { 1044 if (!Op) 1045 { 1046 break; 1047 } 1048 1049 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 1050 1051 /* 1052 * Any one of these operators is "very probably" not a method arg 1053 */ 1054 if ((Op->Common.AmlOpcode == AML_STORE_OP) || 1055 (Op->Common.AmlOpcode == AML_NOTIFY_OP)) 1056 { 1057 break; 1058 } 1059 1060 if ((OpInfo->Class != AML_CLASS_EXECUTE) && 1061 (OpInfo->Class != AML_CLASS_CONTROL)) 1062 { 1063 Last = i+1; 1064 } 1065 1066 Op = Op->Common.Next; 1067 } 1068 1069 return (Last); 1070 }