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