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