]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/dev/acpica/executer/exstore.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / dev / acpica / executer / exstore.c
1 /******************************************************************************
2  *
3  * Module Name: exstore - AML Interpreter object store support
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2011, 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 <contrib/dev/acpica/include/acpi.h>
47 #include <contrib/dev/acpica/include/accommon.h>
48 #include <contrib/dev/acpica/include/acdispat.h>
49 #include <contrib/dev/acpica/include/acinterp.h>
50 #include <contrib/dev/acpica/include/amlcode.h>
51 #include <contrib/dev/acpica/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
66 /*******************************************************************************
67  *
68  * FUNCTION:    AcpiExStore
69  *
70  * PARAMETERS:  *SourceDesc         - Value to be stored
71  *              *DestDesc           - Where to store it.  Must be an NS node
72  *                                    or an ACPI_OPERAND_OBJECT of type
73  *                                    Reference;
74  *              WalkState           - Current walk state
75  *
76  * RETURN:      Status
77  *
78  * DESCRIPTION: Store the value described by SourceDesc into the location
79  *              described by DestDesc.  Called by various interpreter
80  *              functions to store the result of an operation into
81  *              the destination operand -- not just simply the actual "Store"
82  *              ASL operator.
83  *
84  ******************************************************************************/
85
86 ACPI_STATUS
87 AcpiExStore (
88     ACPI_OPERAND_OBJECT     *SourceDesc,
89     ACPI_OPERAND_OBJECT     *DestDesc,
90     ACPI_WALK_STATE         *WalkState)
91 {
92     ACPI_STATUS             Status = AE_OK;
93     ACPI_OPERAND_OBJECT     *RefDesc = DestDesc;
94
95
96     ACPI_FUNCTION_TRACE_PTR (ExStore, DestDesc);
97
98
99     /* Validate parameters */
100
101     if (!SourceDesc || !DestDesc)
102     {
103         ACPI_ERROR ((AE_INFO, "Null parameter"));
104         return_ACPI_STATUS (AE_AML_NO_OPERAND);
105     }
106
107     /* DestDesc can be either a namespace node or an ACPI object */
108
109     if (ACPI_GET_DESCRIPTOR_TYPE (DestDesc) == ACPI_DESC_TYPE_NAMED)
110     {
111         /*
112          * 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
231 static ACPI_STATUS
232 AcpiExStoreObjectToIndex (
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
409 ACPI_STATUS
410 AcpiExStoreObjectToNode (
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