exstore.c revision 217365
12786Ssos/******************************************************************************
22786Ssos *
32786Ssos * Module Name: exstore - AML Interpreter object store support
42786Ssos *
52786Ssos *****************************************************************************/
632822Syokota
72786Ssos/*
86851Ssos * Copyright (C) 2000 - 2011, Intel Corp.
92786Ssos * All rights reserved.
102786Ssos *
112786Ssos * Redistribution and use in source and binary forms, with or without
122786Ssos * modification, are permitted provided that the following conditions
132786Ssos * are met:
142786Ssos * 1. Redistributions of source code must retain the above copyright
152786Ssos *    notice, this list of conditions, and the following disclaimer,
162786Ssos *    without modification.
172786Ssos * 2. Redistributions in binary form must reproduce at minimum a disclaimer
182786Ssos *    substantially similar to the "NO WARRANTY" disclaimer below
197420Ssos *    ("Disclaimer") and any redistribution must be conditioned upon
202786Ssos *    including a substantially similar Disclaimer requirement for further
212786Ssos *    binary redistribution.
222786Ssos * 3. Neither the names of the above-listed copyright holders nor the names
232786Ssos *    of any contributors may be used to endorse or promote products derived
242786Ssos *    from this software without specific prior written permission.
252786Ssos *
262786Ssos * Alternatively, this software may be distributed under the terms of the
272786Ssos * GNU General Public License ("GPL") version 2 as published by the Free
282786Ssos * Software Foundation.
292786Ssos *
302786Ssos * NO WARRANTY
312786Ssos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
322786Ssos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
332786Ssos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
342786Ssos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
352786Ssos * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
362786Ssos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
372786Ssos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
382786Ssos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
392786Ssos * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
402786Ssos * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
412786Ssos * POSSIBILITY OF SUCH DAMAGES.
422786Ssos */
432786Ssos
442786Ssos#define __EXSTORE_C__
452786Ssos
462786Ssos#include <contrib/dev/acpica/include/acpi.h>
472786Ssos#include <contrib/dev/acpica/include/accommon.h>
482786Ssos#include <contrib/dev/acpica/include/acdispat.h>
492786Ssos#include <contrib/dev/acpica/include/acinterp.h>
502786Ssos#include <contrib/dev/acpica/include/amlcode.h>
512786Ssos#include <contrib/dev/acpica/include/acnamesp.h>
522786Ssos
532786Ssos
542786Ssos#define _COMPONENT          ACPI_EXECUTER
552786Ssos        ACPI_MODULE_NAME    ("exstore")
562786Ssos
572786Ssos/* Local prototypes */
582786Ssos
592786Ssosstatic ACPI_STATUS
602786SsosAcpiExStoreObjectToIndex (
612786Ssos    ACPI_OPERAND_OBJECT     *ValDesc,
6232822Syokota    ACPI_OPERAND_OBJECT     *DestDesc,
632786Ssos    ACPI_WALK_STATE         *WalkState);
642786Ssos
652786Ssos
662786Ssos/*******************************************************************************
672786Ssos *
682786Ssos * FUNCTION:    AcpiExStore
692786Ssos *
702786Ssos * PARAMETERS:  *SourceDesc         - Value to be stored
712786Ssos *              *DestDesc           - Where to store it.  Must be an NS node
722786Ssos *                                    or an ACPI_OPERAND_OBJECT of type
732786Ssos *                                    Reference;
742786Ssos *              WalkState           - Current walk state
752786Ssos *
762786Ssos * RETURN:      Status
772786Ssos *
782786Ssos * DESCRIPTION: Store the value described by SourceDesc into the location
792786Ssos *              described by DestDesc.  Called by various interpreter
802786Ssos *              functions to store the result of an operation into
815994Ssos *              the destination operand -- not just simply the actual "Store"
822786Ssos *              ASL operator.
832786Ssos *
842786Ssos ******************************************************************************/
852786Ssos
862786SsosACPI_STATUS
872786SsosAcpiExStore (
886045Ssos    ACPI_OPERAND_OBJECT     *SourceDesc,
892786Ssos    ACPI_OPERAND_OBJECT     *DestDesc,
902786Ssos    ACPI_WALK_STATE         *WalkState)
912786Ssos{
922786Ssos    ACPI_STATUS             Status = AE_OK;
932786Ssos    ACPI_OPERAND_OBJECT     *RefDesc = DestDesc;
9418194Ssos
952786Ssos
962786Ssos    ACPI_FUNCTION_TRACE_PTR (ExStore, DestDesc);
972786Ssos
982786Ssos
992786Ssos    /* Validate parameters */
1002786Ssos
1012786Ssos    if (!SourceDesc || !DestDesc)
1022786Ssos    {
1032786Ssos        ACPI_ERROR ((AE_INFO, "Null parameter"));
1042786Ssos        return_ACPI_STATUS (AE_AML_NO_OPERAND);
1052786Ssos    }
1062786Ssos
1072786Ssos    /* DestDesc can be either a namespace node or an ACPI object */
1086851Ssos
1092786Ssos    if (ACPI_GET_DESCRIPTOR_TYPE (DestDesc) == ACPI_DESC_TYPE_NAMED)
1106851Ssos    {
1116851Ssos        /*
1126851Ssos         * Dest is a namespace node,
113         * Storing an object into a Named node.
114         */
115        Status = AcpiExStoreObjectToNode (SourceDesc,
116                    (ACPI_NAMESPACE_NODE *) DestDesc, WalkState,
117                    ACPI_IMPLICIT_CONVERSION);
118
119        return_ACPI_STATUS (Status);
120    }
121
122    /* Destination object must be a Reference or a Constant object */
123
124    switch (DestDesc->Common.Type)
125    {
126    case ACPI_TYPE_LOCAL_REFERENCE:
127        break;
128
129    case ACPI_TYPE_INTEGER:
130
131        /* Allow stores to Constants -- a Noop as per ACPI spec */
132
133        if (DestDesc->Common.Flags & AOPOBJ_AML_CONSTANT)
134        {
135            return_ACPI_STATUS (AE_OK);
136        }
137
138        /*lint -fallthrough */
139
140    default:
141
142        /* Destination is not a Reference object */
143
144        ACPI_ERROR ((AE_INFO,
145            "Target is not a Reference or Constant object - %s [%p]",
146            AcpiUtGetObjectTypeName (DestDesc), DestDesc));
147
148        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
149    }
150
151    /*
152     * Examine the Reference class. These cases are handled:
153     *
154     * 1) Store to Name (Change the object associated with a name)
155     * 2) Store to an indexed area of a Buffer or Package
156     * 3) Store to a Method Local or Arg
157     * 4) Store to the debug object
158     */
159    switch (RefDesc->Reference.Class)
160    {
161    case ACPI_REFCLASS_REFOF:
162
163        /* Storing an object into a Name "container" */
164
165        Status = AcpiExStoreObjectToNode (SourceDesc,
166                    RefDesc->Reference.Object,
167                    WalkState, ACPI_IMPLICIT_CONVERSION);
168        break;
169
170
171    case ACPI_REFCLASS_INDEX:
172
173        /* Storing to an Index (pointer into a packager or buffer) */
174
175        Status = AcpiExStoreObjectToIndex (SourceDesc, RefDesc, WalkState);
176        break;
177
178
179    case ACPI_REFCLASS_LOCAL:
180    case ACPI_REFCLASS_ARG:
181
182        /* Store to a method local/arg  */
183
184        Status = AcpiDsStoreObjectToLocal (RefDesc->Reference.Class,
185                    RefDesc->Reference.Value, SourceDesc, WalkState);
186        break;
187
188
189    case ACPI_REFCLASS_DEBUG:
190
191        /*
192         * Storing to the Debug object causes the value stored to be
193         * displayed and otherwise has no effect -- see ACPI Specification
194         */
195        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
196            "**** Write to Debug Object: Object %p %s ****:\n\n",
197            SourceDesc, AcpiUtGetObjectTypeName (SourceDesc)));
198
199        ACPI_DEBUG_OBJECT (SourceDesc, 0, 0);
200        break;
201
202
203    default:
204
205        ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X",
206            RefDesc->Reference.Class));
207        ACPI_DUMP_ENTRY (RefDesc, ACPI_LV_INFO);
208
209        Status = AE_AML_INTERNAL;
210        break;
211    }
212
213    return_ACPI_STATUS (Status);
214}
215
216
217/*******************************************************************************
218 *
219 * FUNCTION:    AcpiExStoreObjectToIndex
220 *
221 * PARAMETERS:  *SourceDesc             - Value to be stored
222 *              *DestDesc               - Named object to receive the value
223 *              WalkState               - Current walk state
224 *
225 * RETURN:      Status
226 *
227 * DESCRIPTION: Store the object to indexed Buffer or Package element
228 *
229 ******************************************************************************/
230
231static ACPI_STATUS
232AcpiExStoreObjectToIndex (
233    ACPI_OPERAND_OBJECT     *SourceDesc,
234    ACPI_OPERAND_OBJECT     *IndexDesc,
235    ACPI_WALK_STATE         *WalkState)
236{
237    ACPI_STATUS             Status = AE_OK;
238    ACPI_OPERAND_OBJECT     *ObjDesc;
239    ACPI_OPERAND_OBJECT     *NewDesc;
240    UINT8                   Value = 0;
241    UINT32                  i;
242
243
244    ACPI_FUNCTION_TRACE (ExStoreObjectToIndex);
245
246
247    /*
248     * Destination must be a reference pointer, and
249     * must point to either a buffer or a package
250     */
251    switch (IndexDesc->Reference.TargetType)
252    {
253    case ACPI_TYPE_PACKAGE:
254        /*
255         * Storing to a package element. Copy the object and replace
256         * any existing object with the new object. No implicit
257         * conversion is performed.
258         *
259         * The object at *(IndexDesc->Reference.Where) is the
260         * element within the package that is to be modified.
261         * The parent package object is at IndexDesc->Reference.Object
262         */
263        ObjDesc = *(IndexDesc->Reference.Where);
264
265        if (SourceDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE &&
266            SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
267        {
268            /* This is a DDBHandle, just add a reference to it */
269
270            AcpiUtAddReference (SourceDesc);
271            NewDesc = SourceDesc;
272        }
273        else
274        {
275            /* Normal object, copy it */
276
277            Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState);
278            if (ACPI_FAILURE (Status))
279            {
280                return_ACPI_STATUS (Status);
281            }
282        }
283
284        if (ObjDesc)
285        {
286            /* Decrement reference count by the ref count of the parent package */
287
288            for (i = 0;
289                 i < ((ACPI_OPERAND_OBJECT *)
290                        IndexDesc->Reference.Object)->Common.ReferenceCount;
291                 i++)
292            {
293                AcpiUtRemoveReference (ObjDesc);
294            }
295        }
296
297        *(IndexDesc->Reference.Where) = NewDesc;
298
299        /* Increment ref count by the ref count of the parent package-1 */
300
301        for (i = 1;
302             i < ((ACPI_OPERAND_OBJECT *)
303                    IndexDesc->Reference.Object)->Common.ReferenceCount;
304             i++)
305        {
306            AcpiUtAddReference (NewDesc);
307        }
308
309        break;
310
311
312    case ACPI_TYPE_BUFFER_FIELD:
313
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
372    default:
373        ACPI_ERROR ((AE_INFO,
374            "Target is not a Package or BufferField"));
375        Status = AE_AML_OPERAND_TYPE;
376        break;
377    }
378
379    return_ACPI_STATUS (Status);
380}
381
382
383/*******************************************************************************
384 *
385 * FUNCTION:    AcpiExStoreObjectToNode
386 *
387 * PARAMETERS:  SourceDesc              - Value to be stored
388 *              Node                    - Named object to receive the value
389 *              WalkState               - Current walk state
390 *              ImplicitConversion      - Perform implicit conversion (yes/no)
391 *
392 * RETURN:      Status
393 *
394 * DESCRIPTION: Store the object to the named object.
395 *
396 *              The Assignment of an object to a named object is handled here
397 *              The value passed in will replace the current value (if any)
398 *              with the input value.
399 *
400 *              When storing into an object the data is converted to the
401 *              target object type then stored in the object.  This means
402 *              that the target object type (for an initialized target) will
403 *              not be changed by a store operation.
404 *
405 *              Assumes parameters are already validated.
406 *
407 ******************************************************************************/
408
409ACPI_STATUS
410AcpiExStoreObjectToNode (
411    ACPI_OPERAND_OBJECT     *SourceDesc,
412    ACPI_NAMESPACE_NODE     *Node,
413    ACPI_WALK_STATE         *WalkState,
414    UINT8                   ImplicitConversion)
415{
416    ACPI_STATUS             Status = AE_OK;
417    ACPI_OPERAND_OBJECT     *TargetDesc;
418    ACPI_OPERAND_OBJECT     *NewDesc;
419    ACPI_OBJECT_TYPE        TargetType;
420
421
422    ACPI_FUNCTION_TRACE_PTR (ExStoreObjectToNode, SourceDesc);
423
424
425    /* Get current type of the node, and object attached to Node */
426
427    TargetType = AcpiNsGetType (Node);
428    TargetDesc = AcpiNsGetAttachedObject (Node);
429
430    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n",
431        SourceDesc, AcpiUtGetObjectTypeName (SourceDesc),
432              Node, AcpiUtGetTypeName (TargetType)));
433
434    /*
435     * Resolve the source object to an actual value
436     * (If it is a reference object)
437     */
438    Status = AcpiExResolveObject (&SourceDesc, TargetType, WalkState);
439    if (ACPI_FAILURE (Status))
440    {
441        return_ACPI_STATUS (Status);
442    }
443
444    /* If no implicit conversion, drop into the default case below */
445
446    if ((!ImplicitConversion) ||
447          ((WalkState->Opcode == AML_COPY_OP) &&
448           (TargetType != ACPI_TYPE_LOCAL_REGION_FIELD) &&
449           (TargetType != ACPI_TYPE_LOCAL_BANK_FIELD) &&
450           (TargetType != ACPI_TYPE_LOCAL_INDEX_FIELD)))
451    {
452        /*
453         * Force execution of default (no implicit conversion). Note:
454         * CopyObject does not perform an implicit conversion, as per the ACPI
455         * spec -- except in case of region/bank/index fields -- because these
456         * objects must retain their original type permanently.
457         */
458        TargetType = ACPI_TYPE_ANY;
459    }
460
461    /* Do the actual store operation */
462
463    switch (TargetType)
464    {
465    case ACPI_TYPE_BUFFER_FIELD:
466    case ACPI_TYPE_LOCAL_REGION_FIELD:
467    case ACPI_TYPE_LOCAL_BANK_FIELD:
468    case ACPI_TYPE_LOCAL_INDEX_FIELD:
469
470        /* For fields, copy the source data to the target field. */
471
472        Status = AcpiExWriteDataToField (SourceDesc, TargetDesc,
473                    &WalkState->ResultObj);
474        break;
475
476
477    case ACPI_TYPE_INTEGER:
478    case ACPI_TYPE_STRING:
479    case ACPI_TYPE_BUFFER:
480
481        /*
482         * These target types are all of type Integer/String/Buffer, and
483         * therefore support implicit conversion before the store.
484         *
485         * Copy and/or convert the source object to a new target object
486         */
487        Status = AcpiExStoreObjectToObject (SourceDesc, TargetDesc,
488                    &NewDesc, WalkState);
489        if (ACPI_FAILURE (Status))
490        {
491            return_ACPI_STATUS (Status);
492        }
493
494        if (NewDesc != TargetDesc)
495        {
496            /*
497             * Store the new NewDesc as the new value of the Name, and set
498             * the Name's type to that of the value being stored in it.
499             * SourceDesc reference count is incremented by AttachObject.
500             *
501             * Note: This may change the type of the node if an explicit store
502             * has been performed such that the node/object type has been
503             * changed.
504             */
505            Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type);
506
507            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
508                "Store %s into %s via Convert/Attach\n",
509                AcpiUtGetObjectTypeName (SourceDesc),
510                AcpiUtGetObjectTypeName (NewDesc)));
511        }
512        break;
513
514
515    default:
516
517        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
518            "Storing %s (%p) directly into node (%p) with no implicit conversion\n",
519            AcpiUtGetObjectTypeName (SourceDesc), SourceDesc, Node));
520
521        /* No conversions for all other types.  Just attach the source object */
522
523        Status = AcpiNsAttachObject (Node, SourceDesc,
524                    SourceDesc->Common.Type);
525        break;
526    }
527
528    return_ACPI_STATUS (Status);
529}
530
531
532