Home | History | Annotate | Line # | Download | only in common
adwalk.c revision 1.1.1.11.2.2
      1 /******************************************************************************
      2  *
      3  * Module Name: adwalk - Application-level disassembler parse tree walk routines
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2020, 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 #ifdef ACPI_UNDER_DEVELOPMENT
    488     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    489 #endif
    490 
    491     switch (Op->Common.AmlOpcode)
    492     {
    493 #ifdef ACPI_UNDER_DEVELOPMENT
    494     case AML_ADD_OP:
    495 
    496         ChildOp = Op->Common.Value.Arg;
    497         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
    498             !ChildOp->Common.Node)
    499         {
    500             AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
    501                 NULL, &Path);
    502             AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n",
    503                 Op->Common.AmlOpName, Path);
    504             ACPI_FREE (Path);
    505 
    506             NextOp = Op->Common.Next;
    507             if (!NextOp)
    508             {
    509                 /* This NamePath has no args, assume it is an integer */
    510 
    511                 AcpiDmAddOpToExternalList (ChildOp,
    512                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
    513                 return (AE_OK);
    514             }
    515 
    516             ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
    517             AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n",
    518                 ArgCount, AcpiDmCountChildren (Op));
    519 
    520             if (ArgCount < 1)
    521             {
    522                 /* One Arg means this is just a Store(Name,Target) */
    523 
    524                 AcpiDmAddOpToExternalList (ChildOp,
    525                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
    526                 return (AE_OK);
    527             }
    528 
    529             AcpiDmAddOpToExternalList (ChildOp,
    530                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
    531         }
    532         break;
    533 
    534 #endif
    535 
    536     case AML_STORE_OP:
    537 
    538         ChildOp = Op->Common.Value.Arg;
    539         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
    540             !ChildOp->Common.Node)
    541         {
    542             NextOp = Op->Common.Next;
    543             if (!NextOp)
    544             {
    545                 /* This NamePath has no args, assume it is an integer */
    546 
    547                 AcpiDmAddOpToExternalList (ChildOp,
    548                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
    549                 return (AE_OK);
    550             }
    551 
    552             ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
    553             if (ArgCount <= 1)
    554             {
    555                 /* One Arg means this is just a Store(Name,Target) */
    556 
    557                 AcpiDmAddOpToExternalList (ChildOp,
    558                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, ArgCount, 0);
    559                 return (AE_OK);
    560             }
    561 
    562             AcpiDmAddOpToExternalList (ChildOp,
    563                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
    564         }
    565         break;
    566 
    567     case AML_INT_NAMEPATH_OP:
    568 
    569         /* Must examine parent to see if this namepath is an argument */
    570 
    571         ParentOp = Op->Common.Parent;
    572         OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
    573 
    574         if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
    575             (OpInfo->Class != AML_CLASS_CREATE) &&
    576             (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) &&
    577             (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
    578             !Op->Common.Node)
    579         {
    580             ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op);
    581 
    582             /*
    583              * Check if namepath is a predicate for if/while or lone parameter to
    584              * a return.
    585              */
    586             if (ArgCount == 0)
    587             {
    588                 if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
    589                      (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
    590                      (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
    591 
    592                      /* And namepath is the first argument */
    593                      (ParentOp->Common.Value.Arg == Op))
    594                 {
    595                     AcpiDmAddOpToExternalList (Op,
    596                         Op->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
    597                     break;
    598                 }
    599             }
    600 
    601             /*
    602              * This is a standalone namestring (not a parameter to another
    603              * operator) - it *must* be a method invocation, nothing else is
    604              * grammatically possible.
    605              */
    606             AcpiDmAddOpToExternalList (Op,
    607                 Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
    608         }
    609         break;
    610 
    611     default:
    612 
    613         break;
    614     }
    615 
    616     return (AE_OK);
    617 }
    618 
    619 
    620 /*******************************************************************************
    621  *
    622  * FUNCTION:    AcpiDmLoadDescendingOp
    623  *
    624  * PARAMETERS:  ASL_WALK_CALLBACK
    625  *
    626  * RETURN:      Status
    627  *
    628  * DESCRIPTION: Descending handler for namespace control method object load
    629  *
    630  ******************************************************************************/
    631 
    632 static ACPI_STATUS
    633 AcpiDmLoadDescendingOp (
    634     ACPI_PARSE_OBJECT       *Op,
    635     UINT32                  Level,
    636     void                    *Context)
    637 {
    638     ACPI_OP_WALK_INFO       *Info = Context;
    639     const ACPI_OPCODE_INFO  *OpInfo;
    640     ACPI_WALK_STATE         *WalkState;
    641     ACPI_OBJECT_TYPE        ObjectType;
    642     ACPI_STATUS             Status;
    643     char                    *Path = NULL;
    644     ACPI_PARSE_OBJECT       *NextOp;
    645     ACPI_NAMESPACE_NODE     *Node;
    646     char                    FieldPath[5];
    647     BOOLEAN                 PreDefined = FALSE;
    648     UINT8                   PreDefineIndex = 0;
    649 
    650 
    651     WalkState = Info->WalkState;
    652     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    653     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
    654 
    655     /* Only interested in operators that create new names */
    656 
    657     if (!(OpInfo->Flags & AML_NAMED) &&
    658         !(OpInfo->Flags & AML_CREATE))
    659     {
    660         goto Exit;
    661     }
    662 
    663     /* Get the NamePath from the appropriate place */
    664 
    665     if (OpInfo->Flags & AML_NAMED)
    666     {
    667         /* For all named operators, get the new name */
    668 
    669         Path = Op->Named.Path;
    670 
    671         if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
    672         {
    673             *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
    674             FieldPath[4] = 0;
    675             Path = FieldPath;
    676         }
    677     }
    678     else if (OpInfo->Flags & AML_CREATE)
    679     {
    680         /* New name is the last child */
    681 
    682         NextOp = Op->Common.Value.Arg;
    683 
    684         while (NextOp->Common.Next)
    685         {
    686             NextOp = NextOp->Common.Next;
    687         }
    688 
    689         Path = NextOp->Common.Value.String;
    690     }
    691 
    692     if (!Path)
    693     {
    694         goto Exit;
    695     }
    696 
    697     /* Insert the name into the namespace */
    698 
    699     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
    700         ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
    701         WalkState, &Node);
    702 
    703     Op->Common.Node = Node;
    704 
    705     if (ACPI_SUCCESS (Status))
    706     {
    707         /* Check if it's a predefined node */
    708 
    709         while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
    710         {
    711             if (ACPI_COMPARE_NAMESEG (Node->Name.Ascii,
    712                 AcpiGbl_PreDefinedNames[PreDefineIndex].Name))
    713             {
    714                 PreDefined = TRUE;
    715                 break;
    716             }
    717 
    718             PreDefineIndex++;
    719         }
    720 
    721         /*
    722          * Set node owner id if it satisfies all the following conditions:
    723          * 1) Not a predefined node, _SB_ etc
    724          * 2) Not the root node
    725          * 3) Not a node created by Scope
    726          */
    727 
    728         if (!PreDefined && Node != AcpiGbl_RootNode &&
    729             Op->Common.AmlOpcode != AML_SCOPE_OP)
    730         {
    731             Node->OwnerId = WalkState->OwnerId;
    732         }
    733     }
    734 
    735 
    736 Exit:
    737 
    738     if (AcpiNsOpensScope (ObjectType))
    739     {
    740         if (Op->Common.Node)
    741         {
    742             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
    743                 WalkState);
    744             if (ACPI_FAILURE (Status))
    745             {
    746                 return (Status);
    747             }
    748         }
    749     }
    750 
    751     return (AE_OK);
    752 }
    753 
    754 
    755 /*******************************************************************************
    756  *
    757  * FUNCTION:    AcpiDmXrefDescendingOp
    758  *
    759  * PARAMETERS:  ASL_WALK_CALLBACK
    760  *
    761  * RETURN:      Status
    762  *
    763  * DESCRIPTION: Descending handler for namespace cross reference
    764  *
    765  ******************************************************************************/
    766 
    767 static ACPI_STATUS
    768 AcpiDmXrefDescendingOp (
    769     ACPI_PARSE_OBJECT       *Op,
    770     UINT32                  Level,
    771     void                    *Context)
    772 {
    773     ACPI_OP_WALK_INFO       *Info = Context;
    774     const ACPI_OPCODE_INFO  *OpInfo;
    775     ACPI_WALK_STATE         *WalkState;
    776     ACPI_OBJECT_TYPE        ObjectType;
    777     ACPI_OBJECT_TYPE        ObjectType2;
    778     ACPI_STATUS             Status;
    779     char                    *Path = NULL;
    780     ACPI_PARSE_OBJECT       *NextOp;
    781     ACPI_NAMESPACE_NODE     *Node;
    782     ACPI_OPERAND_OBJECT     *Object;
    783     UINT32                  ParamCount = 0;
    784     char                    *Pathname;
    785     UINT16                  Flags = 0;
    786 
    787 
    788     WalkState = Info->WalkState;
    789     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    790     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
    791 
    792     if ((!(OpInfo->Flags & AML_NAMED)) &&
    793         (!(OpInfo->Flags & AML_CREATE)) &&
    794         (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP) &&
    795         (Op->Common.AmlOpcode != AML_NOTIFY_OP))
    796     {
    797         goto Exit;
    798     }
    799 
    800     /* Get the NamePath from the appropriate place */
    801 
    802     if (OpInfo->Flags & AML_NAMED)
    803     {
    804         /*
    805          * Only these two operators (Alias, Scope) refer to an existing
    806          * name, it is the first argument
    807          */
    808         if (Op->Common.AmlOpcode == AML_ALIAS_OP)
    809         {
    810             ObjectType = ACPI_TYPE_ANY;
    811 
    812             NextOp = Op->Common.Value.Arg;
    813             NextOp = NextOp->Common.Value.Arg;
    814             if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
    815             {
    816                 Path = NextOp->Common.Value.String;
    817             }
    818         }
    819         else if (Op->Common.AmlOpcode == AML_SCOPE_OP ||
    820                  Op->Common.AmlOpcode == AML_EXTERNAL_OP)
    821         {
    822             Path = Op->Named.Path;
    823         }
    824     }
    825     else if (OpInfo->Flags & AML_CREATE)
    826     {
    827         /* Referenced Buffer Name is the first child */
    828 
    829         ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */
    830 
    831         NextOp = Op->Common.Value.Arg;
    832         if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
    833         {
    834             Path = NextOp->Common.Value.String;
    835         }
    836     }
    837     else if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
    838     {
    839         Path = Op->Common.Value.Arg->Asl.Value.String;
    840     }
    841     else
    842     {
    843         Path = Op->Common.Value.String;
    844     }
    845 
    846     if (!Path)
    847     {
    848         goto Exit;
    849     }
    850 
    851     /*
    852      * Lookup the name in the namespace. Name must exist at this point, or it
    853      * is an invalid reference.
    854      *
    855      * The namespace is also used as a lookup table for references to resource
    856      * descriptors and the fields within them.
    857      */
    858     Node = NULL;
    859     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
    860         ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
    861         WalkState, &Node);
    862 
    863     if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL))
    864     {
    865         /* Node was created by an External() statement */
    866 
    867         Status = AE_NOT_FOUND;
    868     }
    869 
    870     if (ACPI_FAILURE (Status))
    871     {
    872         if (Status == AE_NOT_FOUND)
    873         {
    874             /*
    875              * Add this symbol as an external declaration, except if the
    876              * parent is a CondRefOf operator. For this operator, we do not
    877              * need an external, nor do we want one, since this can cause
    878              * disassembly problems if the symbol is actually a control
    879              * method.
    880              */
    881             if (!(Op->Asl.Parent &&
    882                 (Op->Asl.Parent->Asl.AmlOpcode == AML_CONDITIONAL_REF_OF_OP)))
    883             {
    884                 if (Node)
    885                 {
    886                     AcpiDmAddNodeToExternalList (Node,
    887                         (UINT8) ObjectType, 7, Flags);
    888                 }
    889                 else
    890                 {
    891                     AcpiDmAddOpToExternalList (Op, Path,
    892                         (UINT8) ObjectType, 7, Flags);
    893                 }
    894             }
    895         }
    896     }
    897 
    898     /*
    899      * Found the node, but check if it came from an external table.
    900      * Add it to external list. Note: Node->OwnerId == 0 indicates
    901      * one of the built-in ACPI Names (_OS_ etc.) which can safely
    902      * be ignored.
    903      */
    904     else if (Node->OwnerId &&
    905             (WalkState->OwnerId != Node->OwnerId))
    906     {
    907         ObjectType2 = ObjectType;
    908 
    909         Object = AcpiNsGetAttachedObject (Node);
    910         if (Object)
    911         {
    912             ObjectType2 = Object->Common.Type;
    913             if (ObjectType2 == ACPI_TYPE_METHOD)
    914             {
    915                 ParamCount = Object->Method.ParamCount;
    916             }
    917         }
    918 
    919         Pathname = AcpiNsGetExternalPathname (Node);
    920         if (!Pathname)
    921         {
    922             return (AE_NO_MEMORY);
    923         }
    924 
    925         AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2,
    926             ParamCount, ACPI_EXT_RESOLVED_REFERENCE);
    927 
    928         ACPI_FREE (Pathname);
    929         Op->Common.Node = Node;
    930     }
    931     else
    932     {
    933         Op->Common.Node = Node;
    934     }
    935 
    936 
    937 Exit:
    938     /* Open new scope if necessary */
    939 
    940     if (AcpiNsOpensScope (ObjectType))
    941     {
    942         if (Op->Common.Node)
    943         {
    944             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
    945                 WalkState);
    946             if (ACPI_FAILURE (Status))
    947             {
    948                 return (Status);
    949             }
    950         }
    951     }
    952 
    953     return (AE_OK);
    954 }
    955 
    956 /*******************************************************************************
    957  *
    958  * FUNCTION:    AcpiDmCommonDescendingOp
    959  *
    960  * PARAMETERS:  ASL_WALK_CALLBACK
    961  *
    962  * RETURN:      ACPI_STATUS
    963  *
    964  * DESCRIPTION: Perform parse tree preprocessing before main disassembly walk.
    965  *
    966  ******************************************************************************/
    967 
    968 static ACPI_STATUS
    969 AcpiDmCommonDescendingOp (
    970     ACPI_PARSE_OBJECT       *Op,
    971     UINT32                  Level,
    972     void                    *Context)
    973 {
    974     ACPI_STATUS             Status;
    975 
    976 
    977     /* Resource descriptor conversion */
    978 
    979     Status = AcpiDmProcessResourceDescriptors (Op, Level, Context);
    980     if (ACPI_FAILURE (Status))
    981     {
    982         return (Status);
    983     }
    984 
    985     /* Switch/Case conversion */
    986 
    987     Status = AcpiDmProcessSwitch (Op);
    988     return (Status);
    989 }
    990 
    991 
    992 /*******************************************************************************
    993  *
    994  * FUNCTION:    AcpiDmProcessResourceDescriptors
    995  *
    996  * PARAMETERS:  ASL_WALK_CALLBACK
    997  *
    998  * RETURN:      ACPI_STATUS
    999  *
   1000  * DESCRIPTION: Convert fixed-offset references to resource descriptors to
   1001  *              symbolic references. Should only be called after namespace has
   1002  *              been cross referenced.
   1003  *
   1004  ******************************************************************************/
   1005 
   1006 static ACPI_STATUS
   1007 AcpiDmProcessResourceDescriptors (
   1008     ACPI_PARSE_OBJECT       *Op,
   1009     UINT32                  Level,
   1010     void                    *Context)
   1011 {
   1012     ACPI_OP_WALK_INFO       *Info = Context;
   1013     const ACPI_OPCODE_INFO  *OpInfo;
   1014     ACPI_WALK_STATE         *WalkState;
   1015     ACPI_OBJECT_TYPE        ObjectType;
   1016     ACPI_STATUS             Status;
   1017 
   1018 
   1019     WalkState = Info->WalkState;
   1020     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
   1021 
   1022     /* Open new scope if necessary */
   1023 
   1024     ObjectType = OpInfo->ObjectType;
   1025     if (AcpiNsOpensScope (ObjectType))
   1026     {
   1027         if (Op->Common.Node)
   1028         {
   1029 
   1030             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
   1031                 WalkState);
   1032             if (ACPI_FAILURE (Status))
   1033             {
   1034                 return (Status);
   1035             }
   1036         }
   1037     }
   1038 
   1039     /*
   1040      * Check if this operator contains a reference to a resource descriptor.
   1041      * If so, convert the reference into a symbolic reference.
   1042      */
   1043     AcpiDmCheckResourceReference (Op, WalkState);
   1044     return (AE_OK);
   1045 }
   1046 
   1047 /*******************************************************************************
   1048  *
   1049  * FUNCTION:    AcpiDmCommonAscendingOp
   1050  *
   1051  * PARAMETERS:  ASL_WALK_CALLBACK
   1052  *
   1053  * RETURN:      None
   1054  *
   1055  * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
   1056  *              scope if necessary.
   1057  *
   1058  ******************************************************************************/
   1059 
   1060 static ACPI_STATUS
   1061 AcpiDmCommonAscendingOp (
   1062     ACPI_PARSE_OBJECT       *Op,
   1063     UINT32                  Level,
   1064     void                    *Context)
   1065 {
   1066     ACPI_OP_WALK_INFO       *Info = Context;
   1067     ACPI_OBJECT_TYPE        ObjectType;
   1068 
   1069 
   1070     /* Close scope if necessary */
   1071 
   1072     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
   1073 
   1074     if (AcpiNsOpensScope (ObjectType))
   1075     {
   1076         (void) AcpiDsScopeStackPop (Info->WalkState);
   1077     }
   1078 
   1079     return (AE_OK);
   1080 }
   1081 
   1082 /*******************************************************************************
   1083  *
   1084  * FUNCTION:    AcpiDmInspectPossibleArgs
   1085  *
   1086  * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
   1087  *                                    possible method invocation found
   1088  *              TargetCount         - Number of targets (0,1,2) for this op
   1089  *              Op                  - Parse op
   1090  *
   1091  * RETURN:      Status
   1092  *
   1093  * DESCRIPTION: Examine following args and next ops for possible arguments
   1094  *              for an unrecognized method invocation.
   1095  *
   1096  ******************************************************************************/
   1097 
   1098 static UINT32
   1099 AcpiDmInspectPossibleArgs (
   1100     UINT32                  CurrentOpArgCount,
   1101     UINT32                  TargetCount,
   1102     ACPI_PARSE_OBJECT       *Op)
   1103 {
   1104     const ACPI_OPCODE_INFO  *OpInfo;
   1105     UINT32                  i;
   1106     UINT32                  ArgumentCount = 0;
   1107     ACPI_PARSE_OBJECT       *NextOp;
   1108     ACPI_PARSE_OBJECT       *ExecuteOp;
   1109 
   1110 
   1111     if (!Op)
   1112     {
   1113         return (0);
   1114     }
   1115 
   1116     /* Lookahead for the maximum number of possible arguments */
   1117 
   1118     NextOp = Op->Common.Next;
   1119 
   1120     for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && NextOp; i++)
   1121     {
   1122         OpInfo = AcpiPsGetOpcodeInfo (NextOp->Common.AmlOpcode);
   1123 
   1124         /* Any one of these operators is "very probably" not a method arg */
   1125 
   1126         if ((NextOp->Common.AmlOpcode == AML_STORE_OP) ||
   1127             (NextOp->Common.AmlOpcode == AML_NOTIFY_OP) ||
   1128             (OpInfo->Class == AML_CLASS_CONTROL) ||
   1129             (OpInfo->Class == AML_CLASS_CREATE) ||
   1130             (OpInfo->Class == AML_CLASS_NAMED_OBJECT))
   1131         {
   1132             break;
   1133         }
   1134 
   1135         if (OpInfo->Class == AML_CLASS_EXECUTE)
   1136         {
   1137             /* Probable that this is method arg if there is no target */
   1138 
   1139             ExecuteOp = NextOp->Common.Value.Arg;
   1140             while (ExecuteOp)
   1141             {
   1142                 if ((ExecuteOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
   1143                     (ExecuteOp->Common.Value.Arg == NULL))
   1144                 {
   1145                     /* No target, could be a method arg */
   1146 
   1147                     break;
   1148                 }
   1149 
   1150                 if (NextOp->Common.AmlOpcode == AML_REF_OF_OP)
   1151                 {
   1152                     break;
   1153                 }
   1154 
   1155                 ExecuteOp = ExecuteOp->Common.Next;
   1156             }
   1157 
   1158             if (!ExecuteOp)
   1159             {
   1160                 /* Has a target, not method arg */
   1161 
   1162                 return (ArgumentCount);
   1163             }
   1164         }
   1165 
   1166         ArgumentCount++;
   1167         NextOp = NextOp->Common.Next;
   1168     }
   1169 
   1170     return (ArgumentCount);
   1171 }
   1172