1 /****************************************************************************** 2 * 3 * Module Name: adwalk - Application-level disassembler parse tree walk routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 UINT16 Flags = 0; 764 765 766 WalkState = Info->WalkState; 767 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 768 ObjectType = OpInfo->ObjectType; 769 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 770 771 if ((!(OpInfo->Flags & AML_NAMED)) && 772 (!(OpInfo->Flags & AML_CREATE)) && 773 (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP) && 774 (Op->Common.AmlOpcode != AML_NOTIFY_OP)) 775 { 776 goto Exit; 777 } 778 else if (Op->Common.Parent && 779 Op->Common.Parent->Common.AmlOpcode == AML_EXTERNAL_OP) 780 { 781 /* External() NamePath */ 782 783 Path = Op->Common.Value.String; 784 ObjectType = (ACPI_OBJECT_TYPE) Op->Common.Next->Common.Value.Integer; 785 if (ObjectType == ACPI_TYPE_METHOD) 786 { 787 ParamCount = (UINT32) 788 Op->Common.Next->Common.Next->Common.Value.Integer; 789 } 790 791 AcpiDmAddOpToExternalList (Op, Path, 792 (UINT8) ObjectType, ParamCount, Flags); 793 794 goto Exit; 795 } 796 797 /* Get the NamePath from the appropriate place */ 798 799 if (OpInfo->Flags & AML_NAMED) 800 { 801 /* 802 * Only these two operators (Alias, Scope) refer to an existing 803 * name, it is the first argument 804 */ 805 if (Op->Common.AmlOpcode == AML_ALIAS_OP) 806 { 807 ObjectType = ACPI_TYPE_ANY; 808 809 NextOp = Op->Common.Value.Arg; 810 NextOp = NextOp->Common.Value.Arg; 811 if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 812 { 813 Path = NextOp->Common.Value.String; 814 } 815 } 816 else if (Op->Common.AmlOpcode == AML_SCOPE_OP) 817 { 818 Path = (char *) Op->Named.Path; 819 } 820 } 821 else if (OpInfo->Flags & AML_CREATE) 822 { 823 /* Referenced Buffer Name is the first child */ 824 825 ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */ 826 827 NextOp = Op->Common.Value.Arg; 828 if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 829 { 830 Path = NextOp->Common.Value.String; 831 } 832 } 833 else if (Op->Common.AmlOpcode == AML_NOTIFY_OP) 834 { 835 Path = Op->Common.Value.Arg->Asl.Value.String; 836 } 837 else 838 { 839 Path = Op->Common.Value.String; 840 } 841 842 if (!Path) 843 { 844 goto Exit; 845 } 846 847 /* 848 * Lookup the name in the namespace. Name must exist at this point, or it 849 * is an invalid reference. 850 * 851 * The namespace is also used as a lookup table for references to resource 852 * descriptors and the fields within them. 853 */ 854 Node = NULL; 855 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 856 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 857 WalkState, &Node); 858 if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL)) 859 { 860 /* Node was created by an External() statement */ 861 862 Status = AE_NOT_FOUND; 863 Flags = ACPI_EXT_RESOLVED_REFERENCE; 864 } 865 866 if (ACPI_FAILURE (Status)) 867 { 868 if (Status == AE_NOT_FOUND) 869 { 870 /* 871 * Add this symbol as an external declaration, except if the 872 * parent is a CondRefOf operator. For this operator, we do not 873 * need an external, nor do we want one, since this can cause 874 * disassembly problems if the symbol is actually a control 875 * method. 876 */ 877 if (!(Op->Asl.Parent && 878 (Op->Asl.Parent->Asl.AmlOpcode == AML_COND_REF_OF_OP))) 879 { 880 if (Node) 881 { 882 AcpiDmAddNodeToExternalList (Node, 883 (UINT8) ObjectType, 0, Flags); 884 } 885 else 886 { 887 AcpiDmAddOpToExternalList (Op, Path, 888 (UINT8) ObjectType, 0, Flags); 889 } 890 } 891 } 892 } 893 894 /* 895 * Found the node, but check if it came from an external table. 896 * Add it to external list. Note: Node->OwnerId == 0 indicates 897 * one of the built-in ACPI Names (_OS_ etc.) which can safely 898 * be ignored. 899 */ 900 else if (Node->OwnerId && 901 (WalkState->OwnerId != Node->OwnerId)) 902 { 903 ObjectType2 = ObjectType; 904 905 Object = AcpiNsGetAttachedObject (Node); 906 if (Object) 907 { 908 ObjectType2 = Object->Common.Type; 909 if (ObjectType2 == ACPI_TYPE_METHOD) 910 { 911 ParamCount = Object->Method.ParamCount; 912 } 913 } 914 915 Pathname = AcpiNsGetExternalPathname (Node); 916 if (!Pathname) 917 { 918 return (AE_NO_MEMORY); 919 } 920 921 AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2, 922 ParamCount, ACPI_EXT_RESOLVED_REFERENCE); 923 924 ACPI_FREE (Pathname); 925 Op->Common.Node = Node; 926 } 927 else 928 { 929 Op->Common.Node = Node; 930 } 931 932 933 Exit: 934 /* Open new scope if necessary */ 935 936 if (AcpiNsOpensScope (ObjectType)) 937 { 938 if (Op->Common.Node) 939 { 940 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, 941 WalkState); 942 if (ACPI_FAILURE (Status)) 943 { 944 return (Status); 945 } 946 } 947 } 948 949 return (AE_OK); 950 } 951 952 953 /******************************************************************************* 954 * 955 * FUNCTION: AcpiDmResourceDescendingOp 956 * 957 * PARAMETERS: ASL_WALK_CALLBACK 958 * 959 * RETURN: None 960 * 961 * DESCRIPTION: Process one parse op during symbolic resource index conversion. 962 * 963 ******************************************************************************/ 964 965 static ACPI_STATUS 966 AcpiDmResourceDescendingOp ( 967 ACPI_PARSE_OBJECT *Op, 968 UINT32 Level, 969 void *Context) 970 { 971 ACPI_OP_WALK_INFO *Info = Context; 972 const ACPI_OPCODE_INFO *OpInfo; 973 ACPI_WALK_STATE *WalkState; 974 ACPI_OBJECT_TYPE ObjectType; 975 ACPI_STATUS Status; 976 977 978 WalkState = Info->WalkState; 979 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 980 981 /* Open new scope if necessary */ 982 983 ObjectType = OpInfo->ObjectType; 984 if (AcpiNsOpensScope (ObjectType)) 985 { 986 if (Op->Common.Node) 987 { 988 989 Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, 990 WalkState); 991 if (ACPI_FAILURE (Status)) 992 { 993 return (Status); 994 } 995 } 996 } 997 998 /* 999 * Check if this operator contains a reference to a resource descriptor. 1000 * If so, convert the reference into a symbolic reference. 1001 */ 1002 AcpiDmCheckResourceReference (Op, WalkState); 1003 return (AE_OK); 1004 } 1005 1006 1007 /******************************************************************************* 1008 * 1009 * FUNCTION: AcpiDmCommonAscendingOp 1010 * 1011 * PARAMETERS: ASL_WALK_CALLBACK 1012 * 1013 * RETURN: None 1014 * 1015 * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes 1016 * scope if necessary. 1017 * 1018 ******************************************************************************/ 1019 1020 static ACPI_STATUS 1021 AcpiDmCommonAscendingOp ( 1022 ACPI_PARSE_OBJECT *Op, 1023 UINT32 Level, 1024 void *Context) 1025 { 1026 ACPI_OP_WALK_INFO *Info = Context; 1027 const ACPI_OPCODE_INFO *OpInfo; 1028 ACPI_OBJECT_TYPE ObjectType; 1029 1030 1031 /* Close scope if necessary */ 1032 1033 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 1034 ObjectType = OpInfo->ObjectType; 1035 ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 1036 1037 if (AcpiNsOpensScope (ObjectType)) 1038 { 1039 (void) AcpiDsScopeStackPop (Info->WalkState); 1040 } 1041 1042 return (AE_OK); 1043 } 1044 1045 1046 /******************************************************************************* 1047 * 1048 * FUNCTION: AcpiDmInspectPossibleArgs 1049 * 1050 * PARAMETERS: CurrentOpArgCount - Which arg of the current op was the 1051 * possible method invocation found 1052 * TargetCount - Number of targets (0,1,2) for this op 1053 * Op - Parse op 1054 * 1055 * RETURN: Status 1056 * 1057 * DESCRIPTION: Examine following args and next ops for possible arguments 1058 * for an unrecognized method invocation. 1059 * 1060 ******************************************************************************/ 1061 1062 static UINT32 1063 AcpiDmInspectPossibleArgs ( 1064 UINT32 CurrentOpArgCount, 1065 UINT32 TargetCount, 1066 ACPI_PARSE_OBJECT *Op) 1067 { 1068 const ACPI_OPCODE_INFO *OpInfo; 1069 UINT32 i; 1070 UINT32 Last = 0; 1071 UINT32 Lookahead; 1072 1073 1074 Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount; 1075 1076 /* Lookahead for the maximum number of possible arguments */ 1077 1078 for (i = 0; i < Lookahead; i++) 1079 { 1080 if (!Op) 1081 { 1082 break; 1083 } 1084 1085 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 1086 1087 /* 1088 * Any one of these operators is "very probably" not a method arg 1089 */ 1090 if ((Op->Common.AmlOpcode == AML_STORE_OP) || 1091 (Op->Common.AmlOpcode == AML_NOTIFY_OP)) 1092 { 1093 break; 1094 } 1095 1096 if ((OpInfo->Class != AML_CLASS_EXECUTE) && 1097 (OpInfo->Class != AML_CLASS_CONTROL)) 1098 { 1099 Last = i+1; 1100 } 1101 1102 Op = Op->Common.Next; 1103 } 1104 1105 return (Last); 1106 } 1107