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