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