Home | History | Annotate | Line # | Download | only in dispatcher
      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 - 2025, 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  * Alternatively, you may choose to be licensed under the terms of the
    117  * following license:
    118  *
    119  * Redistribution and use in source and binary forms, with or without
    120  * modification, are permitted provided that the following conditions
    121  * are met:
    122  * 1. Redistributions of source code must retain the above copyright
    123  *    notice, this list of conditions, and the following disclaimer,
    124  *    without modification.
    125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
    126  *    substantially similar to the "NO WARRANTY" disclaimer below
    127  *    ("Disclaimer") and any redistribution must be conditioned upon
    128  *    including a substantially similar Disclaimer requirement for further
    129  *    binary redistribution.
    130  * 3. Neither the names of the above-listed copyright holders nor the names
    131  *    of any contributors may be used to endorse or promote products derived
    132  *    from this software without specific prior written permission.
    133  *
    134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    145  *
    146  * Alternatively, you may choose to be licensed under the terms of the
    147  * GNU General Public License ("GPL") version 2 as published by the Free
    148  * Software Foundation.
    149  *
    150  *****************************************************************************/
    151 
    152 #include "acpi.h"
    153 #include "accommon.h"
    154 #include "acparser.h"
    155 #include "amlcode.h"
    156 #include "acdispat.h"
    157 #include "acinterp.h"
    158 #include "acnamesp.h"
    159 #include "acdebug.h"
    160 
    161 #define _COMPONENT          ACPI_DISPATCHER
    162         ACPI_MODULE_NAME    ("dsutils")
    163 
    164 
    165 /*******************************************************************************
    166  *
    167  * FUNCTION:    AcpiDsClearImplicitReturn
    168  *
    169  * PARAMETERS:  WalkState           - Current State
    170  *
    171  * RETURN:      None.
    172  *
    173  * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
    174  *              to delete "stale" return values (if enabled, the return value
    175  *              from every operator is saved at least momentarily, in case the
    176  *              parent method exits.)
    177  *
    178  ******************************************************************************/
    179 
    180 void
    181 AcpiDsClearImplicitReturn (
    182     ACPI_WALK_STATE         *WalkState)
    183 {
    184     ACPI_FUNCTION_NAME (DsClearImplicitReturn);
    185 
    186 
    187     /*
    188      * Slack must be enabled for this feature
    189      */
    190     if (!AcpiGbl_EnableInterpreterSlack)
    191     {
    192         return;
    193     }
    194 
    195     if (WalkState->ImplicitReturnObj)
    196     {
    197         /*
    198          * Delete any "stale" implicit return. However, in
    199          * complex statements, the implicit return value can be
    200          * bubbled up several levels.
    201          */
    202         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    203             "Removing reference on stale implicit return obj %p\n",
    204             WalkState->ImplicitReturnObj));
    205 
    206         AcpiUtRemoveReference (WalkState->ImplicitReturnObj);
    207         WalkState->ImplicitReturnObj = NULL;
    208     }
    209 }
    210 
    211 
    212 /*******************************************************************************
    213  *
    214  * FUNCTION:    AcpiDsDoImplicitReturn
    215  *
    216  * PARAMETERS:  ReturnDesc          - The return value
    217  *              WalkState           - Current State
    218  *              AddReference        - True if a reference should be added to the
    219  *                                    return object
    220  *
    221  * RETURN:      TRUE if implicit return enabled, FALSE otherwise
    222  *
    223  * DESCRIPTION: Implements the optional "implicit return".  We save the result
    224  *              of every ASL operator and control method invocation in case the
    225  *              parent method exit. Before storing a new return value, we
    226  *              delete the previous return value.
    227  *
    228  ******************************************************************************/
    229 
    230 BOOLEAN
    231 AcpiDsDoImplicitReturn (
    232     ACPI_OPERAND_OBJECT     *ReturnDesc,
    233     ACPI_WALK_STATE         *WalkState,
    234     BOOLEAN                 AddReference)
    235 {
    236     ACPI_FUNCTION_NAME (DsDoImplicitReturn);
    237 
    238 
    239     /*
    240      * Slack must be enabled for this feature, and we must
    241      * have a valid return object
    242      */
    243     if ((!AcpiGbl_EnableInterpreterSlack) ||
    244         (!ReturnDesc))
    245     {
    246         return (FALSE);
    247     }
    248 
    249     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    250         "Result %p will be implicitly returned; Prev=%p\n",
    251         ReturnDesc,
    252         WalkState->ImplicitReturnObj));
    253 
    254     /*
    255      * Delete any "stale" implicit return value first. However, in
    256      * complex statements, the implicit return value can be
    257      * bubbled up several levels, so we don't clear the value if it
    258      * is the same as the ReturnDesc.
    259      */
    260     if (WalkState->ImplicitReturnObj)
    261     {
    262         if (WalkState->ImplicitReturnObj == ReturnDesc)
    263         {
    264             return (TRUE);
    265         }
    266         AcpiDsClearImplicitReturn (WalkState);
    267     }
    268 
    269     /* Save the implicit return value, add a reference if requested */
    270 
    271     WalkState->ImplicitReturnObj = ReturnDesc;
    272     if (AddReference)
    273     {
    274         AcpiUtAddReference (ReturnDesc);
    275     }
    276 
    277     return (TRUE);
    278 }
    279 
    280 
    281 /*******************************************************************************
    282  *
    283  * FUNCTION:    AcpiDsIsResultUsed
    284  *
    285  * PARAMETERS:  Op                  - Current Op
    286  *              WalkState           - Current State
    287  *
    288  * RETURN:      TRUE if result is used, FALSE otherwise
    289  *
    290  * DESCRIPTION: Check if a result object will be used by the parent
    291  *
    292  ******************************************************************************/
    293 
    294 BOOLEAN
    295 AcpiDsIsResultUsed (
    296     ACPI_PARSE_OBJECT       *Op,
    297     ACPI_WALK_STATE         *WalkState)
    298 {
    299     const ACPI_OPCODE_INFO  *ParentInfo;
    300 
    301     ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op);
    302 
    303 
    304     /* Must have both an Op and a Result Object */
    305 
    306     if (!Op)
    307     {
    308         ACPI_ERROR ((AE_INFO, "Null Op"));
    309         return_UINT8 (TRUE);
    310     }
    311 
    312     /*
    313      * We know that this operator is not a
    314      * Return() operator (would not come here.) The following code is the
    315      * optional support for a so-called "implicit return". Some AML code
    316      * assumes that the last value of the method is "implicitly" returned
    317      * to the caller. Just save the last result as the return value.
    318      * NOTE: this is optional because the ASL language does not actually
    319      * support this behavior.
    320      */
    321     (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE);
    322 
    323     /*
    324      * Now determine if the parent will use the result
    325      *
    326      * If there is no parent, or the parent is a ScopeOp, we are executing
    327      * at the method level. An executing method typically has no parent,
    328      * since each method is parsed separately. A method invoked externally
    329      * via ExecuteControlMethod has a ScopeOp as the parent.
    330      */
    331     if ((!Op->Common.Parent) ||
    332         (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
    333     {
    334         /* No parent, the return value cannot possibly be used */
    335 
    336         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    337             "At Method level, result of [%s] not used\n",
    338             AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
    339         return_UINT8 (FALSE);
    340     }
    341 
    342     /* Get info on the parent. The RootOp is AML_SCOPE */
    343 
    344     ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
    345     if (ParentInfo->Class == AML_CLASS_UNKNOWN)
    346     {
    347         ACPI_ERROR ((AE_INFO,
    348             "Unknown parent opcode Op=%p", Op));
    349         return_UINT8 (FALSE);
    350     }
    351 
    352     /*
    353      * Decide what to do with the result based on the parent. If
    354      * the parent opcode will not use the result, delete the object.
    355      * Otherwise leave it as is, it will be deleted when it is used
    356      * as an operand later.
    357      */
    358     switch (ParentInfo->Class)
    359     {
    360     case AML_CLASS_CONTROL:
    361 
    362         switch (Op->Common.Parent->Common.AmlOpcode)
    363         {
    364         case AML_RETURN_OP:
    365 
    366             /* Never delete the return value associated with a return opcode */
    367 
    368             goto ResultUsed;
    369 
    370         case AML_IF_OP:
    371         case AML_WHILE_OP:
    372             /*
    373              * If we are executing the predicate AND this is the predicate op,
    374              * we will use the return value
    375              */
    376             if ((WalkState->ControlState->Common.State ==
    377                     ACPI_CONTROL_PREDICATE_EXECUTING) &&
    378                 (WalkState->ControlState->Control.PredicateOp == Op))
    379             {
    380                 goto ResultUsed;
    381             }
    382             break;
    383 
    384         default:
    385 
    386             /* Ignore other control opcodes */
    387 
    388             break;
    389         }
    390 
    391         /* The general control opcode returns no result */
    392 
    393         goto ResultNotUsed;
    394 
    395     case AML_CLASS_CREATE:
    396         /*
    397          * These opcodes allow TermArg(s) as operands and therefore
    398          * the operands can be method calls. The result is used.
    399          */
    400         goto ResultUsed;
    401 
    402     case AML_CLASS_NAMED_OBJECT:
    403 
    404         if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
    405             (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
    406             (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
    407             (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
    408             (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP) ||
    409             (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) ||
    410             (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP))
    411         {
    412             /*
    413              * These opcodes allow TermArg(s) as operands and therefore
    414              * the operands can be method calls. The result is used.
    415              */
    416             goto ResultUsed;
    417         }
    418 
    419         goto ResultNotUsed;
    420 
    421     default:
    422         /*
    423          * In all other cases. the parent will actually use the return
    424          * object, so keep it.
    425          */
    426         goto ResultUsed;
    427     }
    428 
    429 
    430 ResultUsed:
    431     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    432         "Result of [%s] used by Parent [%s] Op=%p\n",
    433         AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
    434         AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
    435 
    436     return_UINT8 (TRUE);
    437 
    438 
    439 ResultNotUsed:
    440     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    441         "Result of [%s] not used by Parent [%s] Op=%p\n",
    442         AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
    443         AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
    444 
    445     return_UINT8 (FALSE);
    446 }
    447 
    448 
    449 /*******************************************************************************
    450  *
    451  * FUNCTION:    AcpiDsDeleteResultIfNotUsed
    452  *
    453  * PARAMETERS:  Op              - Current parse Op
    454  *              ResultObj       - Result of the operation
    455  *              WalkState       - Current state
    456  *
    457  * RETURN:      Status
    458  *
    459  * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
    460  *              result descriptor, check if the parent opcode will actually use
    461  *              this result. If not, delete the result now so that it will
    462  *              not become orphaned.
    463  *
    464  ******************************************************************************/
    465 
    466 void
    467 AcpiDsDeleteResultIfNotUsed (
    468     ACPI_PARSE_OBJECT       *Op,
    469     ACPI_OPERAND_OBJECT     *ResultObj,
    470     ACPI_WALK_STATE         *WalkState)
    471 {
    472     ACPI_OPERAND_OBJECT     *ObjDesc;
    473     ACPI_STATUS             Status;
    474 
    475 
    476     ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj);
    477 
    478 
    479     if (!Op)
    480     {
    481         ACPI_ERROR ((AE_INFO, "Null Op"));
    482         return_VOID;
    483     }
    484 
    485     if (!ResultObj)
    486     {
    487         return_VOID;
    488     }
    489 
    490     if (!AcpiDsIsResultUsed (Op, WalkState))
    491     {
    492         /* Must pop the result stack (ObjDesc should be equal to ResultObj) */
    493 
    494         Status = AcpiDsResultPop (&ObjDesc, WalkState);
    495         if (ACPI_SUCCESS (Status))
    496         {
    497             AcpiUtRemoveReference (ResultObj);
    498         }
    499     }
    500 
    501     return_VOID;
    502 }
    503 
    504 
    505 /*******************************************************************************
    506  *
    507  * FUNCTION:    AcpiDsResolveOperands
    508  *
    509  * PARAMETERS:  WalkState           - Current walk state with operands on stack
    510  *
    511  * RETURN:      Status
    512  *
    513  * DESCRIPTION: Resolve all operands to their values. Used to prepare
    514  *              arguments to a control method invocation (a call from one
    515  *              method to another.)
    516  *
    517  ******************************************************************************/
    518 
    519 ACPI_STATUS
    520 AcpiDsResolveOperands (
    521     ACPI_WALK_STATE         *WalkState)
    522 {
    523     UINT32                  i;
    524     ACPI_STATUS             Status = AE_OK;
    525 
    526 
    527     ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState);
    528 
    529 
    530     /*
    531      * Attempt to resolve each of the valid operands
    532      * Method arguments are passed by reference, not by value. This means
    533      * that the actual objects are passed, not copies of the objects.
    534      */
    535     for (i = 0; i < WalkState->NumOperands; i++)
    536     {
    537         Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState);
    538         if (ACPI_FAILURE (Status))
    539         {
    540             break;
    541         }
    542     }
    543 
    544     return_ACPI_STATUS (Status);
    545 }
    546 
    547 
    548 /*******************************************************************************
    549  *
    550  * FUNCTION:    AcpiDsClearOperands
    551  *
    552  * PARAMETERS:  WalkState           - Current walk state with operands on stack
    553  *
    554  * RETURN:      None
    555  *
    556  * DESCRIPTION: Clear all operands on the current walk state operand stack.
    557  *
    558  ******************************************************************************/
    559 
    560 void
    561 AcpiDsClearOperands (
    562     ACPI_WALK_STATE         *WalkState)
    563 {
    564     UINT32                  i;
    565 
    566 
    567     ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState);
    568 
    569 
    570     /* Remove a reference on each operand on the stack */
    571 
    572     for (i = 0; i < WalkState->NumOperands; i++)
    573     {
    574         /*
    575          * Remove a reference to all operands, including both
    576          * "Arguments" and "Targets".
    577          */
    578         AcpiUtRemoveReference (WalkState->Operands[i]);
    579         WalkState->Operands[i] = NULL;
    580     }
    581 
    582     WalkState->NumOperands = 0;
    583     return_VOID;
    584 }
    585 
    586 
    587 /*******************************************************************************
    588  *
    589  * FUNCTION:    AcpiDsCreateOperand
    590  *
    591  * PARAMETERS:  WalkState       - Current walk state
    592  *              Arg             - Parse object for the argument
    593  *              ArgIndex        - Which argument (zero based)
    594  *
    595  * RETURN:      Status
    596  *
    597  * DESCRIPTION: Translate a parse tree object that is an argument to an AML
    598  *              opcode to the equivalent interpreter object. This may include
    599  *              looking up a name or entering a new name into the internal
    600  *              namespace.
    601  *
    602  ******************************************************************************/
    603 
    604 ACPI_STATUS
    605 AcpiDsCreateOperand (
    606     ACPI_WALK_STATE         *WalkState,
    607     ACPI_PARSE_OBJECT       *Arg,
    608     UINT32                  ArgIndex)
    609 {
    610     ACPI_STATUS             Status = AE_OK;
    611     char                    *NameString;
    612     UINT32                  NameLength;
    613     ACPI_OPERAND_OBJECT     *ObjDesc;
    614     ACPI_PARSE_OBJECT       *ParentOp;
    615     UINT16                  Opcode;
    616     ACPI_INTERPRETER_MODE   InterpreterMode;
    617     const ACPI_OPCODE_INFO  *OpInfo;
    618 
    619 
    620     ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);
    621 
    622 
    623     /* A valid name must be looked up in the namespace */
    624 
    625     if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
    626         (Arg->Common.Value.String) &&
    627         !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
    628     {
    629         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));
    630 
    631         /* Get the entire name string from the AML stream */
    632 
    633         Status = AcpiExGetNameString (ACPI_TYPE_ANY,
    634             Arg->Common.Value.Buffer, &NameString, &NameLength);
    635 
    636         if (ACPI_FAILURE (Status))
    637         {
    638             return_ACPI_STATUS (Status);
    639         }
    640 
    641         /* All prefixes have been handled, and the name is in NameString */
    642 
    643         /*
    644          * Special handling for BufferField declarations. This is a deferred
    645          * opcode that unfortunately defines the field name as the last
    646          * parameter instead of the first. We get here when we are performing
    647          * the deferred execution, so the actual name of the field is already
    648          * in the namespace. We don't want to attempt to look it up again
    649          * because we may be executing in a different scope than where the
    650          * actual opcode exists.
    651          */
    652         if ((WalkState->DeferredNode) &&
    653             (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
    654             (ArgIndex == (UINT32)
    655                 ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
    656         {
    657             ObjDesc = ACPI_CAST_PTR (
    658                 ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
    659             Status = AE_OK;
    660         }
    661         else    /* All other opcodes */
    662         {
    663             /*
    664              * Differentiate between a namespace "create" operation
    665              * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
    666              * IMODE_EXECUTE) in order to support the creation of
    667              * namespace objects during the execution of control methods.
    668              */
    669             ParentOp = Arg->Common.Parent;
    670             OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
    671 
    672             if ((OpInfo->Flags & AML_NSNODE) &&
    673                 (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
    674                 (ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
    675                 (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
    676             {
    677                 /* Enter name into namespace if not found */
    678 
    679                 InterpreterMode = ACPI_IMODE_LOAD_PASS2;
    680             }
    681             else
    682             {
    683                 /* Return a failure if name not found */
    684 
    685                 InterpreterMode = ACPI_IMODE_EXECUTE;
    686             }
    687 
    688             Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
    689                 ACPI_TYPE_ANY, InterpreterMode,
    690                 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, WalkState,
    691                 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
    692             /*
    693              * The only case where we pass through (ignore) a NOT_FOUND
    694              * error is for the CondRefOf opcode.
    695              */
    696             if (Status == AE_NOT_FOUND)
    697             {
    698                 if (ParentOp->Common.AmlOpcode == AML_CONDITIONAL_REF_OF_OP)
    699                 {
    700                     /*
    701                      * For the Conditional Reference op, it's OK if
    702                      * the name is not found;  We just need a way to
    703                      * indicate this to the interpreter, set the
    704                      * object to the root
    705                      */
    706                     ObjDesc = ACPI_CAST_PTR (
    707                         ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
    708                     Status = AE_OK;
    709                 }
    710                 else if (ParentOp->Common.AmlOpcode == AML_EXTERNAL_OP)
    711                 {
    712                     /*
    713                      * This opcode should never appear here. It is used only
    714                      * by AML disassemblers and is surrounded by an If(0)
    715                      * by the ASL compiler.
    716                      *
    717                      * Therefore, if we see it here, it is a serious error.
    718                      */
    719                     Status = AE_AML_BAD_OPCODE;
    720                 }
    721                 else
    722                 {
    723                     /*
    724                      * We just plain didn't find it -- which is a
    725                      * very serious error at this point
    726                      */
    727                     Status = AE_AML_NAME_NOT_FOUND;
    728                 }
    729             }
    730 
    731             if (ACPI_FAILURE (Status))
    732             {
    733                 ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
    734                     NameString, Status);
    735             }
    736         }
    737 
    738         /* Free the namestring created above */
    739 
    740         ACPI_FREE (NameString);
    741 
    742         /* Check status from the lookup */
    743 
    744         if (ACPI_FAILURE (Status))
    745         {
    746             return_ACPI_STATUS (Status);
    747         }
    748 
    749         /* Put the resulting object onto the current object stack */
    750 
    751         Status = AcpiDsObjStackPush (ObjDesc, WalkState);
    752         if (ACPI_FAILURE (Status))
    753         {
    754             return_ACPI_STATUS (Status);
    755         }
    756 
    757         AcpiDbDisplayArgumentObject (ObjDesc, WalkState);
    758     }
    759     else
    760     {
    761         /* Check for null name case */
    762 
    763         if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
    764             !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
    765         {
    766             /*
    767              * If the name is null, this means that this is an
    768              * optional result parameter that was not specified
    769              * in the original ASL. Create a Zero Constant for a
    770              * placeholder. (Store to a constant is a Noop.)
    771              */
    772             Opcode = AML_ZERO_OP;       /* Has no arguments! */
    773 
    774             ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    775                 "Null namepath: Arg=%p\n", Arg));
    776         }
    777         else
    778         {
    779             Opcode = Arg->Common.AmlOpcode;
    780         }
    781 
    782         /* Get the object type of the argument */
    783 
    784         OpInfo = AcpiPsGetOpcodeInfo (Opcode);
    785         if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
    786         {
    787             return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
    788         }
    789 
    790         if ((OpInfo->Flags & AML_HAS_RETVAL) ||
    791             (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
    792         {
    793             /*
    794              * Use value that was already previously returned
    795              * by the evaluation of this argument
    796              */
    797             Status = AcpiDsResultPop (&ObjDesc, WalkState);
    798             if (ACPI_FAILURE (Status))
    799             {
    800                 /*
    801                  * Only error is underflow, and this indicates
    802                  * a missing or null operand!
    803                  */
    804                 ACPI_EXCEPTION ((AE_INFO, Status,
    805                     "Missing or null operand"));
    806                 return_ACPI_STATUS (Status);
    807             }
    808         }
    809         else
    810         {
    811             /* Create an ACPI_INTERNAL_OBJECT for the argument */
    812 
    813             ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
    814             if (!ObjDesc)
    815             {
    816                 return_ACPI_STATUS (AE_NO_MEMORY);
    817             }
    818 
    819             /* Initialize the new object */
    820 
    821             Status = AcpiDsInitObjectFromOp (
    822                 WalkState, Arg, Opcode, &ObjDesc);
    823             if (ACPI_FAILURE (Status))
    824             {
    825                 AcpiUtDeleteObjectDesc (ObjDesc);
    826                 return_ACPI_STATUS (Status);
    827             }
    828         }
    829 
    830         /* Put the operand object on the object stack */
    831 
    832         Status = AcpiDsObjStackPush (ObjDesc, WalkState);
    833         if (ACPI_FAILURE (Status))
    834         {
    835             return_ACPI_STATUS (Status);
    836         }
    837 
    838         AcpiDbDisplayArgumentObject (ObjDesc, WalkState);
    839     }
    840 
    841     return_ACPI_STATUS (AE_OK);
    842 }
    843 
    844 
    845 /*******************************************************************************
    846  *
    847  * FUNCTION:    AcpiDsCreateOperands
    848  *
    849  * PARAMETERS:  WalkState           - Current state
    850  *              FirstArg            - First argument of a parser argument tree
    851  *
    852  * RETURN:      Status
    853  *
    854  * DESCRIPTION: Convert an operator's arguments from a parse tree format to
    855  *              namespace objects and place those argument object on the object
    856  *              stack in preparation for evaluation by the interpreter.
    857  *
    858  ******************************************************************************/
    859 
    860 ACPI_STATUS
    861 AcpiDsCreateOperands (
    862     ACPI_WALK_STATE         *WalkState,
    863     ACPI_PARSE_OBJECT       *FirstArg)
    864 {
    865     ACPI_STATUS             Status = AE_OK;
    866     ACPI_PARSE_OBJECT       *Arg;
    867     ACPI_PARSE_OBJECT       *Arguments[ACPI_OBJ_NUM_OPERANDS];
    868     UINT32                  ArgCount = 0;
    869     UINT32                  Index = WalkState->NumOperands;
    870     UINT32                  PrevNumOperands = WalkState->NumOperands;
    871     UINT32                  NewNumOperands;
    872     UINT32                  i;
    873 
    874 
    875     ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg);
    876 
    877 
    878     /* Get all arguments in the list */
    879 
    880     Arg = FirstArg;
    881     while (Arg)
    882     {
    883         if (Index >= ACPI_OBJ_NUM_OPERANDS)
    884         {
    885             return_ACPI_STATUS (AE_BAD_DATA);
    886         }
    887 
    888         Arguments[Index] = Arg;
    889         WalkState->Operands [Index] = NULL;
    890 
    891         /* Move on to next argument, if any */
    892 
    893         Arg = Arg->Common.Next;
    894         ArgCount++;
    895         Index++;
    896     }
    897 
    898     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    899         "NumOperands %d, ArgCount %d, Index %d\n",
    900         WalkState->NumOperands, ArgCount, Index));
    901 
    902     /* Create the interpreter arguments, in reverse order */
    903 
    904     NewNumOperands = Index;
    905     Index--;
    906     for (i = 0; i < ArgCount; i++)
    907     {
    908         Arg = Arguments[Index];
    909         WalkState->OperandIndex = (UINT8) Index;
    910 
    911         Status = AcpiDsCreateOperand (WalkState, Arg, Index);
    912         if (ACPI_FAILURE (Status))
    913         {
    914             goto Cleanup;
    915         }
    916 
    917         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    918             "Created Arg #%u (%p) %u args total\n",
    919             Index, Arg, ArgCount));
    920         Index--;
    921     }
    922 
    923     return_ACPI_STATUS (Status);
    924 
    925 
    926 Cleanup:
    927     /*
    928      * We must undo everything done above; meaning that we must
    929      * pop everything off of the operand stack and delete those
    930      * objects
    931      */
    932     WalkState->NumOperands = (UINT8) (i);
    933     AcpiDsObjStackPopAndDelete (NewNumOperands, WalkState);
    934 
    935     /* Restore operand count */
    936     WalkState->NumOperands = (UINT8) (PrevNumOperands);
    937 
    938     ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index));
    939     return_ACPI_STATUS (Status);
    940 }
    941 
    942 
    943 /*****************************************************************************
    944  *
    945  * FUNCTION:    AcpiDsEvaluateNamePath
    946  *
    947  * PARAMETERS:  WalkState       - Current state of the parse tree walk,
    948  *                                the opcode of current operation should be
    949  *                                AML_INT_NAMEPATH_OP
    950  *
    951  * RETURN:      Status
    952  *
    953  * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent
    954  *              interpreter object, convert it to value, if needed, duplicate
    955  *              it, if needed, and push it onto the current result stack.
    956  *
    957  ****************************************************************************/
    958 
    959 ACPI_STATUS
    960 AcpiDsEvaluateNamePath (
    961     ACPI_WALK_STATE         *WalkState)
    962 {
    963     ACPI_STATUS             Status = AE_OK;
    964     ACPI_PARSE_OBJECT       *Op = WalkState->Op;
    965     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    966     ACPI_OPERAND_OBJECT     *NewObjDesc;
    967     UINT8                   Type;
    968 
    969 
    970     ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState);
    971 
    972 
    973     if (!Op->Common.Parent)
    974     {
    975         /* This happens after certain exception processing */
    976 
    977         goto Exit;
    978     }
    979 
    980     if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
    981         (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP) ||
    982         (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP))
    983     {
    984         /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */
    985 
    986         goto Exit;
    987     }
    988 
    989     Status = AcpiDsCreateOperand (WalkState, Op, 0);
    990     if (ACPI_FAILURE (Status))
    991     {
    992         goto Exit;
    993     }
    994 
    995     if (Op->Common.Flags & ACPI_PARSEOP_TARGET)
    996     {
    997         NewObjDesc = *Operand;
    998         goto PushResult;
    999     }
   1000 
   1001     Type = (*Operand)->Common.Type;
   1002 
   1003     Status = AcpiExResolveToValue (Operand, WalkState);
   1004     if (ACPI_FAILURE (Status))
   1005     {
   1006         goto Exit;
   1007     }
   1008 
   1009     if (Type == ACPI_TYPE_INTEGER)
   1010     {
   1011         /* It was incremented by AcpiExResolveToValue */
   1012 
   1013         AcpiUtRemoveReference (*Operand);
   1014 
   1015         Status = AcpiUtCopyIobjectToIobject (
   1016             *Operand, &NewObjDesc, WalkState);
   1017         if (ACPI_FAILURE (Status))
   1018         {
   1019             goto Exit;
   1020         }
   1021     }
   1022     else
   1023     {
   1024         /*
   1025          * The object either was anew created or is
   1026          * a Namespace node - don't decrement it.
   1027          */
   1028         NewObjDesc = *Operand;
   1029     }
   1030 
   1031     /* Cleanup for name-path operand */
   1032 
   1033     Status = AcpiDsObjStackPop (1, WalkState);
   1034     if (ACPI_FAILURE (Status))
   1035     {
   1036         WalkState->ResultObj = NewObjDesc;
   1037         goto Exit;
   1038     }
   1039 
   1040 PushResult:
   1041 
   1042     WalkState->ResultObj = NewObjDesc;
   1043 
   1044     Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
   1045     if (ACPI_SUCCESS (Status))
   1046     {
   1047         /* Force to take it from stack */
   1048 
   1049         Op->Common.Flags |= ACPI_PARSEOP_IN_STACK;
   1050     }
   1051 
   1052 Exit:
   1053 
   1054     return_ACPI_STATUS (Status);
   1055 }
   1056