Home | History | Annotate | Line # | Download | only in namespace
nsobject.c revision 1.1.1.2
      1 /*******************************************************************************
      2  *
      3  * Module Name: nsobject - Utilities for objects attached to namespace
      4  *                         table entries
      5  *
      6  ******************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2011, 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 
     46 #define __NSOBJECT_C__
     47 
     48 #include "acpi.h"
     49 #include "accommon.h"
     50 #include "acnamesp.h"
     51 
     52 
     53 #define _COMPONENT          ACPI_NAMESPACE
     54         ACPI_MODULE_NAME    ("nsobject")
     55 
     56 
     57 /*******************************************************************************
     58  *
     59  * FUNCTION:    AcpiNsAttachObject
     60  *
     61  * PARAMETERS:  Node                - Parent Node
     62  *              Object              - Object to be attached
     63  *              Type                - Type of object, or ACPI_TYPE_ANY if not
     64  *                                    known
     65  *
     66  * RETURN:      Status
     67  *
     68  * DESCRIPTION: Record the given object as the value associated with the
     69  *              name whose ACPI_HANDLE is passed.  If Object is NULL
     70  *              and Type is ACPI_TYPE_ANY, set the name as having no value.
     71  *              Note: Future may require that the Node->Flags field be passed
     72  *              as a parameter.
     73  *
     74  * MUTEX:       Assumes namespace is locked
     75  *
     76  ******************************************************************************/
     77 
     78 ACPI_STATUS
     79 AcpiNsAttachObject (
     80     ACPI_NAMESPACE_NODE     *Node,
     81     ACPI_OPERAND_OBJECT     *Object,
     82     ACPI_OBJECT_TYPE        Type)
     83 {
     84     ACPI_OPERAND_OBJECT     *ObjDesc;
     85     ACPI_OPERAND_OBJECT     *LastObjDesc;
     86     ACPI_OBJECT_TYPE        ObjectType = ACPI_TYPE_ANY;
     87 
     88 
     89     ACPI_FUNCTION_TRACE (NsAttachObject);
     90 
     91 
     92     /*
     93      * Parameter validation
     94      */
     95     if (!Node)
     96     {
     97         /* Invalid handle */
     98 
     99         ACPI_ERROR ((AE_INFO, "Null NamedObj handle"));
    100         return_ACPI_STATUS (AE_BAD_PARAMETER);
    101     }
    102 
    103     if (!Object && (ACPI_TYPE_ANY != Type))
    104     {
    105         /* Null object */
    106 
    107         ACPI_ERROR ((AE_INFO,
    108             "Null object, but type not ACPI_TYPE_ANY"));
    109         return_ACPI_STATUS (AE_BAD_PARAMETER);
    110     }
    111 
    112     if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
    113     {
    114         /* Not a name handle */
    115 
    116         ACPI_ERROR ((AE_INFO, "Invalid handle %p [%s]",
    117             Node, AcpiUtGetDescriptorName (Node)));
    118         return_ACPI_STATUS (AE_BAD_PARAMETER);
    119     }
    120 
    121     /* Check if this object is already attached */
    122 
    123     if (Node->Object == Object)
    124     {
    125         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    126             "Obj %p already installed in NameObj %p\n",
    127             Object, Node));
    128 
    129         return_ACPI_STATUS (AE_OK);
    130     }
    131 
    132     /* If null object, we will just install it */
    133 
    134     if (!Object)
    135     {
    136         ObjDesc    = NULL;
    137         ObjectType = ACPI_TYPE_ANY;
    138     }
    139 
    140     /*
    141      * If the source object is a namespace Node with an attached object,
    142      * we will use that (attached) object
    143      */
    144     else if ((ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) &&
    145             ((ACPI_NAMESPACE_NODE *) Object)->Object)
    146     {
    147         /*
    148          * Value passed is a name handle and that name has a
    149          * non-null value.  Use that name's value and type.
    150          */
    151         ObjDesc    = ((ACPI_NAMESPACE_NODE *) Object)->Object;
    152         ObjectType = ((ACPI_NAMESPACE_NODE *) Object)->Type;
    153     }
    154 
    155     /*
    156      * Otherwise, we will use the parameter object, but we must type
    157      * it first
    158      */
    159     else
    160     {
    161         ObjDesc = (ACPI_OPERAND_OBJECT  *) Object;
    162 
    163         /* Use the given type */
    164 
    165         ObjectType = Type;
    166     }
    167 
    168     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
    169         ObjDesc, Node, AcpiUtGetNodeName (Node)));
    170 
    171     /* Detach an existing attached object if present */
    172 
    173     if (Node->Object)
    174     {
    175         AcpiNsDetachObject (Node);
    176     }
    177 
    178     if (ObjDesc)
    179     {
    180         /*
    181          * Must increment the new value's reference count
    182          * (if it is an internal object)
    183          */
    184         AcpiUtAddReference (ObjDesc);
    185 
    186         /*
    187          * Handle objects with multiple descriptors - walk
    188          * to the end of the descriptor list
    189          */
    190         LastObjDesc = ObjDesc;
    191         while (LastObjDesc->Common.NextObject)
    192         {
    193             LastObjDesc = LastObjDesc->Common.NextObject;
    194         }
    195 
    196         /* Install the object at the front of the object list */
    197 
    198         LastObjDesc->Common.NextObject = Node->Object;
    199     }
    200 
    201     Node->Type     = (UINT8) ObjectType;
    202     Node->Object   = ObjDesc;
    203 
    204     return_ACPI_STATUS (AE_OK);
    205 }
    206 
    207 
    208 /*******************************************************************************
    209  *
    210  * FUNCTION:    AcpiNsDetachObject
    211  *
    212  * PARAMETERS:  Node           - A Namespace node whose object will be detached
    213  *
    214  * RETURN:      None.
    215  *
    216  * DESCRIPTION: Detach/delete an object associated with a namespace node.
    217  *              if the object is an allocated object, it is freed.
    218  *              Otherwise, the field is simply cleared.
    219  *
    220  ******************************************************************************/
    221 
    222 void
    223 AcpiNsDetachObject (
    224     ACPI_NAMESPACE_NODE     *Node)
    225 {
    226     ACPI_OPERAND_OBJECT     *ObjDesc;
    227 
    228 
    229     ACPI_FUNCTION_TRACE (NsDetachObject);
    230 
    231 
    232     ObjDesc = Node->Object;
    233 
    234     if (!ObjDesc ||
    235         (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA))
    236     {
    237         return_VOID;
    238     }
    239 
    240     if (Node->Flags & ANOBJ_ALLOCATED_BUFFER)
    241     {
    242         /* Free the dynamic aml buffer */
    243 
    244         if (ObjDesc->Common.Type == ACPI_TYPE_METHOD)
    245         {
    246             ACPI_FREE (ObjDesc->Method.AmlStart);
    247         }
    248     }
    249 
    250     /* Clear the entry in all cases */
    251 
    252     Node->Object = NULL;
    253     if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND)
    254     {
    255         Node->Object = ObjDesc->Common.NextObject;
    256         if (Node->Object &&
    257            ((Node->Object)->Common.Type != ACPI_TYPE_LOCAL_DATA))
    258         {
    259             Node->Object = Node->Object->Common.NextObject;
    260         }
    261     }
    262 
    263     /* Reset the node type to untyped */
    264 
    265     Node->Type = ACPI_TYPE_ANY;
    266 
    267     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
    268         Node, AcpiUtGetNodeName (Node), ObjDesc));
    269 
    270     /* Remove one reference on the object (and all subobjects) */
    271 
    272     AcpiUtRemoveReference (ObjDesc);
    273     return_VOID;
    274 }
    275 
    276 
    277 /*******************************************************************************
    278  *
    279  * FUNCTION:    AcpiNsGetAttachedObject
    280  *
    281  * PARAMETERS:  Node             - Namespace node
    282  *
    283  * RETURN:      Current value of the object field from the Node whose
    284  *              handle is passed
    285  *
    286  * DESCRIPTION: Obtain the object attached to a namespace node.
    287  *
    288  ******************************************************************************/
    289 
    290 ACPI_OPERAND_OBJECT *
    291 AcpiNsGetAttachedObject (
    292     ACPI_NAMESPACE_NODE     *Node)
    293 {
    294     ACPI_FUNCTION_TRACE_PTR (NsGetAttachedObject, Node);
    295 
    296 
    297     if (!Node)
    298     {
    299         ACPI_WARNING ((AE_INFO, "Null Node ptr"));
    300         return_PTR (NULL);
    301     }
    302 
    303     if (!Node->Object ||
    304             ((ACPI_GET_DESCRIPTOR_TYPE (Node->Object) != ACPI_DESC_TYPE_OPERAND) &&
    305              (ACPI_GET_DESCRIPTOR_TYPE (Node->Object) != ACPI_DESC_TYPE_NAMED))  ||
    306         ((Node->Object)->Common.Type == ACPI_TYPE_LOCAL_DATA))
    307     {
    308         return_PTR (NULL);
    309     }
    310 
    311     return_PTR (Node->Object);
    312 }
    313 
    314 
    315 /*******************************************************************************
    316  *
    317  * FUNCTION:    AcpiNsGetSecondaryObject
    318  *
    319  * PARAMETERS:  Node             - Namespace node
    320  *
    321  * RETURN:      Current value of the object field from the Node whose
    322  *              handle is passed.
    323  *
    324  * DESCRIPTION: Obtain a secondary object associated with a namespace node.
    325  *
    326  ******************************************************************************/
    327 
    328 ACPI_OPERAND_OBJECT *
    329 AcpiNsGetSecondaryObject (
    330     ACPI_OPERAND_OBJECT     *ObjDesc)
    331 {
    332     ACPI_FUNCTION_TRACE_PTR (NsGetSecondaryObject, ObjDesc);
    333 
    334 
    335     if ((!ObjDesc)                                     ||
    336         (ObjDesc->Common.Type== ACPI_TYPE_LOCAL_DATA)  ||
    337         (!ObjDesc->Common.NextObject)                  ||
    338         ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA))
    339     {
    340         return_PTR (NULL);
    341     }
    342 
    343     return_PTR (ObjDesc->Common.NextObject);
    344 }
    345 
    346 
    347 /*******************************************************************************
    348  *
    349  * FUNCTION:    AcpiNsAttachData
    350  *
    351  * PARAMETERS:  Node            - Namespace node
    352  *              Handler         - Handler to be associated with the data
    353  *              Data            - Data to be attached
    354  *
    355  * RETURN:      Status
    356  *
    357  * DESCRIPTION: Low-level attach data.  Create and attach a Data object.
    358  *
    359  ******************************************************************************/
    360 
    361 ACPI_STATUS
    362 AcpiNsAttachData (
    363     ACPI_NAMESPACE_NODE     *Node,
    364     ACPI_OBJECT_HANDLER     Handler,
    365     void                    *Data)
    366 {
    367     ACPI_OPERAND_OBJECT     *PrevObjDesc;
    368     ACPI_OPERAND_OBJECT     *ObjDesc;
    369     ACPI_OPERAND_OBJECT     *DataDesc;
    370 
    371 
    372     /* We only allow one attachment per handler */
    373 
    374     PrevObjDesc = NULL;
    375     ObjDesc = Node->Object;
    376     while (ObjDesc)
    377     {
    378         if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) &&
    379             (ObjDesc->Data.Handler == Handler))
    380         {
    381             return (AE_ALREADY_EXISTS);
    382         }
    383 
    384         PrevObjDesc = ObjDesc;
    385         ObjDesc = ObjDesc->Common.NextObject;
    386     }
    387 
    388     /* Create an internal object for the data */
    389 
    390     DataDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_DATA);
    391     if (!DataDesc)
    392     {
    393         return (AE_NO_MEMORY);
    394     }
    395 
    396     DataDesc->Data.Handler = Handler;
    397     DataDesc->Data.Pointer = Data;
    398 
    399     /* Install the data object */
    400 
    401     if (PrevObjDesc)
    402     {
    403         PrevObjDesc->Common.NextObject = DataDesc;
    404     }
    405     else
    406     {
    407         Node->Object = DataDesc;
    408     }
    409 
    410     return (AE_OK);
    411 }
    412 
    413 
    414 /*******************************************************************************
    415  *
    416  * FUNCTION:    AcpiNsDetachData
    417  *
    418  * PARAMETERS:  Node            - Namespace node
    419  *              Handler         - Handler associated with the data
    420  *
    421  * RETURN:      Status
    422  *
    423  * DESCRIPTION: Low-level detach data.  Delete the data node, but the caller
    424  *              is responsible for the actual data.
    425  *
    426  ******************************************************************************/
    427 
    428 ACPI_STATUS
    429 AcpiNsDetachData (
    430     ACPI_NAMESPACE_NODE     *Node,
    431     ACPI_OBJECT_HANDLER     Handler)
    432 {
    433     ACPI_OPERAND_OBJECT     *ObjDesc;
    434     ACPI_OPERAND_OBJECT     *PrevObjDesc;
    435 
    436 
    437     PrevObjDesc = NULL;
    438     ObjDesc = Node->Object;
    439     while (ObjDesc)
    440     {
    441         if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) &&
    442             (ObjDesc->Data.Handler == Handler))
    443         {
    444             if (PrevObjDesc)
    445             {
    446                 PrevObjDesc->Common.NextObject = ObjDesc->Common.NextObject;
    447             }
    448             else
    449             {
    450                 Node->Object = ObjDesc->Common.NextObject;
    451             }
    452 
    453             AcpiUtRemoveReference (ObjDesc);
    454             return (AE_OK);
    455         }
    456 
    457         PrevObjDesc = ObjDesc;
    458         ObjDesc = ObjDesc->Common.NextObject;
    459     }
    460 
    461     return (AE_NOT_FOUND);
    462 }
    463 
    464 
    465 /*******************************************************************************
    466  *
    467  * FUNCTION:    AcpiNsGetAttachedData
    468  *
    469  * PARAMETERS:  Node            - Namespace node
    470  *              Handler         - Handler associated with the data
    471  *              Data            - Where the data is returned
    472  *
    473  * RETURN:      Status
    474  *
    475  * DESCRIPTION: Low level interface to obtain data previously associated with
    476  *              a namespace node.
    477  *
    478  ******************************************************************************/
    479 
    480 ACPI_STATUS
    481 AcpiNsGetAttachedData (
    482     ACPI_NAMESPACE_NODE     *Node,
    483     ACPI_OBJECT_HANDLER     Handler,
    484     void                    **Data)
    485 {
    486     ACPI_OPERAND_OBJECT     *ObjDesc;
    487 
    488 
    489     ObjDesc = Node->Object;
    490     while (ObjDesc)
    491     {
    492         if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) &&
    493             (ObjDesc->Data.Handler == Handler))
    494         {
    495             *Data = ObjDesc->Data.Pointer;
    496             return (AE_OK);
    497         }
    498 
    499         ObjDesc = ObjDesc->Common.NextObject;
    500     }
    501 
    502     return (AE_NOT_FOUND);
    503 }
    504 
    505 
    506