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