1 /******************************************************************************
   2  *
   3  * Module Name: exstore - AML Interpreter object store support
   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 __EXSTORE_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acdispat.h"
  49 #include "acinterp.h"
  50 #include "amlcode.h"
  51 #include "acnamesp.h"
  52 
  53 
  54 #define _COMPONENT          ACPI_EXECUTER
  55         ACPI_MODULE_NAME    ("exstore")
  56 
  57 /* Local prototypes */
  58 
  59 static ACPI_STATUS
  60 AcpiExStoreObjectToIndex (
  61     ACPI_OPERAND_OBJECT     *ValDesc,
  62     ACPI_OPERAND_OBJECT     *DestDesc,
  63     ACPI_WALK_STATE         *WalkState);
  64 
  65 static ACPI_STATUS
  66 AcpiExStoreDirectToNode (
  67     ACPI_OPERAND_OBJECT     *SourceDesc,
  68     ACPI_NAMESPACE_NODE     *Node,
  69     ACPI_WALK_STATE         *WalkState);
  70 
  71 
  72 /*******************************************************************************
  73  *
  74  * FUNCTION:    AcpiExStore
  75  *
  76  * PARAMETERS:  *SourceDesc         - Value to be stored
  77  *              *DestDesc           - Where to store it. Must be an NS node
  78  *                                    or ACPI_OPERAND_OBJECT of type
  79  *                                    Reference;
  80  *              WalkState           - Current walk state
  81  *
  82  * RETURN:      Status
  83  *
  84  * DESCRIPTION: Store the value described by SourceDesc into the location
  85  *              described by DestDesc. Called by various interpreter
  86  *              functions to store the result of an operation into
  87  *              the destination operand -- not just simply the actual "Store"
  88  *              ASL operator.
  89  *
  90  ******************************************************************************/
  91 
  92 ACPI_STATUS
  93 AcpiExStore (
  94     ACPI_OPERAND_OBJECT     *SourceDesc,
  95     ACPI_OPERAND_OBJECT     *DestDesc,
  96     ACPI_WALK_STATE         *WalkState)
  97 {
  98     ACPI_STATUS             Status = AE_OK;
  99     ACPI_OPERAND_OBJECT     *RefDesc = DestDesc;
 100 
 101 
 102     ACPI_FUNCTION_TRACE_PTR (ExStore, DestDesc);
 103 
 104 
 105     /* Validate parameters */
 106 
 107     if (!SourceDesc || !DestDesc)
 108     {
 109         ACPI_ERROR ((AE_INFO, "Null parameter"));
 110         return_ACPI_STATUS (AE_AML_NO_OPERAND);
 111     }
 112 
 113     /* DestDesc can be either a namespace node or an ACPI object */
 114 
 115     if (ACPI_GET_DESCRIPTOR_TYPE (DestDesc) == ACPI_DESC_TYPE_NAMED)
 116     {
 117         /*
 118          * Dest is a namespace node,
 119          * Storing an object into a Named node.
 120          */
 121         Status = AcpiExStoreObjectToNode (SourceDesc,
 122                     (ACPI_NAMESPACE_NODE *) DestDesc, WalkState,
 123                     ACPI_IMPLICIT_CONVERSION);
 124 
 125         return_ACPI_STATUS (Status);
 126     }
 127 
 128     /* Destination object must be a Reference or a Constant object */
 129 
 130     switch (DestDesc->Common.Type)
 131     {
 132     case ACPI_TYPE_LOCAL_REFERENCE:
 133 
 134         break;
 135 
 136     case ACPI_TYPE_INTEGER:
 137 
 138         /* Allow stores to Constants -- a Noop as per ACPI spec */
 139 
 140         if (DestDesc->Common.Flags & AOPOBJ_AML_CONSTANT)
 141         {
 142             return_ACPI_STATUS (AE_OK);
 143         }
 144 
 145         /*lint -fallthrough */
 146 
 147     default:
 148 
 149         /* Destination is not a Reference object */
 150 
 151         ACPI_ERROR ((AE_INFO,
 152             "Target is not a Reference or Constant object - %s [%p]",
 153             AcpiUtGetObjectTypeName (DestDesc), DestDesc));
 154 
 155         return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
 156     }
 157 
 158     /*
 159      * Examine the Reference class. These cases are handled:
 160      *
 161      * 1) Store to Name (Change the object associated with a name)
 162      * 2) Store to an indexed area of a Buffer or Package
 163      * 3) Store to a Method Local or Arg
 164      * 4) Store to the debug object
 165      */
 166     switch (RefDesc->Reference.Class)
 167     {
 168     case ACPI_REFCLASS_REFOF:
 169 
 170         /* Storing an object into a Name "container" */
 171 
 172         Status = AcpiExStoreObjectToNode (SourceDesc,
 173                     RefDesc->Reference.Object,
 174                     WalkState, ACPI_IMPLICIT_CONVERSION);
 175         break;
 176 
 177     case ACPI_REFCLASS_INDEX:
 178 
 179         /* Storing to an Index (pointer into a packager or buffer) */
 180 
 181         Status = AcpiExStoreObjectToIndex (SourceDesc, RefDesc, WalkState);
 182         break;
 183 
 184     case ACPI_REFCLASS_LOCAL:
 185     case ACPI_REFCLASS_ARG:
 186 
 187         /* Store to a method local/arg  */
 188 
 189         Status = AcpiDsStoreObjectToLocal (RefDesc->Reference.Class,
 190                     RefDesc->Reference.Value, SourceDesc, WalkState);
 191         break;
 192 
 193     case ACPI_REFCLASS_DEBUG:
 194         /*
 195          * Storing to the Debug object causes the value stored to be
 196          * displayed and otherwise has no effect -- see ACPI Specification
 197          */
 198         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 199             "**** Write to Debug Object: Object %p %s ****:\n\n",
 200             SourceDesc, AcpiUtGetObjectTypeName (SourceDesc)));
 201 
 202         ACPI_DEBUG_OBJECT (SourceDesc, 0, 0);
 203         break;
 204 
 205     default:
 206 
 207         ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X",
 208             RefDesc->Reference.Class));
 209         ACPI_DUMP_ENTRY (RefDesc, ACPI_LV_INFO);
 210 
 211         Status = AE_AML_INTERNAL;
 212         break;
 213     }
 214 
 215     return_ACPI_STATUS (Status);
 216 }
 217 
 218 
 219 /*******************************************************************************
 220  *
 221  * FUNCTION:    AcpiExStoreObjectToIndex
 222  *
 223  * PARAMETERS:  *SourceDesc             - Value to be stored
 224  *              *DestDesc               - Named object to receive the value
 225  *              WalkState               - Current walk state
 226  *
 227  * RETURN:      Status
 228  *
 229  * DESCRIPTION: Store the object to indexed Buffer or Package element
 230  *
 231  ******************************************************************************/
 232 
 233 static ACPI_STATUS
 234 AcpiExStoreObjectToIndex (
 235     ACPI_OPERAND_OBJECT     *SourceDesc,
 236     ACPI_OPERAND_OBJECT     *IndexDesc,
 237     ACPI_WALK_STATE         *WalkState)
 238 {
 239     ACPI_STATUS             Status = AE_OK;
 240     ACPI_OPERAND_OBJECT     *ObjDesc;
 241     ACPI_OPERAND_OBJECT     *NewDesc;
 242     UINT8                   Value = 0;
 243     UINT32                  i;
 244 
 245 
 246     ACPI_FUNCTION_TRACE (ExStoreObjectToIndex);
 247 
 248 
 249     /*
 250      * Destination must be a reference pointer, and
 251      * must point to either a buffer or a package
 252      */
 253     switch (IndexDesc->Reference.TargetType)
 254     {
 255     case ACPI_TYPE_PACKAGE:
 256         /*
 257          * Storing to a package element. Copy the object and replace
 258          * any existing object with the new object. No implicit
 259          * conversion is performed.
 260          *
 261          * The object at *(IndexDesc->Reference.Where) is the
 262          * element within the package that is to be modified.
 263          * The parent package object is at IndexDesc->Reference.Object
 264          */
 265         ObjDesc = *(IndexDesc->Reference.Where);
 266 
 267         if (SourceDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE &&
 268             SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
 269         {
 270             /* This is a DDBHandle, just add a reference to it */
 271 
 272             AcpiUtAddReference (SourceDesc);
 273             NewDesc = SourceDesc;
 274         }
 275         else
 276         {
 277             /* Normal object, copy it */
 278 
 279             Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState);
 280             if (ACPI_FAILURE (Status))
 281             {
 282                 return_ACPI_STATUS (Status);
 283             }
 284         }
 285 
 286         if (ObjDesc)
 287         {
 288             /* Decrement reference count by the ref count of the parent package */
 289 
 290             for (i = 0;
 291                  i < ((ACPI_OPERAND_OBJECT *)
 292                         IndexDesc->Reference.Object)->Common.ReferenceCount;
 293                  i++)
 294             {
 295                 AcpiUtRemoveReference (ObjDesc);
 296             }
 297         }
 298 
 299         *(IndexDesc->Reference.Where) = NewDesc;
 300 
 301         /* Increment ref count by the ref count of the parent package-1 */
 302 
 303         for (i = 1;
 304              i < ((ACPI_OPERAND_OBJECT *)
 305                     IndexDesc->Reference.Object)->Common.ReferenceCount;
 306              i++)
 307         {
 308             AcpiUtAddReference (NewDesc);
 309         }
 310 
 311         break;
 312 
 313     case ACPI_TYPE_BUFFER_FIELD:
 314         /*
 315          * Store into a Buffer or String (not actually a real BufferField)
 316          * at a location defined by an Index.
 317          *
 318          * The first 8-bit element of the source object is written to the
 319          * 8-bit Buffer location defined by the Index destination object,
 320          * according to the ACPI 2.0 specification.
 321          */
 322 
 323         /*
 324          * Make sure the target is a Buffer or String. An error should
 325          * not happen here, since the ReferenceObject was constructed
 326          * by the INDEX_OP code.
 327          */
 328         ObjDesc = IndexDesc->Reference.Object;
 329         if ((ObjDesc->Common.Type != ACPI_TYPE_BUFFER) &&
 330             (ObjDesc->Common.Type != ACPI_TYPE_STRING))
 331         {
 332             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
 333         }
 334 
 335         /*
 336          * The assignment of the individual elements will be slightly
 337          * different for each source type.
 338          */
 339         switch (SourceDesc->Common.Type)
 340         {
 341         case ACPI_TYPE_INTEGER:
 342 
 343             /* Use the least-significant byte of the integer */
 344 
 345             Value = (UINT8) (SourceDesc->Integer.Value);
 346             break;
 347 
 348         case ACPI_TYPE_BUFFER:
 349         case ACPI_TYPE_STRING:
 350 
 351             /* Note: Takes advantage of common string/buffer fields */
 352 
 353             Value = SourceDesc->Buffer.Pointer[0];
 354             break;
 355 
 356         default:
 357 
 358             /* All other types are invalid */
 359 
 360             ACPI_ERROR ((AE_INFO,
 361                 "Source must be Integer/Buffer/String type, not %s",
 362                 AcpiUtGetObjectTypeName (SourceDesc)));
 363             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
 364         }
 365 
 366         /* Store the source value into the target buffer byte */
 367 
 368         ObjDesc->Buffer.Pointer[IndexDesc->Reference.Value] = Value;
 369         break;
 370 
 371     default:
 372         ACPI_ERROR ((AE_INFO,
 373             "Target is not a Package or BufferField"));
 374         Status = AE_AML_OPERAND_TYPE;
 375         break;
 376     }
 377 
 378     return_ACPI_STATUS (Status);
 379 }
 380 
 381 
 382 /*******************************************************************************
 383  *
 384  * FUNCTION:    AcpiExStoreObjectToNode
 385  *
 386  * PARAMETERS:  SourceDesc              - Value to be stored
 387  *              Node                    - Named object to receive the value
 388  *              WalkState               - Current walk state
 389  *              ImplicitConversion      - Perform implicit conversion (yes/no)
 390  *
 391  * RETURN:      Status
 392  *
 393  * DESCRIPTION: Store the object to the named object.
 394  *
 395  *              The Assignment of an object to a named object is handled here
 396  *              The value passed in will replace the current value (if any)
 397  *              with the input value.
 398  *
 399  *              When storing into an object the data is converted to the
 400  *              target object type then stored in the object. This means
 401  *              that the target object type (for an initialized target) will
 402  *              not be changed by a store operation. A CopyObject can change
 403  *              the target type, however.
 404  *
 405  *              The ImplicitConversion flag is set to NO/FALSE only when
 406  *              storing to an ArgX -- as per the rules of the ACPI spec.
 407  *
 408  *              Assumes parameters are already validated.
 409  *
 410  ******************************************************************************/
 411 
 412 ACPI_STATUS
 413 AcpiExStoreObjectToNode (
 414     ACPI_OPERAND_OBJECT     *SourceDesc,
 415     ACPI_NAMESPACE_NODE     *Node,
 416     ACPI_WALK_STATE         *WalkState,
 417     UINT8                   ImplicitConversion)
 418 {
 419     ACPI_STATUS             Status = AE_OK;
 420     ACPI_OPERAND_OBJECT     *TargetDesc;
 421     ACPI_OPERAND_OBJECT     *NewDesc;
 422     ACPI_OBJECT_TYPE        TargetType;
 423 
 424 
 425     ACPI_FUNCTION_TRACE_PTR (ExStoreObjectToNode, SourceDesc);
 426 
 427 
 428     /* Get current type of the node, and object attached to Node */
 429 
 430     TargetType = AcpiNsGetType (Node);
 431     TargetDesc = AcpiNsGetAttachedObject (Node);
 432 
 433     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p (%s) to node %p (%s)\n",
 434         SourceDesc, AcpiUtGetObjectTypeName (SourceDesc),
 435               Node, AcpiUtGetTypeName (TargetType)));
 436 
 437     /*
 438      * Resolve the source object to an actual value
 439      * (If it is a reference object)
 440      */
 441     Status = AcpiExResolveObject (&SourceDesc, TargetType, WalkState);
 442     if (ACPI_FAILURE (Status))
 443     {
 444         return_ACPI_STATUS (Status);
 445     }
 446 
 447     /* Do the actual store operation */
 448 
 449     switch (TargetType)
 450     {
 451     case ACPI_TYPE_INTEGER:
 452     case ACPI_TYPE_STRING:
 453     case ACPI_TYPE_BUFFER:
 454         /*
 455          * The simple data types all support implicit source operand
 456          * conversion before the store.
 457          */
 458 
 459         if ((WalkState->Opcode == AML_COPY_OP) ||
 460             !ImplicitConversion)
 461         {
 462             /*
 463              * However, CopyObject and Stores to ArgX do not perform
 464              * an implicit conversion, as per the ACPI specification.
 465              * A direct store is performed instead.
 466              */
 467             Status = AcpiExStoreDirectToNode (SourceDesc, Node,
 468                 WalkState);
 469             break;
 470         }
 471 
 472         /* Store with implicit source operand conversion support */
 473 
 474         Status = AcpiExStoreObjectToObject (SourceDesc, TargetDesc,
 475             &NewDesc, WalkState);
 476         if (ACPI_FAILURE (Status))
 477         {
 478             return_ACPI_STATUS (Status);
 479         }
 480 
 481         if (NewDesc != TargetDesc)
 482         {
 483             /*
 484              * Store the new NewDesc as the new value of the Name, and set
 485              * the Name's type to that of the value being stored in it.
 486              * SourceDesc reference count is incremented by AttachObject.
 487              *
 488              * Note: This may change the type of the node if an explicit
 489              * store has been performed such that the node/object type
 490              * has been changed.
 491              */
 492             Status = AcpiNsAttachObject (Node, NewDesc,
 493                 NewDesc->Common.Type);
 494 
 495             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 496                 "Store %s into %s via Convert/Attach\n",
 497                 AcpiUtGetObjectTypeName (SourceDesc),
 498                 AcpiUtGetObjectTypeName (NewDesc)));
 499         }
 500         break;
 501 
 502     case ACPI_TYPE_BUFFER_FIELD:
 503     case ACPI_TYPE_LOCAL_REGION_FIELD:
 504     case ACPI_TYPE_LOCAL_BANK_FIELD:
 505     case ACPI_TYPE_LOCAL_INDEX_FIELD:
 506         /*
 507          * For all fields, always write the source data to the target
 508          * field. Any required implicit source operand conversion is
 509          * performed in the function below as necessary. Note, field
 510          * objects must retain their original type permanently.
 511          */
 512         Status = AcpiExWriteDataToField (SourceDesc, TargetDesc,
 513             &WalkState->ResultObj);
 514         break;
 515 
 516     default:
 517         /*
 518          * No conversions for all other types. Directly store a copy of
 519          * the source object. This is the ACPI spec-defined behavior for
 520          * the CopyObject operator.
 521          *
 522          * NOTE: For the Store operator, this is a departure from the
 523          * ACPI spec, which states "If conversion is impossible, abort
 524          * the running control method". Instead, this code implements
 525          * "If conversion is impossible, treat the Store operation as
 526          * a CopyObject".
 527          */
 528         Status = AcpiExStoreDirectToNode (SourceDesc, Node,
 529             WalkState);
 530         break;
 531     }
 532 
 533     return_ACPI_STATUS (Status);
 534 }
 535 
 536 
 537 /*******************************************************************************
 538  *
 539  * FUNCTION:    AcpiExStoreDirectToNode
 540  *
 541  * PARAMETERS:  SourceDesc              - Value to be stored
 542  *              Node                    - Named object to receive the value
 543  *              WalkState               - Current walk state
 544  *
 545  * RETURN:      Status
 546  *
 547  * DESCRIPTION: "Store" an object directly to a node. This involves a copy
 548  *              and an attach.
 549  *
 550  ******************************************************************************/
 551 
 552 static ACPI_STATUS
 553 AcpiExStoreDirectToNode (
 554     ACPI_OPERAND_OBJECT     *SourceDesc,
 555     ACPI_NAMESPACE_NODE     *Node,
 556     ACPI_WALK_STATE         *WalkState)
 557 {
 558     ACPI_STATUS             Status;
 559     ACPI_OPERAND_OBJECT     *NewDesc;
 560 
 561 
 562     ACPI_FUNCTION_TRACE (ExStoreDirectToNode);
 563 
 564 
 565     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 566         "Storing [%s] (%p) directly into node [%s] (%p)"
 567         " with no implicit conversion\n",
 568         AcpiUtGetObjectTypeName (SourceDesc), SourceDesc,
 569         AcpiUtGetTypeName (Node->Type), Node));
 570 
 571     /* Copy the source object to a new object */
 572 
 573     Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState);
 574     if (ACPI_FAILURE (Status))
 575     {
 576         return_ACPI_STATUS (Status);
 577     }
 578 
 579     /* Attach the new object to the node */
 580 
 581     Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type);
 582     AcpiUtRemoveReference (NewDesc);
 583     return_ACPI_STATUS (Status);
 584 }