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