Sync ACPICA with Intel's version 20140828.
[dragonfly.git] / sys / contrib / dev / acpica / source / components / namespace / nsobject.c
1 /*******************************************************************************
2  *
3  * Module Name: nsobject - Utilities for objects attached to namespace
4  *                         table entries
5  *
6  ******************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2014, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44
45 #define __NSOBJECT_C__
46
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "acnamesp.h"
50
51
52 #define _COMPONENT          ACPI_NAMESPACE
53         ACPI_MODULE_NAME    ("nsobject")
54
55
56 /*******************************************************************************
57  *
58  * FUNCTION:    AcpiNsAttachObject
59  *
60  * PARAMETERS:  Node                - Parent Node
61  *              Object              - Object to be attached
62  *              Type                - Type of object, or ACPI_TYPE_ANY if not
63  *                                    known
64  *
65  * RETURN:      Status
66  *
67  * DESCRIPTION: Record the given object as the value associated with the
68  *              name whose ACPI_HANDLE is passed. If Object is NULL
69  *              and Type is ACPI_TYPE_ANY, set the name as having no value.
70  *              Note: Future may require that the Node->Flags field be passed
71  *              as a parameter.
72  *
73  * MUTEX:       Assumes namespace is locked
74  *
75  ******************************************************************************/
76
77 ACPI_STATUS
78 AcpiNsAttachObject (
79     ACPI_NAMESPACE_NODE     *Node,
80     ACPI_OPERAND_OBJECT     *Object,
81     ACPI_OBJECT_TYPE        Type)
82 {
83     ACPI_OPERAND_OBJECT     *ObjDesc;
84     ACPI_OPERAND_OBJECT     *LastObjDesc;
85     ACPI_OBJECT_TYPE        ObjectType = ACPI_TYPE_ANY;
86
87
88     ACPI_FUNCTION_TRACE (NsAttachObject);
89
90
91     /*
92      * Parameter validation
93      */
94     if (!Node)
95     {
96         /* Invalid handle */
97
98         ACPI_ERROR ((AE_INFO, "Null NamedObj handle"));
99         return_ACPI_STATUS (AE_BAD_PARAMETER);
100     }
101
102     if (!Object && (ACPI_TYPE_ANY != Type))
103     {
104         /* Null object */
105
106         ACPI_ERROR ((AE_INFO,
107             "Null object, but type not ACPI_TYPE_ANY"));
108         return_ACPI_STATUS (AE_BAD_PARAMETER);
109     }
110
111     if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
112     {
113         /* Not a name handle */
114
115         ACPI_ERROR ((AE_INFO, "Invalid handle %p [%s]",
116             Node, AcpiUtGetDescriptorName (Node)));
117         return_ACPI_STATUS (AE_BAD_PARAMETER);
118     }
119
120     /* Check if this object is already attached */
121
122     if (Node->Object == Object)
123     {
124         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
125             "Obj %p already installed in NameObj %p\n",
126             Object, Node));
127
128         return_ACPI_STATUS (AE_OK);
129     }
130
131     /* If null object, we will just install it */
132
133     if (!Object)
134     {
135         ObjDesc    = NULL;
136         ObjectType = ACPI_TYPE_ANY;
137     }
138
139     /*
140      * If the source object is a namespace Node with an attached object,
141      * we will use that (attached) object
142      */
143     else if ((ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) &&
144             ((ACPI_NAMESPACE_NODE *) Object)->Object)
145     {
146         /*
147          * Value passed is a name handle and that name has a
148          * non-null value. Use that name's value and type.
149          */
150         ObjDesc    = ((ACPI_NAMESPACE_NODE *) Object)->Object;
151         ObjectType = ((ACPI_NAMESPACE_NODE *) Object)->Type;
152     }
153
154     /*
155      * Otherwise, we will use the parameter object, but we must type
156      * it first
157      */
158     else
159     {
160         ObjDesc = (ACPI_OPERAND_OBJECT  *) Object;
161
162         /* Use the given type */
163
164         ObjectType = Type;
165     }
166
167     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
168         ObjDesc, Node, AcpiUtGetNodeName (Node)));
169
170     /* Detach an existing attached object if present */
171
172     if (Node->Object)
173     {
174         AcpiNsDetachObject (Node);
175     }
176
177     if (ObjDesc)
178     {
179         /*
180          * Must increment the new value's reference count
181          * (if it is an internal object)
182          */
183         AcpiUtAddReference (ObjDesc);
184
185         /*
186          * Handle objects with multiple descriptors - walk
187          * to the end of the descriptor list
188          */
189         LastObjDesc = ObjDesc;
190         while (LastObjDesc->Common.NextObject)
191         {
192             LastObjDesc = LastObjDesc->Common.NextObject;
193         }
194
195         /* Install the object at the front of the object list */
196
197         LastObjDesc->Common.NextObject = Node->Object;
198     }
199
200     Node->Type     = (UINT8) ObjectType;
201     Node->Object   = ObjDesc;
202
203     return_ACPI_STATUS (AE_OK);
204 }
205
206
207 /*******************************************************************************
208  *
209  * FUNCTION:    AcpiNsDetachObject
210  *
211  * PARAMETERS:  Node           - A Namespace node whose object will be detached
212  *
213  * RETURN:      None.
214  *
215  * DESCRIPTION: Detach/delete an object associated with a namespace node.
216  *              if the object is an allocated object, it is freed.
217  *              Otherwise, the field is simply cleared.
218  *
219  ******************************************************************************/
220
221 void
222 AcpiNsDetachObject (
223     ACPI_NAMESPACE_NODE     *Node)
224 {
225     ACPI_OPERAND_OBJECT     *ObjDesc;
226
227
228     ACPI_FUNCTION_TRACE (NsDetachObject);
229
230
231     ObjDesc = Node->Object;
232
233     if (!ObjDesc ||
234         (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA))
235     {
236         return_VOID;
237     }
238
239     if (Node->Flags & ANOBJ_ALLOCATED_BUFFER)
240     {
241         /* Free the dynamic aml buffer */
242
243         if (ObjDesc->Common.Type == ACPI_TYPE_METHOD)
244         {
245             ACPI_FREE (ObjDesc->Method.AmlStart);
246         }
247     }
248
249     /* Clear the Node entry in all cases */
250
251     Node->Object = NULL;
252     if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND)
253     {
254         /* Unlink object from front of possible object list */
255
256         Node->Object = ObjDesc->Common.NextObject;
257
258         /* Handle possible 2-descriptor object */
259
260         if (Node->Object &&
261            (Node->Object->Common.Type != ACPI_TYPE_LOCAL_DATA))
262         {
263             Node->Object = Node->Object->Common.NextObject;
264         }
265
266         /*
267          * Detach the object from any data objects (which are still held by
268          * the namespace node)
269          */
270         if (ObjDesc->Common.NextObject &&
271            ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA))
272         {
273            ObjDesc->Common.NextObject = NULL;
274         }
275     }
276
277     /* Reset the node type to untyped */
278
279     Node->Type = ACPI_TYPE_ANY;
280
281     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
282         Node, AcpiUtGetNodeName (Node), ObjDesc));
283
284     /* Remove one reference on the object (and all subobjects) */
285
286     AcpiUtRemoveReference (ObjDesc);
287     return_VOID;
288 }
289
290
291 /*******************************************************************************
292  *
293  * FUNCTION:    AcpiNsGetAttachedObject
294  *
295  * PARAMETERS:  Node             - Namespace node
296  *
297  * RETURN:      Current value of the object field from the Node whose
298  *              handle is passed
299  *
300  * DESCRIPTION: Obtain the object attached to a namespace node.
301  *
302  ******************************************************************************/
303
304 ACPI_OPERAND_OBJECT *
305 AcpiNsGetAttachedObject (
306     ACPI_NAMESPACE_NODE     *Node)
307 {
308     ACPI_FUNCTION_TRACE_PTR (NsGetAttachedObject, Node);
309
310
311     if (!Node)
312     {
313         ACPI_WARNING ((AE_INFO, "Null Node ptr"));
314         return_PTR (NULL);
315     }
316
317     if (!Node->Object ||
318             ((ACPI_GET_DESCRIPTOR_TYPE (Node->Object) != ACPI_DESC_TYPE_OPERAND) &&
319              (ACPI_GET_DESCRIPTOR_TYPE (Node->Object) != ACPI_DESC_TYPE_NAMED))  ||
320         ((Node->Object)->Common.Type == ACPI_TYPE_LOCAL_DATA))
321     {
322         return_PTR (NULL);
323     }
324
325     return_PTR (Node->Object);
326 }
327
328
329 /*******************************************************************************
330  *
331  * FUNCTION:    AcpiNsGetSecondaryObject
332  *
333  * PARAMETERS:  Node             - Namespace node
334  *
335  * RETURN:      Current value of the object field from the Node whose
336  *              handle is passed.
337  *
338  * DESCRIPTION: Obtain a secondary object associated with a namespace node.
339  *
340  ******************************************************************************/
341
342 ACPI_OPERAND_OBJECT *
343 AcpiNsGetSecondaryObject (
344     ACPI_OPERAND_OBJECT     *ObjDesc)
345 {
346     ACPI_FUNCTION_TRACE_PTR (NsGetSecondaryObject, ObjDesc);
347
348
349     if ((!ObjDesc)                                     ||
350         (ObjDesc->Common.Type== ACPI_TYPE_LOCAL_DATA)  ||
351         (!ObjDesc->Common.NextObject)                  ||
352         ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA))
353     {
354         return_PTR (NULL);
355     }
356
357     return_PTR (ObjDesc->Common.NextObject);
358 }
359
360
361 /*******************************************************************************
362  *
363  * FUNCTION:    AcpiNsAttachData
364  *
365  * PARAMETERS:  Node            - Namespace node
366  *              Handler         - Handler to be associated with the data
367  *              Data            - Data to be attached
368  *
369  * RETURN:      Status
370  *
371  * DESCRIPTION: Low-level attach data. Create and attach a Data object.
372  *
373  ******************************************************************************/
374
375 ACPI_STATUS
376 AcpiNsAttachData (
377     ACPI_NAMESPACE_NODE     *Node,
378     ACPI_OBJECT_HANDLER     Handler,
379     void                    *Data)
380 {
381     ACPI_OPERAND_OBJECT     *PrevObjDesc;
382     ACPI_OPERAND_OBJECT     *ObjDesc;
383     ACPI_OPERAND_OBJECT     *DataDesc;
384
385
386     /* We only allow one attachment per handler */
387
388     PrevObjDesc = NULL;
389     ObjDesc = Node->Object;
390     while (ObjDesc)
391     {
392         if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) &&
393             (ObjDesc->Data.Handler == Handler))
394         {
395             return (AE_ALREADY_EXISTS);
396         }
397
398         PrevObjDesc = ObjDesc;
399         ObjDesc = ObjDesc->Common.NextObject;
400     }
401
402     /* Create an internal object for the data */
403
404     DataDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_DATA);
405     if (!DataDesc)
406     {
407         return (AE_NO_MEMORY);
408     }
409
410     DataDesc->Data.Handler = Handler;
411     DataDesc->Data.Pointer = Data;
412
413     /* Install the data object */
414
415     if (PrevObjDesc)
416     {
417         PrevObjDesc->Common.NextObject = DataDesc;
418     }
419     else
420     {
421         Node->Object = DataDesc;
422     }
423
424     return (AE_OK);
425 }
426
427
428 /*******************************************************************************
429  *
430  * FUNCTION:    AcpiNsDetachData
431  *
432  * PARAMETERS:  Node            - Namespace node
433  *              Handler         - Handler associated with the data
434  *
435  * RETURN:      Status
436  *
437  * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
438  *              is responsible for the actual data.
439  *
440  ******************************************************************************/
441
442 ACPI_STATUS
443 AcpiNsDetachData (
444     ACPI_NAMESPACE_NODE     *Node,
445     ACPI_OBJECT_HANDLER     Handler)
446 {
447     ACPI_OPERAND_OBJECT     *ObjDesc;
448     ACPI_OPERAND_OBJECT     *PrevObjDesc;
449
450
451     PrevObjDesc = NULL;
452     ObjDesc = Node->Object;
453     while (ObjDesc)
454     {
455         if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) &&
456             (ObjDesc->Data.Handler == Handler))
457         {
458             if (PrevObjDesc)
459             {
460                 PrevObjDesc->Common.NextObject = ObjDesc->Common.NextObject;
461             }
462             else
463             {
464                 Node->Object = ObjDesc->Common.NextObject;
465             }
466
467             AcpiUtRemoveReference (ObjDesc);
468             return (AE_OK);
469         }
470
471         PrevObjDesc = ObjDesc;
472         ObjDesc = ObjDesc->Common.NextObject;
473     }
474
475     return (AE_NOT_FOUND);
476 }
477
478
479 /*******************************************************************************
480  *
481  * FUNCTION:    AcpiNsGetAttachedData
482  *
483  * PARAMETERS:  Node            - Namespace node
484  *              Handler         - Handler associated with the data
485  *              Data            - Where the data is returned
486  *
487  * RETURN:      Status
488  *
489  * DESCRIPTION: Low level interface to obtain data previously associated with
490  *              a namespace node.
491  *
492  ******************************************************************************/
493
494 ACPI_STATUS
495 AcpiNsGetAttachedData (
496     ACPI_NAMESPACE_NODE     *Node,
497     ACPI_OBJECT_HANDLER     Handler,
498     void                    **Data)
499 {
500     ACPI_OPERAND_OBJECT     *ObjDesc;
501
502
503     ObjDesc = Node->Object;
504     while (ObjDesc)
505     {
506         if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) &&
507             (ObjDesc->Data.Handler == Handler))
508         {
509             *Data = ObjDesc->Data.Pointer;
510             return (AE_OK);
511         }
512
513         ObjDesc = ObjDesc->Common.NextObject;
514     }
515
516     return (AE_NOT_FOUND);
517 }