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