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