Home | History | Annotate | Line # | Download | only in common
adwalk.c revision 1.1.1.10
      1 /******************************************************************************
      2  *
      3  * Module Name: adwalk - Application-level disassembler parse tree walk routines
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, 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 "acpi.h"
     45 #include "accommon.h"
     46 #include "acparser.h"
     47 #include "amlcode.h"
     48 #include "acdisasm.h"
     49 #include "acdispat.h"
     50 #include "acnamesp.h"
     51 #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 AcpiDmCommonDescendingOp (
    104     ACPI_PARSE_OBJECT       *Op,
    105     UINT32                  Level,
    106     void                    *Context);
    107 
    108 static ACPI_STATUS
    109 AcpiDmProcessResourceDescriptors (
    110     ACPI_PARSE_OBJECT       *Op,
    111     UINT32                  Level,
    112     void                    *Context);
    113 
    114 /*******************************************************************************
    115  *
    116  * FUNCTION:    AcpiDmDumpTree
    117  *
    118  * PARAMETERS:  Origin              - Starting object
    119  *
    120  * RETURN:      None
    121  *
    122  * DESCRIPTION: Parse tree walk to format and output the nodes
    123  *
    124  ******************************************************************************/
    125 
    126 void
    127 AcpiDmDumpTree (
    128     ACPI_PARSE_OBJECT       *Origin)
    129 {
    130     ACPI_OP_WALK_INFO       Info;
    131 
    132 
    133     if (!Origin)
    134     {
    135         return;
    136     }
    137 
    138     AcpiOsPrintf ("/*\nAML Parse Tree\n\n");
    139     Info.Flags = 0;
    140     Info.Count = 0;
    141     Info.Level = 0;
    142     Info.WalkState = NULL;
    143 
    144     AcpiDmWalkParseTree (Origin, AcpiDmDumpDescending, NULL, &Info);
    145     AcpiOsPrintf ("*/\n\n");
    146 }
    147 
    148 
    149 /*******************************************************************************
    150  *
    151  * FUNCTION:    AcpiDmFindOrphanMethods
    152  *
    153  * PARAMETERS:  Origin              - Starting object
    154  *
    155  * RETURN:      None
    156  *
    157  * DESCRIPTION: Parse tree walk to find "orphaned" method invocations -- methods
    158  *              that are not resolved in the namespace
    159  *
    160  ******************************************************************************/
    161 
    162 void
    163 AcpiDmFindOrphanMethods (
    164     ACPI_PARSE_OBJECT       *Origin)
    165 {
    166     ACPI_OP_WALK_INFO       Info;
    167 
    168 
    169     if (!Origin)
    170     {
    171         return;
    172     }
    173 
    174     Info.Flags = 0;
    175     Info.Level = 0;
    176     Info.WalkState = NULL;
    177 
    178     AcpiDmWalkParseTree (Origin, AcpiDmFindOrphanDescending, NULL, &Info);
    179 }
    180 
    181 
    182 /*******************************************************************************
    183  *
    184  * FUNCTION:    AcpiDmFinishNamespaceLoad
    185  *
    186  * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
    187  *              NamespaceRoot       - Root of the internal namespace
    188  *              OwnerId             - OwnerId of the table to be disassembled
    189  *
    190  * RETURN:      None
    191  *
    192  * DESCRIPTION: Load all namespace items that are created within control
    193  *              methods. Used before namespace cross reference
    194  *
    195  ******************************************************************************/
    196 
    197 void
    198 AcpiDmFinishNamespaceLoad (
    199     ACPI_PARSE_OBJECT       *ParseTreeRoot,
    200     ACPI_NAMESPACE_NODE     *NamespaceRoot,
    201     ACPI_OWNER_ID           OwnerId)
    202 {
    203     ACPI_STATUS             Status;
    204     ACPI_OP_WALK_INFO       Info;
    205     ACPI_WALK_STATE         *WalkState;
    206 
    207 
    208     if (!ParseTreeRoot)
    209     {
    210         return;
    211     }
    212 
    213     /* Create and initialize a new walk state */
    214 
    215     WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL);
    216     if (!WalkState)
    217     {
    218         return;
    219     }
    220 
    221     Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type,
    222         WalkState);
    223     if (ACPI_FAILURE (Status))
    224     {
    225         return;
    226     }
    227 
    228     Info.Flags = 0;
    229     Info.Level = 0;
    230     Info.WalkState = WalkState;
    231 
    232     AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmLoadDescendingOp,
    233         AcpiDmCommonAscendingOp, &Info);
    234     ACPI_FREE (WalkState);
    235 }
    236 
    237 
    238 /*******************************************************************************
    239  *
    240  * FUNCTION:    AcpiDmCrossReferenceNamespace
    241  *
    242  * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
    243  *              NamespaceRoot       - Root of the internal namespace
    244  *              OwnerId             - OwnerId of the table to be disassembled
    245  *
    246  * RETURN:      None
    247  *
    248  * DESCRIPTION: Cross reference the namespace to create externals
    249  *
    250  ******************************************************************************/
    251 
    252 void
    253 AcpiDmCrossReferenceNamespace (
    254     ACPI_PARSE_OBJECT       *ParseTreeRoot,
    255     ACPI_NAMESPACE_NODE     *NamespaceRoot,
    256     ACPI_OWNER_ID           OwnerId)
    257 {
    258     ACPI_STATUS             Status;
    259     ACPI_OP_WALK_INFO       Info;
    260     ACPI_WALK_STATE         *WalkState;
    261 
    262 
    263     if (!ParseTreeRoot)
    264     {
    265         return;
    266     }
    267 
    268     /* Create and initialize a new walk state */
    269 
    270     WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL);
    271     if (!WalkState)
    272     {
    273         return;
    274     }
    275 
    276     Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type,
    277         WalkState);
    278     if (ACPI_FAILURE (Status))
    279     {
    280         return;
    281     }
    282 
    283     Info.Flags = 0;
    284     Info.Level = 0;
    285     Info.WalkState = WalkState;
    286 
    287     AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmXrefDescendingOp,
    288         AcpiDmCommonAscendingOp, &Info);
    289     ACPI_FREE (WalkState);
    290 }
    291 
    292 
    293 /*******************************************************************************
    294  *
    295  * FUNCTION:    AcpiDmConvertParseObjects
    296  *
    297  * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
    298  *              NamespaceRoot       - Root of the internal namespace
    299  *
    300  * RETURN:      None
    301  *
    302  * DESCRIPTION: Begin parse tree walk to perform conversions needed for
    303  *              disassembly. These include resource descriptors and switch/case
    304  *              operations.
    305  *
    306  ******************************************************************************/
    307 
    308 void
    309 AcpiDmConvertParseObjects (
    310     ACPI_PARSE_OBJECT       *ParseTreeRoot,
    311     ACPI_NAMESPACE_NODE     *NamespaceRoot)
    312 {
    313     ACPI_STATUS             Status;
    314     ACPI_OP_WALK_INFO       Info;
    315     ACPI_WALK_STATE         *WalkState;
    316 
    317 
    318     if (!ParseTreeRoot)
    319     {
    320         return;
    321     }
    322 
    323     /* Create and initialize a new walk state */
    324 
    325     WalkState = AcpiDsCreateWalkState (0, ParseTreeRoot, NULL, NULL);
    326     if (!WalkState)
    327     {
    328         return;
    329     }
    330 
    331     Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type,
    332         WalkState);
    333     if (ACPI_FAILURE (Status))
    334     {
    335         ACPI_FREE (WalkState);
    336         return;
    337     }
    338 
    339     Info.Flags = 0;
    340     Info.Level = 0;
    341     Info.WalkState = WalkState;
    342 
    343     AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmCommonDescendingOp,
    344         AcpiDmCommonAscendingOp, &Info);
    345     ACPI_FREE (WalkState);
    346 
    347     if (AcpiGbl_TempListHead) {
    348         AcpiDmClearTempList();
    349     }
    350 
    351     return;
    352 }
    353 
    354 
    355 /*******************************************************************************
    356  *
    357  * FUNCTION:    AcpiDmDumpDescending
    358  *
    359  * PARAMETERS:  ASL_WALK_CALLBACK
    360  *
    361  * RETURN:      Status
    362  *
    363  * DESCRIPTION: Format and print contents of one parse Op.
    364  *
    365  ******************************************************************************/
    366 
    367 static ACPI_STATUS
    368 AcpiDmDumpDescending (
    369     ACPI_PARSE_OBJECT       *Op,
    370     UINT32                  Level,
    371     void                    *Context)
    372 {
    373     ACPI_OP_WALK_INFO       *Info = Context;
    374     char                    *Path;
    375 
    376 
    377     if (!Op)
    378     {
    379         return (AE_OK);
    380     }
    381 
    382     /* Most of the information (count, level, name) here */
    383 
    384     Info->Count++;
    385     AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level);
    386     AcpiDmIndent (Level);
    387     AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode));
    388 
    389     /* Extra info is helpful */
    390 
    391     switch (Op->Common.AmlOpcode)
    392     {
    393     case AML_BYTE_OP:
    394 
    395         AcpiOsPrintf ("%2.2X", (UINT32) Op->Common.Value.Integer);
    396         break;
    397 
    398     case AML_WORD_OP:
    399 
    400         AcpiOsPrintf ("%4.4X", (UINT32) Op->Common.Value.Integer);
    401         break;
    402 
    403     case AML_DWORD_OP:
    404 
    405         AcpiOsPrintf ("%8.8X", (UINT32) Op->Common.Value.Integer);
    406         break;
    407 
    408     case AML_QWORD_OP:
    409 
    410         AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
    411         break;
    412 
    413     case AML_INT_NAMEPATH_OP:
    414 
    415         if (Op->Common.Value.String)
    416         {
    417             AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
    418                 NULL, &Path);
    419             AcpiOsPrintf ("%s %p", Path, Op->Common.Node);
    420             ACPI_FREE (Path);
    421         }
    422         else
    423         {
    424             AcpiOsPrintf ("[NULL]");
    425         }
    426         break;
    427 
    428     case AML_NAME_OP:
    429     case AML_METHOD_OP:
    430     case AML_DEVICE_OP:
    431 
    432         AcpiOsPrintf ("%4.4s",
    433             ACPI_CAST_PTR (char, &Op->Named.Name));
    434         break;
    435 
    436     case AML_INT_NAMEDFIELD_OP:
    437 
    438         AcpiOsPrintf ("%4.4s Length: (bits) %8.8X%8.8X (bytes) %8.8X%8.8X",
    439             ACPI_CAST_PTR (char, &Op->Named.Name),
    440             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer),
    441             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer / 8));
    442         break;
    443 
    444 
    445     default:
    446 
    447         break;
    448     }
    449 
    450     AcpiOsPrintf ("\n");
    451     return (AE_OK);
    452 }
    453 
    454 
    455 /*******************************************************************************
    456  *
    457  * FUNCTION:    AcpiDmFindOrphanDescending
    458  *
    459  * PARAMETERS:  ASL_WALK_CALLBACK
    460  *
    461  * RETURN:      Status
    462  *
    463  * DESCRIPTION: Check namepath Ops for orphaned method invocations
    464  *
    465  * Note: Parts of this are experimental, under possible further development.
    466  *
    467  ******************************************************************************/
    468 
    469 static ACPI_STATUS
    470 AcpiDmFindOrphanDescending (
    471     ACPI_PARSE_OBJECT       *Op,
    472     UINT32                  Level,
    473     void                    *Context)
    474 {
    475     const ACPI_OPCODE_INFO  *OpInfo;
    476     ACPI_PARSE_OBJECT       *ChildOp;
    477     ACPI_PARSE_OBJECT       *NextOp;
    478     ACPI_PARSE_OBJECT       *ParentOp;
    479     UINT32                  ArgCount;
    480 
    481 
    482     if (!Op)
    483     {
    484         return (AE_OK);
    485     }
    486 
    487     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    488 
    489     switch (Op->Common.AmlOpcode)
    490     {
    491 #ifdef ACPI_UNDER_DEVELOPMENT
    492     case AML_ADD_OP:
    493 
    494         ChildOp = Op->Common.Value.Arg;
    495         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
    496             !ChildOp->Common.Node)
    497         {
    498             AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
    499                 NULL, &Path);
    500             AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n",
    501                 Op->Common.AmlOpName, Path);
    502             ACPI_FREE (Path);
    503 
    504             NextOp = Op->Common.Next;
    505             if (!NextOp)
    506             {
    507                 /* This NamePath has no args, assume it is an integer */
    508 
    509                 AcpiDmAddOpToExternalList (ChildOp,
    510                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
    511                 return (AE_OK);
    512             }
    513 
    514             ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
    515             AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n",
    516                 ArgCount, AcpiDmCountChildren (Op));
    517 
    518             if (ArgCount < 1)
    519             {
    520                 /* One Arg means this is just a Store(Name,Target) */
    521 
    522                 AcpiDmAddOpToExternalList (ChildOp,
    523                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
    524                 return (AE_OK);
    525             }
    526 
    527             AcpiDmAddOpToExternalList (ChildOp,
    528                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
    529         }
    530         break;
    531 
    532 #endif
    533 
    534     case AML_STORE_OP:
    535 
    536         ChildOp = Op->Common.Value.Arg;
    537         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
    538             !ChildOp->Common.Node)
    539         {
    540             NextOp = Op->Common.Next;
    541             if (!NextOp)
    542             {
    543                 /* This NamePath has no args, assume it is an integer */
    544 
    545                 AcpiDmAddOpToExternalList (ChildOp,
    546                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
    547                 return (AE_OK);
    548             }
    549 
    550             ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
    551             if (ArgCount <= 1)
    552             {
    553                 /* One Arg means this is just a Store(Name,Target) */
    554 
    555                 AcpiDmAddOpToExternalList (ChildOp,
    556                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, ArgCount, 0);
    557                 return (AE_OK);
    558             }
    559 
    560             AcpiDmAddOpToExternalList (ChildOp,
    561                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
    562         }
    563         break;
    564 
    565     case AML_INT_NAMEPATH_OP:
    566 
    567         /* Must examine parent to see if this namepath is an argument */
    568 
    569         ParentOp = Op->Common.Parent;
    570         OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
    571 
    572         if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
    573             (OpInfo->Class != AML_CLASS_CREATE) &&
    574             (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) &&
    575             (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
    576             !Op->Common.Node)
    577         {
    578             ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op);
    579 
    580             /*
    581              * Check if namepath is a predicate for if/while or lone parameter to
    582              * a return.
    583              */
    584             if (ArgCount == 0)
    585             {
    586                 if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
    587                      (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
    588                      (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
    589 
    590                      /* And namepath is the first argument */
    591                      (ParentOp->Common.Value.Arg == Op))
    592                 {
    593                     AcpiDmAddOpToExternalList (Op,
    594                         Op->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
    595                     break;
    596                 }
    597             }
    598 
    599             /*
    600              * This is a standalone namestring (not a parameter to another
    601              * operator) - it *must* be a method invocation, nothing else is
    602              * grammatically possible.
    603              */
    604             AcpiDmAddOpToExternalList (Op,
    605                 Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
    606         }
    607         break;
    608 
    609     default:
    610 
    611         break;
    612     }
    613 
    614     return (AE_OK);
    615 }
    616 
    617 
    618 /*******************************************************************************
    619  *
    620  * FUNCTION:    AcpiDmLoadDescendingOp
    621  *
    622  * PARAMETERS:  ASL_WALK_CALLBACK
    623  *
    624  * RETURN:      Status
    625  *
    626  * DESCRIPTION: Descending handler for namespace control method object load
    627  *
    628  ******************************************************************************/
    629 
    630 static ACPI_STATUS
    631 AcpiDmLoadDescendingOp (
    632     ACPI_PARSE_OBJECT       *Op,
    633     UINT32                  Level,
    634     void                    *Context)
    635 {
    636     ACPI_OP_WALK_INFO       *Info = Context;
    637     const ACPI_OPCODE_INFO  *OpInfo;
    638     ACPI_WALK_STATE         *WalkState;
    639     ACPI_OBJECT_TYPE        ObjectType;
    640     ACPI_STATUS             Status;
    641     char                    *Path = NULL;
    642     ACPI_PARSE_OBJECT       *NextOp;
    643     ACPI_NAMESPACE_NODE     *Node;
    644     char                    FieldPath[5];
    645     BOOLEAN                 PreDefined = FALSE;
    646     UINT8                   PreDefineIndex = 0;
    647 
    648 
    649     WalkState = Info->WalkState;
    650     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    651     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
    652 
    653     /* Only interested in operators that create new names */
    654 
    655     if (!(OpInfo->Flags & AML_NAMED) &&
    656         !(OpInfo->Flags & AML_CREATE))
    657     {
    658         goto Exit;
    659     }
    660 
    661     /* Get the NamePath from the appropriate place */
    662 
    663     if (OpInfo->Flags & AML_NAMED)
    664     {
    665         /* For all named operators, get the new name */
    666 
    667         Path = Op->Named.Path;
    668 
    669         if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
    670         {
    671             *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
    672             FieldPath[4] = 0;
    673             Path = FieldPath;
    674         }
    675     }
    676     else if (OpInfo->Flags & AML_CREATE)
    677     {
    678         /* New name is the last child */
    679 
    680         NextOp = Op->Common.Value.Arg;
    681 
    682         while (NextOp->Common.Next)
    683         {
    684             NextOp = NextOp->Common.Next;
    685         }
    686 
    687         Path = NextOp->Common.Value.String;
    688     }
    689 
    690     if (!Path)
    691     {
    692         goto Exit;
    693     }
    694 
    695     /* Insert the name into the namespace */
    696 
    697     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
    698         ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
    699         WalkState, &Node);
    700 
    701     Op->Common.Node = Node;
    702 
    703     if (ACPI_SUCCESS (Status))
    704     {
    705         /* Check if it's a predefined node */
    706 
    707         while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
    708         {
    709             if (ACPI_COMPARE_NAME (Node->Name.Ascii,
    710                 AcpiGbl_PreDefinedNames[PreDefineIndex].Name))
    711             {
    712                 PreDefined = TRUE;
    713                 break;
    714             }
    715 
    716             PreDefineIndex++;
    717         }
    718 
    719         /*
    720          * Set node owner id if it satisfies all the following conditions:
    721          * 1) Not a predefined node, _SB_ etc
    722          * 2) Not the root node
    723          * 3) Not a node created by Scope
    724          */
    725 
    726         if (!PreDefined && Node != AcpiGbl_RootNode &&
    727             Op->Common.AmlOpcode != AML_SCOPE_OP)
    728         {
    729             Node->OwnerId = WalkState->OwnerId;
    730         }
    731     }
    732 
    733 
    734 Exit:
    735 
    736     if (AcpiNsOpensScope (ObjectType))
    737     {
    738         if (Op->Common.Node)
    739         {
    740             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
    741                 WalkState);
    742             if (ACPI_FAILURE (Status))
    743             {
    744                 return (Status);
    745             }
    746         }
    747     }
    748 
    749     return (AE_OK);
    750 }
    751 
    752 
    753 /*******************************************************************************
    754  *
    755  * FUNCTION:    AcpiDmXrefDescendingOp
    756  *
    757  * PARAMETERS:  ASL_WALK_CALLBACK
    758  *
    759  * RETURN:      Status
    760  *
    761  * DESCRIPTION: Descending handler for namespace cross reference
    762  *
    763  ******************************************************************************/
    764 
    765 static ACPI_STATUS
    766 AcpiDmXrefDescendingOp (
    767     ACPI_PARSE_OBJECT       *Op,
    768     UINT32                  Level,
    769     void                    *Context)
    770 {
    771     ACPI_OP_WALK_INFO       *Info = Context;
    772     const ACPI_OPCODE_INFO  *OpInfo;
    773     ACPI_WALK_STATE         *WalkState;
    774     ACPI_OBJECT_TYPE        ObjectType;
    775     ACPI_OBJECT_TYPE        ObjectType2;
    776     ACPI_STATUS             Status;
    777     char                    *Path = NULL;
    778     ACPI_PARSE_OBJECT       *NextOp;
    779     ACPI_NAMESPACE_NODE     *Node;
    780     ACPI_OPERAND_OBJECT     *Object;
    781     UINT32                  ParamCount = 0;
    782     char                    *Pathname;
    783     UINT16                  Flags = 0;
    784 
    785 
    786     WalkState = Info->WalkState;
    787     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    788     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
    789 
    790     if ((!(OpInfo->Flags & AML_NAMED)) &&
    791         (!(OpInfo->Flags & AML_CREATE)) &&
    792         (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP) &&
    793         (Op->Common.AmlOpcode != AML_NOTIFY_OP))
    794     {
    795         goto Exit;
    796     }
    797 
    798     /* Get the NamePath from the appropriate place */
    799 
    800     if (OpInfo->Flags & AML_NAMED)
    801     {
    802         /*
    803          * Only these two operators (Alias, Scope) refer to an existing
    804          * name, it is the first argument
    805          */
    806         if (Op->Common.AmlOpcode == AML_ALIAS_OP)
    807         {
    808             ObjectType = ACPI_TYPE_ANY;
    809 
    810             NextOp = Op->Common.Value.Arg;
    811             NextOp = NextOp->Common.Value.Arg;
    812             if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
    813             {
    814                 Path = NextOp->Common.Value.String;
    815             }
    816         }
    817         else if (Op->Common.AmlOpcode == AML_SCOPE_OP ||
    818                  Op->Common.AmlOpcode == AML_EXTERNAL_OP)
    819         {
    820             Path = Op->Named.Path;
    821         }
    822     }
    823     else if (OpInfo->Flags & AML_CREATE)
    824     {
    825         /* Referenced Buffer Name is the first child */
    826 
    827         ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */
    828 
    829         NextOp = Op->Common.Value.Arg;
    830         if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
    831         {
    832             Path = NextOp->Common.Value.String;
    833         }
    834     }
    835     else if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
    836     {
    837         Path = Op->Common.Value.Arg->Asl.Value.String;
    838     }
    839     else
    840     {
    841         Path = Op->Common.Value.String;
    842     }
    843 
    844     if (!Path)
    845     {
    846         goto Exit;
    847     }
    848 
    849     /*
    850      * Lookup the name in the namespace. Name must exist at this point, or it
    851      * is an invalid reference.
    852      *
    853      * The namespace is also used as a lookup table for references to resource
    854      * descriptors and the fields within them.
    855      */
    856     Node = NULL;
    857     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
    858         ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
    859         WalkState, &Node);
    860 
    861     if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL))
    862     {
    863         /* Node was created by an External() statement */
    864 
    865         Status = AE_NOT_FOUND;
    866     }
    867 
    868     if (ACPI_FAILURE (Status))
    869     {
    870         if (Status == AE_NOT_FOUND)
    871         {
    872             /*
    873              * Add this symbol as an external declaration, except if the
    874              * parent is a CondRefOf operator. For this operator, we do not
    875              * need an external, nor do we want one, since this can cause
    876              * disassembly problems if the symbol is actually a control
    877              * method.
    878              */
    879             if (!(Op->Asl.Parent &&
    880                 (Op->Asl.Parent->Asl.AmlOpcode == AML_CONDITIONAL_REF_OF_OP)))
    881             {
    882                 if (Node)
    883                 {
    884                     AcpiDmAddNodeToExternalList (Node,
    885                         (UINT8) ObjectType, 7, Flags);
    886                 }
    887                 else
    888                 {
    889                     AcpiDmAddOpToExternalList (Op, Path,
    890                         (UINT8) ObjectType, 7, Flags);
    891                 }
    892             }
    893         }
    894     }
    895 
    896     /*
    897      * Found the node, but check if it came from an external table.
    898      * Add it to external list. Note: Node->OwnerId == 0 indicates
    899      * one of the built-in ACPI Names (_OS_ etc.) which can safely
    900      * be ignored.
    901      */
    902     else if (Node->OwnerId &&
    903             (WalkState->OwnerId != Node->OwnerId))
    904     {
    905         ObjectType2 = ObjectType;
    906 
    907         Object = AcpiNsGetAttachedObject (Node);
    908         if (Object)
    909         {
    910             ObjectType2 = Object->Common.Type;
    911             if (ObjectType2 == ACPI_TYPE_METHOD)
    912             {
    913                 ParamCount = Object->Method.ParamCount;
    914             }
    915         }
    916 
    917         Pathname = AcpiNsGetExternalPathname (Node);
    918         if (!Pathname)
    919         {
    920             return (AE_NO_MEMORY);
    921         }
    922 
    923         AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2,
    924             ParamCount, ACPI_EXT_RESOLVED_REFERENCE);
    925 
    926         ACPI_FREE (Pathname);
    927         Op->Common.Node = Node;
    928     }
    929     else
    930     {
    931         Op->Common.Node = Node;
    932     }
    933 
    934 
    935 Exit:
    936     /* Open new scope if necessary */
    937 
    938     if (AcpiNsOpensScope (ObjectType))
    939     {
    940         if (Op->Common.Node)
    941         {
    942             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
    943                 WalkState);
    944             if (ACPI_FAILURE (Status))
    945             {
    946                 return (Status);
    947             }
    948         }
    949     }
    950 
    951     return (AE_OK);
    952 }
    953 
    954 /*******************************************************************************
    955  *
    956  * FUNCTION:    AcpiDmCommonDescendingOp
    957  *
    958  * PARAMETERS:  ASL_WALK_CALLBACK
    959  *
    960  * RETURN:      ACPI_STATUS
    961  *
    962  * DESCRIPTION: Perform parse tree preprocessing before main disassembly walk.
    963  *
    964  ******************************************************************************/
    965 
    966 static ACPI_STATUS
    967 AcpiDmCommonDescendingOp (
    968     ACPI_PARSE_OBJECT       *Op,
    969     UINT32                  Level,
    970     void                    *Context)
    971 {
    972     ACPI_STATUS             Status;
    973 
    974 
    975     /* Resource descriptor conversion */
    976 
    977     Status = AcpiDmProcessResourceDescriptors (Op, Level, Context);
    978     if (ACPI_FAILURE (Status))
    979     {
    980         return (Status);
    981     }
    982 
    983     /* Switch/Case conversion */
    984 
    985     Status = AcpiDmProcessSwitch (Op);
    986     return (AE_OK);
    987 }
    988 
    989 
    990 /*******************************************************************************
    991  *
    992  * FUNCTION:    AcpiDmProcessResourceDescriptors
    993  *
    994  * PARAMETERS:  ASL_WALK_CALLBACK
    995  *
    996  * RETURN:      ACPI_STATUS
    997  *
    998  * DESCRIPTION: Convert fixed-offset references to resource descriptors to
    999  *              symbolic references. Should only be called after namespace has
   1000  *              been cross referenced.
   1001  *
   1002  ******************************************************************************/
   1003 
   1004 static ACPI_STATUS
   1005 AcpiDmProcessResourceDescriptors (
   1006     ACPI_PARSE_OBJECT       *Op,
   1007     UINT32                  Level,
   1008     void                    *Context)
   1009 {
   1010     ACPI_OP_WALK_INFO       *Info = Context;
   1011     const ACPI_OPCODE_INFO  *OpInfo;
   1012     ACPI_WALK_STATE         *WalkState;
   1013     ACPI_OBJECT_TYPE        ObjectType;
   1014     ACPI_STATUS             Status;
   1015 
   1016 
   1017     WalkState = Info->WalkState;
   1018     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
   1019 
   1020     /* Open new scope if necessary */
   1021 
   1022     ObjectType = OpInfo->ObjectType;
   1023     if (AcpiNsOpensScope (ObjectType))
   1024     {
   1025         if (Op->Common.Node)
   1026         {
   1027 
   1028             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
   1029                 WalkState);
   1030             if (ACPI_FAILURE (Status))
   1031             {
   1032                 return (Status);
   1033             }
   1034         }
   1035     }
   1036 
   1037     /*
   1038      * Check if this operator contains a reference to a resource descriptor.
   1039      * If so, convert the reference into a symbolic reference.
   1040      */
   1041     AcpiDmCheckResourceReference (Op, WalkState);
   1042     return (AE_OK);
   1043 }
   1044 
   1045 /*******************************************************************************
   1046  *
   1047  * FUNCTION:    AcpiDmCommonAscendingOp
   1048  *
   1049  * PARAMETERS:  ASL_WALK_CALLBACK
   1050  *
   1051  * RETURN:      None
   1052  *
   1053  * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
   1054  *              scope if necessary.
   1055  *
   1056  ******************************************************************************/
   1057 
   1058 static ACPI_STATUS
   1059 AcpiDmCommonAscendingOp (
   1060     ACPI_PARSE_OBJECT       *Op,
   1061     UINT32                  Level,
   1062     void                    *Context)
   1063 {
   1064     ACPI_OP_WALK_INFO       *Info = Context;
   1065     ACPI_OBJECT_TYPE        ObjectType;
   1066 
   1067 
   1068     /* Close scope if necessary */
   1069 
   1070     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
   1071 
   1072     if (AcpiNsOpensScope (ObjectType))
   1073     {
   1074         (void) AcpiDsScopeStackPop (Info->WalkState);
   1075     }
   1076 
   1077     return (AE_OK);
   1078 }
   1079 
   1080 /*******************************************************************************
   1081  *
   1082  * FUNCTION:    AcpiDmInspectPossibleArgs
   1083  *
   1084  * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
   1085  *                                    possible method invocation found
   1086  *              TargetCount         - Number of targets (0,1,2) for this op
   1087  *              Op                  - Parse op
   1088  *
   1089  * RETURN:      Status
   1090  *
   1091  * DESCRIPTION: Examine following args and next ops for possible arguments
   1092  *              for an unrecognized method invocation.
   1093  *
   1094  ******************************************************************************/
   1095 
   1096 static UINT32
   1097 AcpiDmInspectPossibleArgs (
   1098     UINT32                  CurrentOpArgCount,
   1099     UINT32                  TargetCount,
   1100     ACPI_PARSE_OBJECT       *Op)
   1101 {
   1102     const ACPI_OPCODE_INFO  *OpInfo;
   1103     UINT32                  i;
   1104     UINT32                  ArgumentCount = 0;
   1105     ACPI_PARSE_OBJECT       *NextOp;
   1106     ACPI_PARSE_OBJECT       *ExecuteOp;
   1107 
   1108 
   1109     if (!Op)
   1110     {
   1111         return (0);
   1112     }
   1113 
   1114     /* Lookahead for the maximum number of possible arguments */
   1115 
   1116     NextOp = Op->Common.Next;
   1117 
   1118     for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && NextOp; i++)
   1119     {
   1120         OpInfo = AcpiPsGetOpcodeInfo (NextOp->Common.AmlOpcode);
   1121 
   1122         /* Any one of these operators is "very probably" not a method arg */
   1123 
   1124         if ((NextOp->Common.AmlOpcode == AML_STORE_OP) ||
   1125             (NextOp->Common.AmlOpcode == AML_NOTIFY_OP) ||
   1126             (OpInfo->Class == AML_CLASS_CONTROL) ||
   1127             (OpInfo->Class == AML_CLASS_CREATE) ||
   1128             (OpInfo->Class == AML_CLASS_NAMED_OBJECT))
   1129         {
   1130             break;
   1131         }
   1132 
   1133         if (OpInfo->Class == AML_CLASS_EXECUTE)
   1134         {
   1135             /* Probable that this is method arg if there is no target */
   1136 
   1137             ExecuteOp = NextOp->Common.Value.Arg;
   1138             while (ExecuteOp)
   1139             {
   1140                 if ((ExecuteOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
   1141                     (ExecuteOp->Common.Value.Arg == NULL))
   1142                 {
   1143                     /* No target, could be a method arg */
   1144 
   1145                     break;
   1146                 }
   1147 
   1148                 if (NextOp->Common.AmlOpcode == AML_REF_OF_OP)
   1149                 {
   1150                     break;
   1151                 }
   1152 
   1153                 ExecuteOp = ExecuteOp->Common.Next;
   1154             }
   1155 
   1156             if (!ExecuteOp)
   1157             {
   1158                 /* Has a target, not method arg */
   1159 
   1160                 return (ArgumentCount);
   1161             }
   1162         }
   1163 
   1164         ArgumentCount++;
   1165         NextOp = NextOp->Common.Next;
   1166     }
   1167 
   1168     return (ArgumentCount);
   1169 }
   1170