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