Home | History | Annotate | Line # | Download | only in namespace
      1 /*******************************************************************************
      2  *
      3  * Module Name: nsobject - Utilities for objects attached to namespace
      4  *                         table entries
      5  *
      6  ******************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2026, 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 MERCHANTABILITY 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     /* Alias nodes point directly to other namespace nodes; skip teardown */
    232     if (Node->Flags & ANOBJ_IS_ALIAS)
    233     {
    234         Node->Object = NULL;
    235         return_VOID;
    236     }
    237 
    238     if (!ObjDesc ||
    239         (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA))
    240     {
    241         return_VOID;
    242     }
    243 
    244     if (Node->Flags & ANOBJ_ALLOCATED_BUFFER)
    245     {
    246         /* Free the dynamic aml buffer */
    247 
    248         if (ObjDesc->Common.Type == ACPI_TYPE_METHOD)
    249         {
    250             ACPI_FREE (ObjDesc->Method.AmlStart);
    251         }
    252     }
    253 
    254     if (ObjDesc->Common.Type == ACPI_TYPE_REGION)
    255     {
    256         AcpiUtRemoveAddressRange(ObjDesc->Region.SpaceId, Node);
    257     }
    258 
    259     /* Clear the Node entry in all cases */
    260 
    261     Node->Object = NULL;
    262     if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND)
    263     {
    264         /* Unlink object from front of possible object list */
    265 
    266         Node->Object = ObjDesc->Common.NextObject;
    267 
    268         /* Handle possible 2-descriptor object */
    269 
    270         if (Node->Object &&
    271            (Node->Object->Common.Type != ACPI_TYPE_LOCAL_DATA))
    272         {
    273             Node->Object = Node->Object->Common.NextObject;
    274         }
    275 
    276         /*
    277          * Detach the object from any data objects (which are still held by
    278          * the namespace node)
    279          */
    280         if (ObjDesc->Common.NextObject &&
    281            ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA))
    282         {
    283            ObjDesc->Common.NextObject = NULL;
    284         }
    285     }
    286 
    287     /* Reset the node type to untyped */
    288 
    289     Node->Type = ACPI_TYPE_ANY;
    290 
    291     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
    292         Node, AcpiUtGetNodeName (Node), ObjDesc));
    293 
    294     /* Remove one reference on the object (and all subobjects) */
    295 
    296     AcpiUtRemoveReference (ObjDesc);
    297     return_VOID;
    298 }
    299 
    300 
    301 /*******************************************************************************
    302  *
    303  * FUNCTION:    AcpiNsGetAttachedObject
    304  *
    305  * PARAMETERS:  Node             - Namespace node
    306  *
    307  * RETURN:      Current value of the object field from the Node whose
    308  *              handle is passed
    309  *
    310  * DESCRIPTION: Obtain the object attached to a namespace node.
    311  *
    312  ******************************************************************************/
    313 
    314 ACPI_OPERAND_OBJECT *
    315 AcpiNsGetAttachedObject (
    316     ACPI_NAMESPACE_NODE     *Node)
    317 {
    318     ACPI_FUNCTION_TRACE_PTR (NsGetAttachedObject, Node);
    319 
    320 
    321     if (!Node)
    322     {
    323         ACPI_WARNING ((AE_INFO, "Null Node ptr"));
    324         return_PTR (NULL);
    325     }
    326 
    327     if (!Node->Object ||
    328             ((ACPI_GET_DESCRIPTOR_TYPE (Node->Object) != ACPI_DESC_TYPE_OPERAND) &&
    329              (ACPI_GET_DESCRIPTOR_TYPE (Node->Object) != ACPI_DESC_TYPE_NAMED))  ||
    330         ((Node->Object)->Common.Type == ACPI_TYPE_LOCAL_DATA))
    331     {
    332         return_PTR (NULL);
    333     }
    334 
    335     return_PTR (Node->Object);
    336 }
    337 
    338 
    339 /*******************************************************************************
    340  *
    341  * FUNCTION:    AcpiNsGetSecondaryObject
    342  *
    343  * PARAMETERS:  Node             - Namespace node
    344  *
    345  * RETURN:      Current value of the object field from the Node whose
    346  *              handle is passed.
    347  *
    348  * DESCRIPTION: Obtain a secondary object associated with a namespace node.
    349  *
    350  ******************************************************************************/
    351 
    352 ACPI_OPERAND_OBJECT *
    353 AcpiNsGetSecondaryObject (
    354     ACPI_OPERAND_OBJECT     *ObjDesc)
    355 {
    356     ACPI_FUNCTION_TRACE_PTR (NsGetSecondaryObject, ObjDesc);
    357 
    358 
    359     if ((!ObjDesc)                                     ||
    360         (ObjDesc->Common.Type== ACPI_TYPE_LOCAL_DATA)  ||
    361         (!ObjDesc->Common.NextObject)                  ||
    362         ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA))
    363     {
    364         return_PTR (NULL);
    365     }
    366 
    367     return_PTR (ObjDesc->Common.NextObject);
    368 }
    369 
    370 
    371 /*******************************************************************************
    372  *
    373  * FUNCTION:    AcpiNsAttachData
    374  *
    375  * PARAMETERS:  Node            - Namespace node
    376  *              Handler         - Handler to be associated with the data
    377  *              Data            - Data to be attached
    378  *
    379  * RETURN:      Status
    380  *
    381  * DESCRIPTION: Low-level attach data. Create and attach a Data object.
    382  *
    383  ******************************************************************************/
    384 
    385 ACPI_STATUS
    386 AcpiNsAttachData (
    387     ACPI_NAMESPACE_NODE     *Node,
    388     ACPI_OBJECT_HANDLER     Handler,
    389     void                    *Data)
    390 {
    391     ACPI_OPERAND_OBJECT     *PrevObjDesc;
    392     ACPI_OPERAND_OBJECT     *ObjDesc;
    393     ACPI_OPERAND_OBJECT     *DataDesc;
    394 
    395 
    396     /* We only allow one attachment per handler */
    397 
    398     PrevObjDesc = NULL;
    399     ObjDesc = Node->Object;
    400     while (ObjDesc)
    401     {
    402         if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) &&
    403             (ObjDesc->Data.Handler == Handler))
    404         {
    405             return (AE_ALREADY_EXISTS);
    406         }
    407 
    408         PrevObjDesc = ObjDesc;
    409         ObjDesc = ObjDesc->Common.NextObject;
    410     }
    411 
    412     /* Create an internal object for the data */
    413 
    414     DataDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_DATA);
    415     if (!DataDesc)
    416     {
    417         return (AE_NO_MEMORY);
    418     }
    419 
    420     DataDesc->Data.Handler = Handler;
    421     DataDesc->Data.Pointer = Data;
    422 
    423     /* Install the data object */
    424 
    425     if (PrevObjDesc)
    426     {
    427         PrevObjDesc->Common.NextObject = DataDesc;
    428     }
    429     else
    430     {
    431         Node->Object = DataDesc;
    432     }
    433 
    434     return (AE_OK);
    435 }
    436 
    437 
    438 /*******************************************************************************
    439  *
    440  * FUNCTION:    AcpiNsDetachData
    441  *
    442  * PARAMETERS:  Node            - Namespace node
    443  *              Handler         - Handler associated with the data
    444  *
    445  * RETURN:      Status
    446  *
    447  * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
    448  *              is responsible for the actual data.
    449  *
    450  ******************************************************************************/
    451 
    452 ACPI_STATUS
    453 AcpiNsDetachData (
    454     ACPI_NAMESPACE_NODE     *Node,
    455     ACPI_OBJECT_HANDLER     Handler)
    456 {
    457     ACPI_OPERAND_OBJECT     *ObjDesc;
    458     ACPI_OPERAND_OBJECT     *PrevObjDesc;
    459 
    460 
    461     PrevObjDesc = NULL;
    462     ObjDesc = Node->Object;
    463     while (ObjDesc)
    464     {
    465         if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) &&
    466             (ObjDesc->Data.Handler == Handler))
    467         {
    468             if (PrevObjDesc)
    469             {
    470                 PrevObjDesc->Common.NextObject = ObjDesc->Common.NextObject;
    471             }
    472             else
    473             {
    474                 Node->Object = ObjDesc->Common.NextObject;
    475             }
    476 
    477             AcpiUtRemoveReference (ObjDesc);
    478             return (AE_OK);
    479         }
    480 
    481         PrevObjDesc = ObjDesc;
    482         ObjDesc = ObjDesc->Common.NextObject;
    483     }
    484 
    485     return (AE_NOT_FOUND);
    486 }
    487 
    488 
    489 /*******************************************************************************
    490  *
    491  * FUNCTION:    AcpiNsGetAttachedData
    492  *
    493  * PARAMETERS:  Node            - Namespace node
    494  *              Handler         - Handler associated with the data
    495  *              Data            - Where the data is returned
    496  *
    497  * RETURN:      Status
    498  *
    499  * DESCRIPTION: Low level interface to obtain data previously associated with
    500  *              a namespace node.
    501  *
    502  ******************************************************************************/
    503 
    504 ACPI_STATUS
    505 AcpiNsGetAttachedData (
    506     ACPI_NAMESPACE_NODE     *Node,
    507     ACPI_OBJECT_HANDLER     Handler,
    508     void                    **Data)
    509 {
    510     ACPI_OPERAND_OBJECT     *ObjDesc;
    511 
    512 
    513     ObjDesc = Node->Object;
    514     while (ObjDesc)
    515     {
    516         if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) &&
    517             (ObjDesc->Data.Handler == Handler))
    518         {
    519             *Data = ObjDesc->Data.Pointer;
    520             return (AE_OK);
    521         }
    522 
    523         ObjDesc = ObjDesc->Common.NextObject;
    524     }
    525 
    526     return (AE_NOT_FOUND);
    527 }
    528