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