1 /*******************************************************************************
   2  *
   3  * Module Name: nsobject - Utilities for objects attached to namespace
   4  *                         table entries
   5  *
   6  ******************************************************************************/
   7 
   8 /*
   9  * Copyright (C) 2000 - 2013, 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 }