Home | History | Annotate | Line # | Download | only in dispatcher
      1 /*******************************************************************************
      2  *
      3  * Module Name: dsmthdat - control method arguments and local variables
      4  *
      5  ******************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2025, 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 MERCHANTABILITY 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 "acdispat.h"
     47 #include "acnamesp.h"
     48 #include "acinterp.h"
     49 
     50 
     51 #define _COMPONENT          ACPI_DISPATCHER
     52         ACPI_MODULE_NAME    ("dsmthdat")
     53 
     54 /* Local prototypes */
     55 
     56 static void
     57 AcpiDsMethodDataDeleteValue (
     58     UINT8                   Type,
     59     UINT32                  Index,
     60     ACPI_WALK_STATE         *WalkState);
     61 
     62 static ACPI_STATUS
     63 AcpiDsMethodDataSetValue (
     64     UINT8                   Type,
     65     UINT32                  Index,
     66     ACPI_OPERAND_OBJECT     *Object,
     67     ACPI_WALK_STATE         *WalkState);
     68 
     69 #ifdef ACPI_OBSOLETE_FUNCTIONS
     70 ACPI_OBJECT_TYPE
     71 AcpiDsMethodDataGetType (
     72     UINT16                  Opcode,
     73     UINT32                  Index,
     74     ACPI_WALK_STATE         *WalkState);
     75 #endif
     76 
     77 
     78 /*******************************************************************************
     79  *
     80  * FUNCTION:    AcpiDsMethodDataInit
     81  *
     82  * PARAMETERS:  WalkState           - Current walk state object
     83  *
     84  * RETURN:      Status
     85  *
     86  * DESCRIPTION: Initialize the data structures that hold the method's arguments
     87  *              and locals. The data struct is an array of namespace nodes for
     88  *              each - this allows RefOf and DeRefOf to work properly for these
     89  *              special data types.
     90  *
     91  * NOTES:       WalkState fields are initialized to zero by the
     92  *              ACPI_ALLOCATE_ZEROED().
     93  *
     94  *              A pseudo-Namespace Node is assigned to each argument and local
     95  *              so that RefOf() can return a pointer to the Node.
     96  *
     97  ******************************************************************************/
     98 
     99 void
    100 AcpiDsMethodDataInit (
    101     ACPI_WALK_STATE         *WalkState)
    102 {
    103     UINT32                  i;
    104 
    105 
    106     ACPI_FUNCTION_TRACE (DsMethodDataInit);
    107 
    108 
    109     /* Init the method arguments */
    110 
    111     for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
    112     {
    113         ACPI_MOVE_32_TO_32 (&WalkState->Arguments[i].Name,
    114             NAMEOF_ARG_NTE);
    115 
    116         WalkState->Arguments[i].Name.Integer |= (i << 24);
    117         WalkState->Arguments[i].DescriptorType = ACPI_DESC_TYPE_NAMED;
    118         WalkState->Arguments[i].Type = ACPI_TYPE_ANY;
    119         WalkState->Arguments[i].Flags = ANOBJ_METHOD_ARG;
    120     }
    121 
    122     /* Init the method locals */
    123 
    124     for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++)
    125     {
    126         ACPI_MOVE_32_TO_32 (&WalkState->LocalVariables[i].Name,
    127             NAMEOF_LOCAL_NTE);
    128 
    129         WalkState->LocalVariables[i].Name.Integer |= (i << 24);
    130         WalkState->LocalVariables[i].DescriptorType = ACPI_DESC_TYPE_NAMED;
    131         WalkState->LocalVariables[i].Type = ACPI_TYPE_ANY;
    132         WalkState->LocalVariables[i].Flags = ANOBJ_METHOD_LOCAL;
    133     }
    134 
    135     return_VOID;
    136 }
    137 
    138 
    139 /*******************************************************************************
    140  *
    141  * FUNCTION:    AcpiDsMethodDataDeleteAll
    142  *
    143  * PARAMETERS:  WalkState           - Current walk state object
    144  *
    145  * RETURN:      None
    146  *
    147  * DESCRIPTION: Delete method locals and arguments. Arguments are only
    148  *              deleted if this method was called from another method.
    149  *
    150  ******************************************************************************/
    151 
    152 void
    153 AcpiDsMethodDataDeleteAll (
    154     ACPI_WALK_STATE         *WalkState)
    155 {
    156     UINT32                  Index;
    157 
    158 
    159     ACPI_FUNCTION_TRACE (DsMethodDataDeleteAll);
    160 
    161 
    162     /* Detach the locals */
    163 
    164     for (Index = 0; Index < ACPI_METHOD_NUM_LOCALS; Index++)
    165     {
    166         if (WalkState->LocalVariables[Index].Object)
    167         {
    168             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Local%u=%p\n",
    169                 Index, WalkState->LocalVariables[Index].Object));
    170 
    171             /* Detach object (if present) and remove a reference */
    172 
    173             AcpiNsDetachObject (&WalkState->LocalVariables[Index]);
    174         }
    175     }
    176 
    177     /* Detach the arguments */
    178 
    179     for (Index = 0; Index < ACPI_METHOD_NUM_ARGS; Index++)
    180     {
    181         if (WalkState->Arguments[Index].Object)
    182         {
    183             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Arg%u=%p\n",
    184                 Index, WalkState->Arguments[Index].Object));
    185 
    186             /* Detach object (if present) and remove a reference */
    187 
    188             AcpiNsDetachObject (&WalkState->Arguments[Index]);
    189         }
    190     }
    191 
    192     return_VOID;
    193 }
    194 
    195 
    196 /*******************************************************************************
    197  *
    198  * FUNCTION:    AcpiDsMethodDataInitArgs
    199  *
    200  * PARAMETERS:  *Params         - Pointer to a parameter list for the method
    201  *              MaxParamCount   - The arg count for this method
    202  *              WalkState       - Current walk state object
    203  *
    204  * RETURN:      Status
    205  *
    206  * DESCRIPTION: Initialize arguments for a method. The parameter list is a list
    207  *              of ACPI operand objects, either null terminated or whose length
    208  *              is defined by MaxParamCount.
    209  *
    210  ******************************************************************************/
    211 
    212 ACPI_STATUS
    213 AcpiDsMethodDataInitArgs (
    214     ACPI_OPERAND_OBJECT     **Params,
    215     UINT32                  MaxParamCount,
    216     ACPI_WALK_STATE         *WalkState)
    217 {
    218     ACPI_STATUS             Status;
    219     UINT32                  Index = 0;
    220 
    221 
    222     ACPI_FUNCTION_TRACE_PTR (DsMethodDataInitArgs, Params);
    223 
    224 
    225     if (!Params)
    226     {
    227         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    228             "No parameter list passed to method\n"));
    229         return_ACPI_STATUS (AE_OK);
    230     }
    231 
    232     /* Copy passed parameters into the new method stack frame */
    233 
    234     while ((Index < ACPI_METHOD_NUM_ARGS) &&
    235            (Index < MaxParamCount)        &&
    236             Params[Index])
    237     {
    238         /*
    239          * A valid parameter.
    240          * Store the argument in the method/walk descriptor.
    241          * Do not copy the arg in order to implement call by reference
    242          */
    243         Status = AcpiDsMethodDataSetValue (
    244             ACPI_REFCLASS_ARG, Index, Params[Index], WalkState);
    245         if (ACPI_FAILURE (Status))
    246         {
    247             return_ACPI_STATUS (Status);
    248         }
    249 
    250         Index++;
    251     }
    252     AcpiExTraceArgs(Params, Index);
    253 
    254     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%u args passed to method\n", Index));
    255     return_ACPI_STATUS (AE_OK);
    256 }
    257 
    258 
    259 /*******************************************************************************
    260  *
    261  * FUNCTION:    AcpiDsMethodDataGetNode
    262  *
    263  * PARAMETERS:  Type                - Either ACPI_REFCLASS_LOCAL or
    264  *                                    ACPI_REFCLASS_ARG
    265  *              Index               - Which Local or Arg whose type to get
    266  *              WalkState           - Current walk state object
    267  *              Node                - Where the node is returned.
    268  *
    269  * RETURN:      Status and node
    270  *
    271  * DESCRIPTION: Get the Node associated with a local or arg.
    272  *
    273  ******************************************************************************/
    274 
    275 ACPI_STATUS
    276 AcpiDsMethodDataGetNode (
    277     UINT8                   Type,
    278     UINT32                  Index,
    279     ACPI_WALK_STATE         *WalkState,
    280     ACPI_NAMESPACE_NODE     **Node)
    281 {
    282     ACPI_FUNCTION_TRACE (DsMethodDataGetNode);
    283 
    284 
    285     /*
    286      * Method Locals and Arguments are supported
    287      */
    288     switch (Type)
    289     {
    290     case ACPI_REFCLASS_LOCAL:
    291 
    292         if (Index > ACPI_METHOD_MAX_LOCAL)
    293         {
    294             ACPI_ERROR ((AE_INFO,
    295                 "Local index %u is invalid (max %u)",
    296                 Index, ACPI_METHOD_MAX_LOCAL));
    297             return_ACPI_STATUS (AE_AML_INVALID_INDEX);
    298         }
    299 
    300         /* Return a pointer to the pseudo-node */
    301 
    302         *Node = &WalkState->LocalVariables[Index];
    303         break;
    304 
    305     case ACPI_REFCLASS_ARG:
    306 
    307         if (Index > ACPI_METHOD_MAX_ARG)
    308         {
    309             ACPI_ERROR ((AE_INFO,
    310                 "Arg index %u is invalid (max %u)",
    311                 Index, ACPI_METHOD_MAX_ARG));
    312             return_ACPI_STATUS (AE_AML_INVALID_INDEX);
    313         }
    314 
    315         /* Return a pointer to the pseudo-node */
    316 
    317         *Node = &WalkState->Arguments[Index];
    318         break;
    319 
    320     default:
    321 
    322         ACPI_ERROR ((AE_INFO, "Type %u is invalid", Type));
    323         return_ACPI_STATUS (AE_TYPE);
    324     }
    325 
    326     return_ACPI_STATUS (AE_OK);
    327 }
    328 
    329 
    330 /*******************************************************************************
    331  *
    332  * FUNCTION:    AcpiDsMethodDataSetValue
    333  *
    334  * PARAMETERS:  Type                - Either ACPI_REFCLASS_LOCAL or
    335  *                                    ACPI_REFCLASS_ARG
    336  *              Index               - Which Local or Arg to get
    337  *              Object              - Object to be inserted into the stack entry
    338  *              WalkState           - Current walk state object
    339  *
    340  * RETURN:      Status
    341  *
    342  * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
    343  *              Note: There is no "implicit conversion" for locals.
    344  *
    345  ******************************************************************************/
    346 
    347 static ACPI_STATUS
    348 AcpiDsMethodDataSetValue (
    349     UINT8                   Type,
    350     UINT32                  Index,
    351     ACPI_OPERAND_OBJECT     *Object,
    352     ACPI_WALK_STATE         *WalkState)
    353 {
    354     ACPI_STATUS             Status;
    355     ACPI_NAMESPACE_NODE     *Node;
    356 
    357 
    358     ACPI_FUNCTION_TRACE (DsMethodDataSetValue);
    359 
    360 
    361     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    362         "NewObj %p Type %2.2X, Refs=%u [%s]\n", Object,
    363         Type, Object->Common.ReferenceCount,
    364         AcpiUtGetTypeName (Object->Common.Type)));
    365 
    366     /* Get the namespace node for the arg/local */
    367 
    368     Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node);
    369     if (ACPI_FAILURE (Status))
    370     {
    371         return_ACPI_STATUS (Status);
    372     }
    373 
    374     /*
    375      * Increment ref count so object can't be deleted while installed.
    376      * NOTE: We do not copy the object in order to preserve the call by
    377      * reference semantics of ACPI Control Method invocation.
    378      * (See ACPI Specification 2.0C)
    379      */
    380     AcpiUtAddReference (Object);
    381 
    382     /* Install the object */
    383 
    384     Node->Object = Object;
    385     return_ACPI_STATUS (Status);
    386 }
    387 
    388 
    389 /*******************************************************************************
    390  *
    391  * FUNCTION:    AcpiDsMethodDataGetValue
    392  *
    393  * PARAMETERS:  Type                - Either ACPI_REFCLASS_LOCAL or
    394  *                                    ACPI_REFCLASS_ARG
    395  *              Index               - Which localVar or argument to get
    396  *              WalkState           - Current walk state object
    397  *              DestDesc            - Where Arg or Local value is returned
    398  *
    399  * RETURN:      Status
    400  *
    401  * DESCRIPTION: Retrieve value of selected Arg or Local for this method
    402  *              Used only in AcpiExResolveToValue().
    403  *
    404  ******************************************************************************/
    405 
    406 ACPI_STATUS
    407 AcpiDsMethodDataGetValue (
    408     UINT8                   Type,
    409     UINT32                  Index,
    410     ACPI_WALK_STATE         *WalkState,
    411     ACPI_OPERAND_OBJECT     **DestDesc)
    412 {
    413     ACPI_STATUS             Status;
    414     ACPI_NAMESPACE_NODE     *Node;
    415     ACPI_OPERAND_OBJECT     *Object;
    416 
    417 
    418     ACPI_FUNCTION_TRACE (DsMethodDataGetValue);
    419 
    420 
    421     /* Validate the object descriptor */
    422 
    423     if (!DestDesc)
    424     {
    425         ACPI_ERROR ((AE_INFO, "Null object descriptor pointer"));
    426         return_ACPI_STATUS (AE_BAD_PARAMETER);
    427     }
    428 
    429     /* Get the namespace node for the arg/local */
    430 
    431     Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node);
    432     if (ACPI_FAILURE (Status))
    433     {
    434         return_ACPI_STATUS (Status);
    435     }
    436 
    437     /* Get the object from the node */
    438 
    439     Object = Node->Object;
    440 
    441     /* Examine the returned object, it must be valid. */
    442 
    443     if (!Object)
    444     {
    445         /*
    446          * Index points to uninitialized object.
    447          * This means that either 1) The expected argument was
    448          * not passed to the method, or 2) A local variable
    449          * was referenced by the method (via the ASL)
    450          * before it was initialized. Either case is an error.
    451          */
    452 
    453         /* If slack enabled, init the LocalX/ArgX to an Integer of value zero */
    454 
    455         if (AcpiGbl_EnableInterpreterSlack)
    456         {
    457             Object = AcpiUtCreateIntegerObject ((UINT64) 0);
    458             if (!Object)
    459             {
    460                 return_ACPI_STATUS (AE_NO_MEMORY);
    461             }
    462 
    463             Node->Object = Object;
    464         }
    465 
    466         /* Otherwise, return the error */
    467 
    468         else switch (Type)
    469         {
    470         case ACPI_REFCLASS_ARG:
    471 
    472             ACPI_ERROR ((AE_INFO,
    473                 "Uninitialized Arg[%u] at node %p",
    474                 Index, Node));
    475 
    476             return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG);
    477 
    478         case ACPI_REFCLASS_LOCAL:
    479             /*
    480              * No error message for this case, will be trapped again later to
    481              * detect and ignore cases of Store(LocalX,LocalX)
    482              */
    483             return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);
    484 
    485         default:
    486 
    487             ACPI_ERROR ((AE_INFO, "Not a Arg/Local opcode: 0x%X", Type));
    488             return_ACPI_STATUS (AE_AML_INTERNAL);
    489         }
    490     }
    491 
    492     /*
    493      * The Index points to an initialized and valid object.
    494      * Return an additional reference to the object
    495      */
    496     *DestDesc = Object;
    497     AcpiUtAddReference (Object);
    498 
    499     return_ACPI_STATUS (AE_OK);
    500 }
    501 
    502 
    503 /*******************************************************************************
    504  *
    505  * FUNCTION:    AcpiDsMethodDataDeleteValue
    506  *
    507  * PARAMETERS:  Type                - Either ACPI_REFCLASS_LOCAL or
    508  *                                    ACPI_REFCLASS_ARG
    509  *              Index               - Which localVar or argument to delete
    510  *              WalkState           - Current walk state object
    511  *
    512  * RETURN:      None
    513  *
    514  * DESCRIPTION: Delete the entry at Opcode:Index. Inserts
    515  *              a null into the stack slot after the object is deleted.
    516  *
    517  ******************************************************************************/
    518 
    519 static void
    520 AcpiDsMethodDataDeleteValue (
    521     UINT8                   Type,
    522     UINT32                  Index,
    523     ACPI_WALK_STATE         *WalkState)
    524 {
    525     ACPI_STATUS             Status;
    526     ACPI_NAMESPACE_NODE     *Node;
    527     ACPI_OPERAND_OBJECT     *Object;
    528 
    529 
    530     ACPI_FUNCTION_TRACE (DsMethodDataDeleteValue);
    531 
    532 
    533     /* Get the namespace node for the arg/local */
    534 
    535     Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node);
    536     if (ACPI_FAILURE (Status))
    537     {
    538         return_VOID;
    539     }
    540 
    541     /* Get the associated object */
    542 
    543     Object = AcpiNsGetAttachedObject (Node);
    544 
    545     /*
    546      * Undefine the Arg or Local by setting its descriptor
    547      * pointer to NULL. Locals/Args can contain both
    548      * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
    549      */
    550     Node->Object = NULL;
    551 
    552     if ((Object) &&
    553         (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_OPERAND))
    554     {
    555         /*
    556          * There is a valid object.
    557          * Decrement the reference count by one to balance the
    558          * increment when the object was stored.
    559          */
    560         AcpiUtRemoveReference (Object);
    561     }
    562 
    563     return_VOID;
    564 }
    565 
    566 
    567 /*******************************************************************************
    568  *
    569  * FUNCTION:    AcpiDsStoreObjectToLocal
    570  *
    571  * PARAMETERS:  Type                - Either ACPI_REFCLASS_LOCAL or
    572  *                                    ACPI_REFCLASS_ARG
    573  *              Index               - Which Local or Arg to set
    574  *              ObjDesc             - Value to be stored
    575  *              WalkState           - Current walk state
    576  *
    577  * RETURN:      Status
    578  *
    579  * DESCRIPTION: Store a value in an Arg or Local. The ObjDesc is installed
    580  *              as the new value for the Arg or Local and the reference count
    581  *              for ObjDesc is incremented.
    582  *
    583  ******************************************************************************/
    584 
    585 ACPI_STATUS
    586 AcpiDsStoreObjectToLocal (
    587     UINT8                   Type,
    588     UINT32                  Index,
    589     ACPI_OPERAND_OBJECT     *ObjDesc,
    590     ACPI_WALK_STATE         *WalkState)
    591 {
    592     ACPI_STATUS             Status;
    593     ACPI_NAMESPACE_NODE     *Node;
    594     ACPI_OPERAND_OBJECT     *CurrentObjDesc;
    595     ACPI_OPERAND_OBJECT     *NewObjDesc;
    596 
    597 
    598     ACPI_FUNCTION_TRACE (DsStoreObjectToLocal);
    599     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Type=%2.2X Index=%u Obj=%p\n",
    600         Type, Index, ObjDesc));
    601 
    602     /* Parameter validation */
    603 
    604     if (!ObjDesc)
    605     {
    606         return_ACPI_STATUS (AE_BAD_PARAMETER);
    607     }
    608 
    609     /* Get the namespace node for the arg/local */
    610 
    611     Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node);
    612     if (ACPI_FAILURE (Status))
    613     {
    614         return_ACPI_STATUS (Status);
    615     }
    616 
    617     CurrentObjDesc = AcpiNsGetAttachedObject (Node);
    618     if (CurrentObjDesc == ObjDesc)
    619     {
    620         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n",
    621             ObjDesc));
    622         return_ACPI_STATUS (Status);
    623     }
    624 
    625     /*
    626      * If the reference count on the object is more than one, we must
    627      * take a copy of the object before we store. A reference count
    628      * of exactly 1 means that the object was just created during the
    629      * evaluation of an expression, and we can safely use it since it
    630      * is not used anywhere else.
    631      */
    632     NewObjDesc = ObjDesc;
    633     if (ObjDesc->Common.ReferenceCount > 1)
    634     {
    635         Status = AcpiUtCopyIobjectToIobject (
    636             ObjDesc, &NewObjDesc, WalkState);
    637         if (ACPI_FAILURE (Status))
    638         {
    639             return_ACPI_STATUS (Status);
    640         }
    641     }
    642 
    643     /*
    644      * If there is an object already in this slot, we either
    645      * have to delete it, or if this is an argument and there
    646      * is an object reference stored there, we have to do
    647      * an indirect store!
    648      */
    649     if (CurrentObjDesc)
    650     {
    651         /*
    652          * Check for an indirect store if an argument
    653          * contains an object reference (stored as an Node).
    654          * We don't allow this automatic dereferencing for
    655          * locals, since a store to a local should overwrite
    656          * anything there, including an object reference.
    657          *
    658          * If both Arg0 and Local0 contain RefOf (Local4):
    659          *
    660          * Store (1, Arg0)             - Causes indirect store to local4
    661          * Store (1, Local0)           - Stores 1 in local0, overwriting
    662          *                                  the reference to local4
    663          * Store (1, DeRefof (Local0)) - Causes indirect store to local4
    664          *
    665          * Weird, but true.
    666          */
    667         if (Type == ACPI_REFCLASS_ARG)
    668         {
    669             /*
    670              * If we have a valid reference object that came from RefOf(),
    671              * do the indirect store
    672              */
    673             if ((ACPI_GET_DESCRIPTOR_TYPE (CurrentObjDesc) ==
    674                     ACPI_DESC_TYPE_OPERAND) &&
    675                 (CurrentObjDesc->Common.Type ==
    676                     ACPI_TYPE_LOCAL_REFERENCE) &&
    677                 (CurrentObjDesc->Reference.Class ==
    678                     ACPI_REFCLASS_REFOF))
    679             {
    680                 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    681                     "Arg (%p) is an ObjRef(Node), storing in node %p\n",
    682                     NewObjDesc, CurrentObjDesc));
    683 
    684                 /*
    685                  * Store this object to the Node (perform the indirect store)
    686                  * NOTE: No implicit conversion is performed, as per the ACPI
    687                  * specification rules on storing to Locals/Args.
    688                  */
    689                 Status = AcpiExStoreObjectToNode (NewObjDesc,
    690                     CurrentObjDesc->Reference.Object, WalkState,
    691                     ACPI_NO_IMPLICIT_CONVERSION);
    692 
    693                 /* Remove local reference if we copied the object above */
    694 
    695                 if (NewObjDesc != ObjDesc)
    696                 {
    697                     AcpiUtRemoveReference (NewObjDesc);
    698                 }
    699 
    700                 return_ACPI_STATUS (Status);
    701             }
    702         }
    703 
    704         /* Delete the existing object before storing the new one */
    705 
    706         AcpiDsMethodDataDeleteValue (Type, Index, WalkState);
    707     }
    708 
    709     /*
    710      * Install the Obj descriptor (*NewObjDesc) into
    711      * the descriptor for the Arg or Local.
    712      * (increments the object reference count by one)
    713      */
    714     Status = AcpiDsMethodDataSetValue (Type, Index, NewObjDesc, WalkState);
    715 
    716     /* Remove local reference if we copied the object above */
    717 
    718     if (NewObjDesc != ObjDesc)
    719     {
    720         AcpiUtRemoveReference (NewObjDesc);
    721     }
    722 
    723     return_ACPI_STATUS (Status);
    724 }
    725 
    726 
    727 #ifdef ACPI_OBSOLETE_FUNCTIONS
    728 /*******************************************************************************
    729  *
    730  * FUNCTION:    AcpiDsMethodDataGetType
    731  *
    732  * PARAMETERS:  Opcode              - Either AML_FIRST LOCAL_OP or
    733  *                                    AML_FIRST_ARG_OP
    734  *              Index               - Which Local or Arg whose type to get
    735  *              WalkState           - Current walk state object
    736  *
    737  * RETURN:      Data type of current value of the selected Arg or Local
    738  *
    739  * DESCRIPTION: Get the type of the object stored in the Local or Arg
    740  *
    741  ******************************************************************************/
    742 
    743 ACPI_OBJECT_TYPE
    744 AcpiDsMethodDataGetType (
    745     UINT16                  Opcode,
    746     UINT32                  Index,
    747     ACPI_WALK_STATE         *WalkState)
    748 {
    749     ACPI_STATUS             Status;
    750     ACPI_NAMESPACE_NODE     *Node;
    751     ACPI_OPERAND_OBJECT     *Object;
    752 
    753 
    754     ACPI_FUNCTION_TRACE (DsMethodDataGetType);
    755 
    756 
    757     /* Get the namespace node for the arg/local */
    758 
    759     Status = AcpiDsMethodDataGetNode (Opcode, Index, WalkState, &Node);
    760     if (ACPI_FAILURE (Status))
    761     {
    762         return_VALUE ((ACPI_TYPE_NOT_FOUND));
    763     }
    764 
    765     /* Get the object */
    766 
    767     Object = AcpiNsGetAttachedObject (Node);
    768     if (!Object)
    769     {
    770         /* Uninitialized local/arg, return TYPE_ANY */
    771 
    772         return_VALUE (ACPI_TYPE_ANY);
    773     }
    774 
    775     /* Get the object type */
    776 
    777     return_VALUE (Object->Type);
    778 }
    779 #endif
    780