Home | History | Annotate | Line # | Download | only in dispatcher
dsutils.c revision 1.1
      1 /*******************************************************************************
      2  *
      3  * Module Name: dsutils - Dispatcher utilities
      4  *
      5  ******************************************************************************/
      6 
      7 /******************************************************************************
      8  *
      9  * 1. Copyright Notice
     10  *
     11  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
     12  * All rights reserved.
     13  *
     14  * 2. License
     15  *
     16  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  * rights.  You may have additional license terms from the party that provided
     18  * you this software, covering your right to use that party's intellectual
     19  * property rights.
     20  *
     21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  * copy of the source code appearing in this file ("Covered Code") an
     23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  * make derivatives, distribute, use and display any portion of the Covered
     26  * Code in any form, with the right to sublicense such rights; and
     27  *
     28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  * license (with the right to sublicense), under only those claims of Intel
     30  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  * offer to sell, and import the Covered Code and derivative works thereof
     32  * solely to the minimum extent necessary to exercise the above copyright
     33  * license, and in no event shall the patent license extend to any additions
     34  * to or modifications of the Original Intel Code.  No other license or right
     35  * is granted directly or by implication, estoppel or otherwise;
     36  *
     37  * The above copyright and patent license is granted only if the following
     38  * conditions are met:
     39  *
     40  * 3. Conditions
     41  *
     42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  * Redistribution of source code of any substantial portion of the Covered
     44  * Code or modification with rights to further distribute source must include
     45  * the above Copyright Notice, the above License, this list of Conditions,
     46  * and the following Disclaimer and Export Compliance provision.  In addition,
     47  * Licensee must cause all Covered Code to which Licensee contributes to
     48  * contain a file documenting the changes Licensee made to create that Covered
     49  * Code and the date of any change.  Licensee must include in that file the
     50  * documentation of any changes made by any predecessor Licensee.  Licensee
     51  * must include a prominent statement that the modification is derived,
     52  * directly or indirectly, from Original Intel Code.
     53  *
     54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  * Redistribution of source code of any substantial portion of the Covered
     56  * Code or modification without rights to further distribute source must
     57  * include the following Disclaimer and Export Compliance provision in the
     58  * documentation and/or other materials provided with distribution.  In
     59  * addition, Licensee may not authorize further sublicense of source of any
     60  * portion of the Covered Code, and must include terms to the effect that the
     61  * license from Licensee to its licensee is limited to the intellectual
     62  * property embodied in the software Licensee provides to its licensee, and
     63  * not to intellectual property embodied in modifications its licensee may
     64  * make.
     65  *
     66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  * substantial portion of the Covered Code or modification must reproduce the
     68  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  * provision in the documentation and/or other materials provided with the
     70  * distribution.
     71  *
     72  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  * Intel Code.
     74  *
     75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  * other dealings in products derived from or relating to the Covered Code
     78  * without prior written authorization from Intel.
     79  *
     80  * 4. Disclaimer and Export Compliance
     81  *
     82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
     85  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
     86  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
     87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  * PARTICULAR PURPOSE.
     89  *
     90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
     96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  * LIMITED REMEDY.
     98  *
     99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  * software or system incorporating such software without first obtaining any
    101  * required license or other approval from the U. S. Department of Commerce or
    102  * any other agency or department of the United States Government.  In the
    103  * event Licensee exports any such software from the United States or
    104  * re-exports any such software from a foreign destination, Licensee shall
    105  * ensure that the distribution and export/re-export of the software is in
    106  * compliance with all laws, regulations, orders, or other restrictions of the
    107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  * any of its subsidiaries will export/re-export any technical data, process,
    109  * software, or service, directly or indirectly, to any country for which the
    110  * United States government or any agency thereof requires an export license,
    111  * other governmental approval, or letter of assurance, without first obtaining
    112  * such license, approval or letter.
    113  *
    114  *****************************************************************************/
    115 
    116 #define __DSUTILS_C__
    117 
    118 #include "acpi.h"
    119 #include "accommon.h"
    120 #include "acparser.h"
    121 #include "amlcode.h"
    122 #include "acdispat.h"
    123 #include "acinterp.h"
    124 #include "acnamesp.h"
    125 #include "acdebug.h"
    126 
    127 #define _COMPONENT          ACPI_DISPATCHER
    128         ACPI_MODULE_NAME    ("dsutils")
    129 
    130 
    131 /*******************************************************************************
    132  *
    133  * FUNCTION:    AcpiDsClearImplicitReturn
    134  *
    135  * PARAMETERS:  WalkState           - Current State
    136  *
    137  * RETURN:      None.
    138  *
    139  * DESCRIPTION: Clear and remove a reference on an implicit return value.  Used
    140  *              to delete "stale" return values (if enabled, the return value
    141  *              from every operator is saved at least momentarily, in case the
    142  *              parent method exits.)
    143  *
    144  ******************************************************************************/
    145 
    146 void
    147 AcpiDsClearImplicitReturn (
    148     ACPI_WALK_STATE         *WalkState)
    149 {
    150     ACPI_FUNCTION_NAME (DsClearImplicitReturn);
    151 
    152 
    153     /*
    154      * Slack must be enabled for this feature
    155      */
    156     if (!AcpiGbl_EnableInterpreterSlack)
    157     {
    158         return;
    159     }
    160 
    161     if (WalkState->ImplicitReturnObj)
    162     {
    163         /*
    164          * Delete any "stale" implicit return. However, in
    165          * complex statements, the implicit return value can be
    166          * bubbled up several levels.
    167          */
    168         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    169             "Removing reference on stale implicit return obj %p\n",
    170             WalkState->ImplicitReturnObj));
    171 
    172         AcpiUtRemoveReference (WalkState->ImplicitReturnObj);
    173         WalkState->ImplicitReturnObj = NULL;
    174     }
    175 }
    176 
    177 
    178 #ifndef ACPI_NO_METHOD_EXECUTION
    179 /*******************************************************************************
    180  *
    181  * FUNCTION:    AcpiDsDoImplicitReturn
    182  *
    183  * PARAMETERS:  ReturnDesc          - The return value
    184  *              WalkState           - Current State
    185  *              AddReference        - True if a reference should be added to the
    186  *                                    return object
    187  *
    188  * RETURN:      TRUE if implicit return enabled, FALSE otherwise
    189  *
    190  * DESCRIPTION: Implements the optional "implicit return".  We save the result
    191  *              of every ASL operator and control method invocation in case the
    192  *              parent method exit.  Before storing a new return value, we
    193  *              delete the previous return value.
    194  *
    195  ******************************************************************************/
    196 
    197 BOOLEAN
    198 AcpiDsDoImplicitReturn (
    199     ACPI_OPERAND_OBJECT     *ReturnDesc,
    200     ACPI_WALK_STATE         *WalkState,
    201     BOOLEAN                 AddReference)
    202 {
    203     ACPI_FUNCTION_NAME (DsDoImplicitReturn);
    204 
    205 
    206     /*
    207      * Slack must be enabled for this feature, and we must
    208      * have a valid return object
    209      */
    210     if ((!AcpiGbl_EnableInterpreterSlack) ||
    211         (!ReturnDesc))
    212     {
    213         return (FALSE);
    214     }
    215 
    216     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    217             "Result %p will be implicitly returned; Prev=%p\n",
    218             ReturnDesc,
    219             WalkState->ImplicitReturnObj));
    220 
    221     /*
    222      * Delete any "stale" implicit return value first. However, in
    223      * complex statements, the implicit return value can be
    224      * bubbled up several levels, so we don't clear the value if it
    225      * is the same as the ReturnDesc.
    226      */
    227     if (WalkState->ImplicitReturnObj)
    228     {
    229         if (WalkState->ImplicitReturnObj == ReturnDesc)
    230         {
    231             return (TRUE);
    232         }
    233         AcpiDsClearImplicitReturn (WalkState);
    234     }
    235 
    236     /* Save the implicit return value, add a reference if requested */
    237 
    238     WalkState->ImplicitReturnObj = ReturnDesc;
    239     if (AddReference)
    240     {
    241         AcpiUtAddReference (ReturnDesc);
    242     }
    243 
    244     return (TRUE);
    245 }
    246 
    247 
    248 /*******************************************************************************
    249  *
    250  * FUNCTION:    AcpiDsIsResultUsed
    251  *
    252  * PARAMETERS:  Op                  - Current Op
    253  *              WalkState           - Current State
    254  *
    255  * RETURN:      TRUE if result is used, FALSE otherwise
    256  *
    257  * DESCRIPTION: Check if a result object will be used by the parent
    258  *
    259  ******************************************************************************/
    260 
    261 BOOLEAN
    262 AcpiDsIsResultUsed (
    263     ACPI_PARSE_OBJECT       *Op,
    264     ACPI_WALK_STATE         *WalkState)
    265 {
    266     const ACPI_OPCODE_INFO  *ParentInfo;
    267 
    268     ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op);
    269 
    270 
    271     /* Must have both an Op and a Result Object */
    272 
    273     if (!Op)
    274     {
    275         ACPI_ERROR ((AE_INFO, "Null Op"));
    276         return_UINT8 (TRUE);
    277     }
    278 
    279     /*
    280      * We know that this operator is not a
    281      * Return() operator (would not come here.) The following code is the
    282      * optional support for a so-called "implicit return". Some AML code
    283      * assumes that the last value of the method is "implicitly" returned
    284      * to the caller. Just save the last result as the return value.
    285      * NOTE: this is optional because the ASL language does not actually
    286      * support this behavior.
    287      */
    288     (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE);
    289 
    290     /*
    291      * Now determine if the parent will use the result
    292      *
    293      * If there is no parent, or the parent is a ScopeOp, we are executing
    294      * at the method level. An executing method typically has no parent,
    295      * since each method is parsed separately.  A method invoked externally
    296      * via ExecuteControlMethod has a ScopeOp as the parent.
    297      */
    298     if ((!Op->Common.Parent) ||
    299         (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
    300     {
    301         /* No parent, the return value cannot possibly be used */
    302 
    303         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    304             "At Method level, result of [%s] not used\n",
    305             AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
    306         return_UINT8 (FALSE);
    307     }
    308 
    309     /* Get info on the parent. The RootOp is AML_SCOPE */
    310 
    311     ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
    312     if (ParentInfo->Class == AML_CLASS_UNKNOWN)
    313     {
    314         ACPI_ERROR ((AE_INFO,
    315             "Unknown parent opcode Op=%p", Op));
    316         return_UINT8 (FALSE);
    317     }
    318 
    319     /*
    320      * Decide what to do with the result based on the parent.  If
    321      * the parent opcode will not use the result, delete the object.
    322      * Otherwise leave it as is, it will be deleted when it is used
    323      * as an operand later.
    324      */
    325     switch (ParentInfo->Class)
    326     {
    327     case AML_CLASS_CONTROL:
    328 
    329         switch (Op->Common.Parent->Common.AmlOpcode)
    330         {
    331         case AML_RETURN_OP:
    332 
    333             /* Never delete the return value associated with a return opcode */
    334 
    335             goto ResultUsed;
    336 
    337         case AML_IF_OP:
    338         case AML_WHILE_OP:
    339 
    340             /*
    341              * If we are executing the predicate AND this is the predicate op,
    342              * we will use the return value
    343              */
    344             if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) &&
    345                 (WalkState->ControlState->Control.PredicateOp == Op))
    346             {
    347                 goto ResultUsed;
    348             }
    349             break;
    350 
    351         default:
    352             /* Ignore other control opcodes */
    353             break;
    354         }
    355 
    356         /* The general control opcode returns no result */
    357 
    358         goto ResultNotUsed;
    359 
    360 
    361     case AML_CLASS_CREATE:
    362 
    363         /*
    364          * These opcodes allow TermArg(s) as operands and therefore
    365          * the operands can be method calls.  The result is used.
    366          */
    367         goto ResultUsed;
    368 
    369 
    370     case AML_CLASS_NAMED_OBJECT:
    371 
    372         if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
    373             (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
    374             (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
    375             (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)  ||
    376             (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
    377             (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) ||
    378             (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP))
    379         {
    380             /*
    381              * These opcodes allow TermArg(s) as operands and therefore
    382              * the operands can be method calls.  The result is used.
    383              */
    384             goto ResultUsed;
    385         }
    386 
    387         goto ResultNotUsed;
    388 
    389 
    390     default:
    391 
    392         /*
    393          * In all other cases. the parent will actually use the return
    394          * object, so keep it.
    395          */
    396         goto ResultUsed;
    397     }
    398 
    399 
    400 ResultUsed:
    401     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    402         "Result of [%s] used by Parent [%s] Op=%p\n",
    403         AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
    404         AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
    405 
    406     return_UINT8 (TRUE);
    407 
    408 
    409 ResultNotUsed:
    410     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    411         "Result of [%s] not used by Parent [%s] Op=%p\n",
    412         AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
    413         AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
    414 
    415     return_UINT8 (FALSE);
    416 }
    417 
    418 
    419 /*******************************************************************************
    420  *
    421  * FUNCTION:    AcpiDsDeleteResultIfNotUsed
    422  *
    423  * PARAMETERS:  Op              - Current parse Op
    424  *              ResultObj       - Result of the operation
    425  *              WalkState       - Current state
    426  *
    427  * RETURN:      Status
    428  *
    429  * DESCRIPTION: Used after interpretation of an opcode.  If there is an internal
    430  *              result descriptor, check if the parent opcode will actually use
    431  *              this result.  If not, delete the result now so that it will
    432  *              not become orphaned.
    433  *
    434  ******************************************************************************/
    435 
    436 void
    437 AcpiDsDeleteResultIfNotUsed (
    438     ACPI_PARSE_OBJECT       *Op,
    439     ACPI_OPERAND_OBJECT     *ResultObj,
    440     ACPI_WALK_STATE         *WalkState)
    441 {
    442     ACPI_OPERAND_OBJECT     *ObjDesc;
    443     ACPI_STATUS             Status;
    444 
    445 
    446     ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj);
    447 
    448 
    449     if (!Op)
    450     {
    451         ACPI_ERROR ((AE_INFO, "Null Op"));
    452         return_VOID;
    453     }
    454 
    455     if (!ResultObj)
    456     {
    457         return_VOID;
    458     }
    459 
    460     if (!AcpiDsIsResultUsed (Op, WalkState))
    461     {
    462         /* Must pop the result stack (ObjDesc should be equal to ResultObj) */
    463 
    464         Status = AcpiDsResultPop (&ObjDesc, WalkState);
    465         if (ACPI_SUCCESS (Status))
    466         {
    467             AcpiUtRemoveReference (ResultObj);
    468         }
    469     }
    470 
    471     return_VOID;
    472 }
    473 
    474 
    475 /*******************************************************************************
    476  *
    477  * FUNCTION:    AcpiDsResolveOperands
    478  *
    479  * PARAMETERS:  WalkState           - Current walk state with operands on stack
    480  *
    481  * RETURN:      Status
    482  *
    483  * DESCRIPTION: Resolve all operands to their values.  Used to prepare
    484  *              arguments to a control method invocation (a call from one
    485  *              method to another.)
    486  *
    487  ******************************************************************************/
    488 
    489 ACPI_STATUS
    490 AcpiDsResolveOperands (
    491     ACPI_WALK_STATE         *WalkState)
    492 {
    493     UINT32                  i;
    494     ACPI_STATUS             Status = AE_OK;
    495 
    496 
    497     ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState);
    498 
    499 
    500     /*
    501      * Attempt to resolve each of the valid operands
    502      * Method arguments are passed by reference, not by value.  This means
    503      * that the actual objects are passed, not copies of the objects.
    504      */
    505     for (i = 0; i < WalkState->NumOperands; i++)
    506     {
    507         Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState);
    508         if (ACPI_FAILURE (Status))
    509         {
    510             break;
    511         }
    512     }
    513 
    514     return_ACPI_STATUS (Status);
    515 }
    516 
    517 
    518 /*******************************************************************************
    519  *
    520  * FUNCTION:    AcpiDsClearOperands
    521  *
    522  * PARAMETERS:  WalkState           - Current walk state with operands on stack
    523  *
    524  * RETURN:      None
    525  *
    526  * DESCRIPTION: Clear all operands on the current walk state operand stack.
    527  *
    528  ******************************************************************************/
    529 
    530 void
    531 AcpiDsClearOperands (
    532     ACPI_WALK_STATE         *WalkState)
    533 {
    534     UINT32                  i;
    535 
    536 
    537     ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState);
    538 
    539 
    540     /* Remove a reference on each operand on the stack */
    541 
    542     for (i = 0; i < WalkState->NumOperands; i++)
    543     {
    544         /*
    545          * Remove a reference to all operands, including both
    546          * "Arguments" and "Targets".
    547          */
    548         AcpiUtRemoveReference (WalkState->Operands[i]);
    549         WalkState->Operands[i] = NULL;
    550     }
    551 
    552     WalkState->NumOperands = 0;
    553     return_VOID;
    554 }
    555 #endif
    556 
    557 
    558 /*******************************************************************************
    559  *
    560  * FUNCTION:    AcpiDsCreateOperand
    561  *
    562  * PARAMETERS:  WalkState       - Current walk state
    563  *              Arg             - Parse object for the argument
    564  *              ArgIndex        - Which argument (zero based)
    565  *
    566  * RETURN:      Status
    567  *
    568  * DESCRIPTION: Translate a parse tree object that is an argument to an AML
    569  *              opcode to the equivalent interpreter object.  This may include
    570  *              looking up a name or entering a new name into the internal
    571  *              namespace.
    572  *
    573  ******************************************************************************/
    574 
    575 ACPI_STATUS
    576 AcpiDsCreateOperand (
    577     ACPI_WALK_STATE         *WalkState,
    578     ACPI_PARSE_OBJECT       *Arg,
    579     UINT32                  ArgIndex)
    580 {
    581     ACPI_STATUS             Status = AE_OK;
    582     char                    *NameString;
    583     UINT32                  NameLength;
    584     ACPI_OPERAND_OBJECT     *ObjDesc;
    585     ACPI_PARSE_OBJECT       *ParentOp;
    586     UINT16                  Opcode;
    587     ACPI_INTERPRETER_MODE   InterpreterMode;
    588     const ACPI_OPCODE_INFO  *OpInfo;
    589 
    590 
    591     ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);
    592 
    593 
    594     /* A valid name must be looked up in the namespace */
    595 
    596     if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
    597         (Arg->Common.Value.String) &&
    598         !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
    599     {
    600         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));
    601 
    602         /* Get the entire name string from the AML stream */
    603 
    604         Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer,
    605                         &NameString, &NameLength);
    606 
    607         if (ACPI_FAILURE (Status))
    608         {
    609             return_ACPI_STATUS (Status);
    610         }
    611 
    612         /* All prefixes have been handled, and the name is in NameString */
    613 
    614         /*
    615          * Special handling for BufferField declarations.  This is a deferred
    616          * opcode that unfortunately defines the field name as the last
    617          * parameter instead of the first.  We get here when we are performing
    618          * the deferred execution, so the actual name of the field is already
    619          * in the namespace.  We don't want to attempt to look it up again
    620          * because we may be executing in a different scope than where the
    621          * actual opcode exists.
    622          */
    623         if ((WalkState->DeferredNode) &&
    624             (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
    625             (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
    626         {
    627             ObjDesc = ACPI_CAST_PTR (
    628                         ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
    629             Status = AE_OK;
    630         }
    631         else    /* All other opcodes */
    632         {
    633             /*
    634              * Differentiate between a namespace "create" operation
    635              * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
    636              * IMODE_EXECUTE) in order to support the creation of
    637              * namespace objects during the execution of control methods.
    638              */
    639             ParentOp = Arg->Common.Parent;
    640             OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
    641             if ((OpInfo->Flags & AML_NSNODE) &&
    642                 (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
    643                 (ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
    644                 (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
    645             {
    646                 /* Enter name into namespace if not found */
    647 
    648                 InterpreterMode = ACPI_IMODE_LOAD_PASS2;
    649             }
    650             else
    651             {
    652                 /* Return a failure if name not found */
    653 
    654                 InterpreterMode = ACPI_IMODE_EXECUTE;
    655             }
    656 
    657             Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
    658                         ACPI_TYPE_ANY, InterpreterMode,
    659                         ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
    660                         WalkState,
    661                         ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
    662             /*
    663              * The only case where we pass through (ignore) a NOT_FOUND
    664              * error is for the CondRefOf opcode.
    665              */
    666             if (Status == AE_NOT_FOUND)
    667             {
    668                 if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP)
    669                 {
    670                     /*
    671                      * For the Conditional Reference op, it's OK if
    672                      * the name is not found;  We just need a way to
    673                      * indicate this to the interpreter, set the
    674                      * object to the root
    675                      */
    676                     ObjDesc = ACPI_CAST_PTR (
    677                                 ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
    678                     Status = AE_OK;
    679                 }
    680                 else
    681                 {
    682                     /*
    683                      * We just plain didn't find it -- which is a
    684                      * very serious error at this point
    685                      */
    686                     Status = AE_AML_NAME_NOT_FOUND;
    687                 }
    688             }
    689 
    690             if (ACPI_FAILURE (Status))
    691             {
    692                 ACPI_ERROR_NAMESPACE (NameString, Status);
    693             }
    694         }
    695 
    696         /* Free the namestring created above */
    697 
    698         ACPI_FREE (NameString);
    699 
    700         /* Check status from the lookup */
    701 
    702         if (ACPI_FAILURE (Status))
    703         {
    704             return_ACPI_STATUS (Status);
    705         }
    706 
    707         /* Put the resulting object onto the current object stack */
    708 
    709         Status = AcpiDsObjStackPush (ObjDesc, WalkState);
    710         if (ACPI_FAILURE (Status))
    711         {
    712             return_ACPI_STATUS (Status);
    713         }
    714         ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
    715     }
    716     else
    717     {
    718         /* Check for null name case */
    719 
    720         if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
    721             !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
    722         {
    723             /*
    724              * If the name is null, this means that this is an
    725              * optional result parameter that was not specified
    726              * in the original ASL.  Create a Zero Constant for a
    727              * placeholder.  (Store to a constant is a Noop.)
    728              */
    729             Opcode = AML_ZERO_OP;       /* Has no arguments! */
    730 
    731             ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    732                 "Null namepath: Arg=%p\n", Arg));
    733         }
    734         else
    735         {
    736             Opcode = Arg->Common.AmlOpcode;
    737         }
    738 
    739         /* Get the object type of the argument */
    740 
    741         OpInfo = AcpiPsGetOpcodeInfo (Opcode);
    742         if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
    743         {
    744             return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
    745         }
    746 
    747         if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
    748         {
    749             ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    750                 "Argument previously created, already stacked\n"));
    751 
    752             ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (
    753                 WalkState->Operands [WalkState->NumOperands - 1], WalkState));
    754 
    755             /*
    756              * Use value that was already previously returned
    757              * by the evaluation of this argument
    758              */
    759             Status = AcpiDsResultPop (&ObjDesc, WalkState);
    760             if (ACPI_FAILURE (Status))
    761             {
    762                 /*
    763                  * Only error is underflow, and this indicates
    764                  * a missing or null operand!
    765                  */
    766                 ACPI_EXCEPTION ((AE_INFO, Status,
    767                     "Missing or null operand"));
    768                 return_ACPI_STATUS (Status);
    769             }
    770         }
    771         else
    772         {
    773             /* Create an ACPI_INTERNAL_OBJECT for the argument */
    774 
    775             ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
    776             if (!ObjDesc)
    777             {
    778                 return_ACPI_STATUS (AE_NO_MEMORY);
    779             }
    780 
    781             /* Initialize the new object */
    782 
    783             Status = AcpiDsInitObjectFromOp (
    784                         WalkState, Arg, Opcode, &ObjDesc);
    785             if (ACPI_FAILURE (Status))
    786             {
    787                 AcpiUtDeleteObjectDesc (ObjDesc);
    788                 return_ACPI_STATUS (Status);
    789             }
    790         }
    791 
    792         /* Put the operand object on the object stack */
    793 
    794         Status = AcpiDsObjStackPush (ObjDesc, WalkState);
    795         if (ACPI_FAILURE (Status))
    796         {
    797             return_ACPI_STATUS (Status);
    798         }
    799 
    800         ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
    801     }
    802 
    803     return_ACPI_STATUS (AE_OK);
    804 }
    805 
    806 
    807 /*******************************************************************************
    808  *
    809  * FUNCTION:    AcpiDsCreateOperands
    810  *
    811  * PARAMETERS:  WalkState           - Current state
    812  *              FirstArg            - First argument of a parser argument tree
    813  *
    814  * RETURN:      Status
    815  *
    816  * DESCRIPTION: Convert an operator's arguments from a parse tree format to
    817  *              namespace objects and place those argument object on the object
    818  *              stack in preparation for evaluation by the interpreter.
    819  *
    820  ******************************************************************************/
    821 
    822 ACPI_STATUS
    823 AcpiDsCreateOperands (
    824     ACPI_WALK_STATE         *WalkState,
    825     ACPI_PARSE_OBJECT       *FirstArg)
    826 {
    827     ACPI_STATUS             Status = AE_OK;
    828     ACPI_PARSE_OBJECT       *Arg;
    829     ACPI_PARSE_OBJECT       *Arguments[ACPI_OBJ_NUM_OPERANDS];
    830     UINT32                  ArgCount = 0;
    831     UINT32                  Index = WalkState->NumOperands;
    832     UINT32                  i;
    833 
    834 
    835     ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg);
    836 
    837 
    838     /* Get all arguments in the list */
    839 
    840     Arg = FirstArg;
    841     while (Arg)
    842     {
    843         if (Index >= ACPI_OBJ_NUM_OPERANDS)
    844         {
    845             return_ACPI_STATUS (AE_BAD_DATA);
    846         }
    847 
    848         Arguments[Index] = Arg;
    849         WalkState->Operands [Index] = NULL;
    850 
    851         /* Move on to next argument, if any */
    852 
    853         Arg = Arg->Common.Next;
    854         ArgCount++;
    855         Index++;
    856     }
    857 
    858     Index--;
    859 
    860     /* It is the appropriate order to get objects from the Result stack */
    861 
    862     for (i = 0; i < ArgCount; i++)
    863     {
    864         Arg = Arguments[Index];
    865 
    866         /* Force the filling of the operand stack in inverse order */
    867 
    868         WalkState->OperandIndex = (UINT8) Index;
    869 
    870         Status = AcpiDsCreateOperand (WalkState, Arg, Index);
    871         if (ACPI_FAILURE (Status))
    872         {
    873             goto Cleanup;
    874         }
    875 
    876         Index--;
    877 
    878         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%u (%p) done, Arg1=%p\n",
    879             Index, Arg, FirstArg));
    880     }
    881 
    882     return_ACPI_STATUS (Status);
    883 
    884 
    885 Cleanup:
    886     /*
    887      * We must undo everything done above; meaning that we must
    888      * pop everything off of the operand stack and delete those
    889      * objects
    890      */
    891     AcpiDsObjStackPopAndDelete (ArgCount, WalkState);
    892 
    893     ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index));
    894     return_ACPI_STATUS (Status);
    895 }
    896 
    897 
    898 /*****************************************************************************
    899  *
    900  * FUNCTION:    AcpiDsEvaluateNamePath
    901  *
    902  * PARAMETERS:  WalkState       - Current state of the parse tree walk,
    903  *                                the opcode of current operation should be
    904  *                                AML_INT_NAMEPATH_OP
    905  *
    906  * RETURN:      Status
    907  *
    908  * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent
    909  *              interpreter object, convert it to value, if needed, duplicate
    910  *              it, if needed, and push it onto the current result stack.
    911  *
    912  ****************************************************************************/
    913 
    914 ACPI_STATUS
    915 AcpiDsEvaluateNamePath (
    916     ACPI_WALK_STATE         *WalkState)
    917 {
    918     ACPI_STATUS             Status = AE_OK;
    919     ACPI_PARSE_OBJECT       *Op = WalkState->Op;
    920     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    921     ACPI_OPERAND_OBJECT     *NewObjDesc;
    922     UINT8                   Type;
    923 
    924 
    925     ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState);
    926 
    927 
    928     if (!Op->Common.Parent)
    929     {
    930         /* This happens after certain exception processing */
    931 
    932         goto Exit;
    933     }
    934 
    935     if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
    936         (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) ||
    937         (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP))
    938     {
    939         /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */
    940 
    941         goto Exit;
    942     }
    943 
    944     Status = AcpiDsCreateOperand (WalkState, Op, 0);
    945     if (ACPI_FAILURE (Status))
    946     {
    947         goto Exit;
    948     }
    949 
    950     if (Op->Common.Flags & ACPI_PARSEOP_TARGET)
    951     {
    952         NewObjDesc = *Operand;
    953         goto PushResult;
    954     }
    955 
    956     Type = (*Operand)->Common.Type;
    957 
    958     Status = AcpiExResolveToValue (Operand, WalkState);
    959     if (ACPI_FAILURE (Status))
    960     {
    961         goto Exit;
    962     }
    963 
    964     if (Type == ACPI_TYPE_INTEGER)
    965     {
    966         /* It was incremented by AcpiExResolveToValue */
    967 
    968         AcpiUtRemoveReference (*Operand);
    969 
    970         Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState);
    971         if (ACPI_FAILURE (Status))
    972         {
    973             goto Exit;
    974         }
    975     }
    976     else
    977     {
    978         /*
    979          * The object either was anew created or is
    980          * a Namespace node - don't decrement it.
    981          */
    982         NewObjDesc = *Operand;
    983     }
    984 
    985     /* Cleanup for name-path operand */
    986 
    987     Status = AcpiDsObjStackPop (1, WalkState);
    988     if (ACPI_FAILURE (Status))
    989     {
    990         WalkState->ResultObj = NewObjDesc;
    991         goto Exit;
    992     }
    993 
    994 PushResult:
    995 
    996     WalkState->ResultObj = NewObjDesc;
    997 
    998     Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
    999     if (ACPI_SUCCESS (Status))
   1000     {
   1001         /* Force to take it from stack */
   1002 
   1003         Op->Common.Flags |= ACPI_PARSEOP_IN_STACK;
   1004     }
   1005 
   1006 Exit:
   1007 
   1008     return_ACPI_STATUS (Status);
   1009 }
   1010