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