exstore.c revision 306536
1/******************************************************************************
2 *
3 * Module Name: exstore - AML Interpreter object store support
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, 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 (
278                SourceDesc, &NewDesc, WalkState);
279            if (ACPI_FAILURE (Status))
280            {
281                return_ACPI_STATUS (Status);
282            }
283        }
284
285        if (ObjDesc)
286        {
287            /* Decrement reference count by the ref count of the parent package */
288
289            for (i = 0;
290                 i < ((ACPI_OPERAND_OBJECT *)
291                        IndexDesc->Reference.Object)->Common.ReferenceCount;
292                 i++)
293            {
294                AcpiUtRemoveReference (ObjDesc);
295            }
296        }
297
298        *(IndexDesc->Reference.Where) = NewDesc;
299
300        /* Increment ref count by the ref count of the parent package-1 */
301
302        for (i = 1;
303             i < ((ACPI_OPERAND_OBJECT *)
304                    IndexDesc->Reference.Object)->Common.ReferenceCount;
305             i++)
306        {
307            AcpiUtAddReference (NewDesc);
308        }
309
310        break;
311
312    case ACPI_TYPE_BUFFER_FIELD:
313        /*
314         * Store into a Buffer or String (not actually a real BufferField)
315         * at a location defined by an Index.
316         *
317         * The first 8-bit element of the source object is written to the
318         * 8-bit Buffer location defined by the Index destination object,
319         * according to the ACPI 2.0 specification.
320         */
321
322        /*
323         * Make sure the target is a Buffer or String. An error should
324         * not happen here, since the ReferenceObject was constructed
325         * by the INDEX_OP code.
326         */
327        ObjDesc = IndexDesc->Reference.Object;
328        if ((ObjDesc->Common.Type != ACPI_TYPE_BUFFER) &&
329            (ObjDesc->Common.Type != ACPI_TYPE_STRING))
330        {
331            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
332        }
333
334        /*
335         * The assignment of the individual elements will be slightly
336         * different for each source type.
337         */
338        switch (SourceDesc->Common.Type)
339        {
340        case ACPI_TYPE_INTEGER:
341
342            /* Use the least-significant byte of the integer */
343
344            Value = (UINT8) (SourceDesc->Integer.Value);
345            break;
346
347        case ACPI_TYPE_BUFFER:
348        case ACPI_TYPE_STRING:
349
350            /* Note: Takes advantage of common string/buffer fields */
351
352            Value = SourceDesc->Buffer.Pointer[0];
353            break;
354
355        default:
356
357            /* All other types are invalid */
358
359            ACPI_ERROR ((AE_INFO,
360                "Source must be type [Integer/Buffer/String], found [%s]",
361                AcpiUtGetObjectTypeName (SourceDesc)));
362            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
363        }
364
365        /* Store the source value into the target buffer byte */
366
367        ObjDesc->Buffer.Pointer[IndexDesc->Reference.Value] = Value;
368        break;
369
370    default:
371        ACPI_ERROR ((AE_INFO,
372            "Target is not of type [Package/BufferField]"));
373        Status = AE_AML_TARGET_TYPE;
374        break;
375    }
376
377    return_ACPI_STATUS (Status);
378}
379
380
381/*******************************************************************************
382 *
383 * FUNCTION:    AcpiExStoreObjectToNode
384 *
385 * PARAMETERS:  SourceDesc              - Value to be stored
386 *              Node                    - Named object to receive the value
387 *              WalkState               - Current walk state
388 *              ImplicitConversion      - Perform implicit conversion (yes/no)
389 *
390 * RETURN:      Status
391 *
392 * DESCRIPTION: Store the object to the named object.
393 *
394 * The assignment of an object to a named object is handled here.
395 * The value passed in will replace the current value (if any)
396 * with the input value.
397 *
398 * When storing into an object the data is converted to the
399 * target object type then stored in the object. This means
400 * that the target object type (for an initialized target) will
401 * not be changed by a store operation. A CopyObject can change
402 * the target type, however.
403 *
404 * The ImplicitConversion flag is set to NO/FALSE only when
405 * storing to an ArgX -- as per the rules of the ACPI spec.
406 *
407 * Assumes parameters are already validated.
408 *
409 ******************************************************************************/
410
411ACPI_STATUS
412AcpiExStoreObjectToNode (
413    ACPI_OPERAND_OBJECT     *SourceDesc,
414    ACPI_NAMESPACE_NODE     *Node,
415    ACPI_WALK_STATE         *WalkState,
416    UINT8                   ImplicitConversion)
417{
418    ACPI_STATUS             Status = AE_OK;
419    ACPI_OPERAND_OBJECT     *TargetDesc;
420    ACPI_OPERAND_OBJECT     *NewDesc;
421    ACPI_OBJECT_TYPE        TargetType;
422
423
424    ACPI_FUNCTION_TRACE_PTR (ExStoreObjectToNode, SourceDesc);
425
426
427    /* Get current type of the node, and object attached to Node */
428
429    TargetType = AcpiNsGetType (Node);
430    TargetDesc = AcpiNsGetAttachedObject (Node);
431
432    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p [%s] to node %p [%s]\n",
433        SourceDesc, AcpiUtGetObjectTypeName (SourceDesc),
434        Node, AcpiUtGetTypeName (TargetType)));
435
436    /* Only limited target types possible for everything except CopyObject */
437
438    if (WalkState->Opcode != AML_COPY_OP)
439    {
440        /*
441         * Only CopyObject allows all object types to be overwritten. For
442         * TargetRef(s), there are restrictions on the object types that
443         * are allowed.
444         *
445         * Allowable operations/typing for Store:
446         *
447         * 1) Simple Store
448         *      Integer     --> Integer (Named/Local/Arg)
449         *      String      --> String  (Named/Local/Arg)
450         *      Buffer      --> Buffer  (Named/Local/Arg)
451         *      Package     --> Package (Named/Local/Arg)
452         *
453         * 2) Store with implicit conversion
454         *      Integer     --> String or Buffer  (Named)
455         *      String      --> Integer or Buffer (Named)
456         *      Buffer      --> Integer or String (Named)
457         */
458        switch (TargetType)
459        {
460        case ACPI_TYPE_PACKAGE:
461            /*
462             * Here, can only store a package to an existing package.
463             * Storing a package to a Local/Arg is OK, and handled
464             * elsewhere.
465             */
466            if (WalkState->Opcode == AML_STORE_OP)
467            {
468                if (SourceDesc->Common.Type != ACPI_TYPE_PACKAGE)
469                {
470                    ACPI_ERROR ((AE_INFO,
471                        "Cannot assign type [%s] to [Package] "
472                        "(source must be type Pkg)",
473                        AcpiUtGetObjectTypeName (SourceDesc)));
474
475                    return_ACPI_STATUS (AE_AML_TARGET_TYPE);
476                }
477                break;
478            }
479
480        /* Fallthrough */
481
482        case ACPI_TYPE_DEVICE:
483        case ACPI_TYPE_EVENT:
484        case ACPI_TYPE_MUTEX:
485        case ACPI_TYPE_REGION:
486        case ACPI_TYPE_POWER:
487        case ACPI_TYPE_PROCESSOR:
488        case ACPI_TYPE_THERMAL:
489
490            ACPI_ERROR ((AE_INFO,
491                "Target must be [Buffer/Integer/String/Reference]"
492                ", found [%s] (%4.4s)",
493                AcpiUtGetTypeName (Node->Type), Node->Name.Ascii));
494
495            return_ACPI_STATUS (AE_AML_TARGET_TYPE);
496
497        default:
498            break;
499        }
500    }
501
502    /*
503     * Resolve the source object to an actual value
504     * (If it is a reference object)
505     */
506    Status = AcpiExResolveObject (&SourceDesc, TargetType, WalkState);
507    if (ACPI_FAILURE (Status))
508    {
509        return_ACPI_STATUS (Status);
510    }
511
512    /* Do the actual store operation */
513
514    switch (TargetType)
515    {
516        /*
517         * The simple data types all support implicit source operand
518         * conversion before the store.
519         */
520    case ACPI_TYPE_INTEGER:
521    case ACPI_TYPE_STRING:
522    case ACPI_TYPE_BUFFER:
523
524        if ((WalkState->Opcode == AML_COPY_OP) ||
525            !ImplicitConversion)
526        {
527            /*
528             * However, CopyObject and Stores to ArgX do not perform
529             * an implicit conversion, as per the ACPI specification.
530             * A direct store is performed instead.
531             */
532            Status = AcpiExStoreDirectToNode (SourceDesc, Node, WalkState);
533            break;
534        }
535
536        /* Store with implicit source operand conversion support */
537
538        Status = AcpiExStoreObjectToObject (SourceDesc, TargetDesc,
539            &NewDesc, WalkState);
540        if (ACPI_FAILURE (Status))
541        {
542            return_ACPI_STATUS (Status);
543        }
544
545        if (NewDesc != TargetDesc)
546        {
547            /*
548             * Store the new NewDesc as the new value of the Name, and set
549             * the Name's type to that of the value being stored in it.
550             * SourceDesc reference count is incremented by AttachObject.
551             *
552             * Note: This may change the type of the node if an explicit
553             * store has been performed such that the node/object type
554             * has been changed.
555             */
556            Status = AcpiNsAttachObject (
557                Node, NewDesc, NewDesc->Common.Type);
558
559            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
560                "Store type [%s] into [%s] via Convert/Attach\n",
561                AcpiUtGetObjectTypeName (SourceDesc),
562                AcpiUtGetObjectTypeName (NewDesc)));
563        }
564        break;
565
566    case ACPI_TYPE_BUFFER_FIELD:
567    case ACPI_TYPE_LOCAL_REGION_FIELD:
568    case ACPI_TYPE_LOCAL_BANK_FIELD:
569    case ACPI_TYPE_LOCAL_INDEX_FIELD:
570        /*
571         * For all fields, always write the source data to the target
572         * field. Any required implicit source operand conversion is
573         * performed in the function below as necessary. Note, field
574         * objects must retain their original type permanently.
575         */
576        Status = AcpiExWriteDataToField (SourceDesc, TargetDesc,
577            &WalkState->ResultObj);
578        break;
579
580    default:
581        /*
582         * CopyObject operator: No conversions for all other types.
583         * Instead, directly store a copy of the source object.
584         *
585         * This is the ACPI spec-defined behavior for the CopyObject
586         * operator. (Note, for this default case, all normal
587         * Store/Target operations exited above with an error).
588         */
589        Status = AcpiExStoreDirectToNode (SourceDesc, Node, WalkState);
590        break;
591    }
592
593    return_ACPI_STATUS (Status);
594}
595
596
597/*******************************************************************************
598 *
599 * FUNCTION:    AcpiExStoreDirectToNode
600 *
601 * PARAMETERS:  SourceDesc              - Value to be stored
602 *              Node                    - Named object to receive the value
603 *              WalkState               - Current walk state
604 *
605 * RETURN:      Status
606 *
607 * DESCRIPTION: "Store" an object directly to a node. This involves a copy
608 *              and an attach.
609 *
610 ******************************************************************************/
611
612static ACPI_STATUS
613AcpiExStoreDirectToNode (
614    ACPI_OPERAND_OBJECT     *SourceDesc,
615    ACPI_NAMESPACE_NODE     *Node,
616    ACPI_WALK_STATE         *WalkState)
617{
618    ACPI_STATUS             Status;
619    ACPI_OPERAND_OBJECT     *NewDesc;
620
621
622    ACPI_FUNCTION_TRACE (ExStoreDirectToNode);
623
624
625    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
626        "Storing [%s] (%p) directly into node [%s] (%p)"
627        " with no implicit conversion\n",
628        AcpiUtGetObjectTypeName (SourceDesc), SourceDesc,
629        AcpiUtGetTypeName (Node->Type), Node));
630
631    /* Copy the source object to a new object */
632
633    Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState);
634    if (ACPI_FAILURE (Status))
635    {
636        return_ACPI_STATUS (Status);
637    }
638
639    /* Attach the new object to the node */
640
641    Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type);
642    AcpiUtRemoveReference (NewDesc);
643    return_ACPI_STATUS (Status);
644}
645