root/drivers/acpi/acpica/nsobject.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ns_detach_object
  3. acpi_ns_get_attached_object
  4. acpi_ns_get_secondary_object
  5. acpi_ns_attach_data
  6. acpi_ns_detach_data
  7. acpi_ns_get_attached_data

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /*******************************************************************************
   3  *
   4  * Module Name: nsobject - Utilities for objects attached to namespace
   5  *                         table entries
   6  *
   7  ******************************************************************************/
   8 
   9 #include <acpi/acpi.h>
  10 #include "accommon.h"
  11 #include "acnamesp.h"
  12 
  13 #define _COMPONENT          ACPI_NAMESPACE
  14 ACPI_MODULE_NAME("nsobject")
  15 
  16 /*******************************************************************************
  17  *
  18  * FUNCTION:    acpi_ns_attach_object
  19  *
  20  * PARAMETERS:  node                - Parent Node
  21  *              object              - Object to be attached
  22  *              type                - Type of object, or ACPI_TYPE_ANY if not
  23  *                                    known
  24  *
  25  * RETURN:      Status
  26  *
  27  * DESCRIPTION: Record the given object as the value associated with the
  28  *              name whose acpi_handle is passed. If Object is NULL
  29  *              and Type is ACPI_TYPE_ANY, set the name as having no value.
  30  *              Note: Future may require that the Node->Flags field be passed
  31  *              as a parameter.
  32  *
  33  * MUTEX:       Assumes namespace is locked
  34  *
  35  ******************************************************************************/
  36 acpi_status
  37 acpi_ns_attach_object(struct acpi_namespace_node *node,
  38                       union acpi_operand_object *object, acpi_object_type type)
  39 {
  40         union acpi_operand_object *obj_desc;
  41         union acpi_operand_object *last_obj_desc;
  42         acpi_object_type object_type = ACPI_TYPE_ANY;
  43 
  44         ACPI_FUNCTION_TRACE(ns_attach_object);
  45 
  46         /*
  47          * Parameter validation
  48          */
  49         if (!node) {
  50 
  51                 /* Invalid handle */
  52 
  53                 ACPI_ERROR((AE_INFO, "Null NamedObj handle"));
  54                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  55         }
  56 
  57         if (!object && (ACPI_TYPE_ANY != type)) {
  58 
  59                 /* Null object */
  60 
  61                 ACPI_ERROR((AE_INFO,
  62                             "Null object, but type not ACPI_TYPE_ANY"));
  63                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  64         }
  65 
  66         if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
  67 
  68                 /* Not a name handle */
  69 
  70                 ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
  71                             node, acpi_ut_get_descriptor_name(node)));
  72                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  73         }
  74 
  75         /* Check if this object is already attached */
  76 
  77         if (node->object == object) {
  78                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
  79                                   "Obj %p already installed in NameObj %p\n",
  80                                   object, node));
  81 
  82                 return_ACPI_STATUS(AE_OK);
  83         }
  84 
  85         /* If null object, we will just install it */
  86 
  87         if (!object) {
  88                 obj_desc = NULL;
  89                 object_type = ACPI_TYPE_ANY;
  90         }
  91 
  92         /*
  93          * If the source object is a namespace Node with an attached object,
  94          * we will use that (attached) object
  95          */
  96         else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
  97                  ((struct acpi_namespace_node *)object)->object) {
  98                 /*
  99                  * Value passed is a name handle and that name has a
 100                  * non-null value. Use that name's value and type.
 101                  */
 102                 obj_desc = ((struct acpi_namespace_node *)object)->object;
 103                 object_type = ((struct acpi_namespace_node *)object)->type;
 104         }
 105 
 106         /*
 107          * Otherwise, we will use the parameter object, but we must type
 108          * it first
 109          */
 110         else {
 111                 obj_desc = (union acpi_operand_object *)object;
 112 
 113                 /* Use the given type */
 114 
 115                 object_type = type;
 116         }
 117 
 118         ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
 119                           obj_desc, node, acpi_ut_get_node_name(node)));
 120 
 121         /* Detach an existing attached object if present */
 122 
 123         if (node->object) {
 124                 acpi_ns_detach_object(node);
 125         }
 126 
 127         if (obj_desc) {
 128                 /*
 129                  * Must increment the new value's reference count
 130                  * (if it is an internal object)
 131                  */
 132                 acpi_ut_add_reference(obj_desc);
 133 
 134                 /*
 135                  * Handle objects with multiple descriptors - walk
 136                  * to the end of the descriptor list
 137                  */
 138                 last_obj_desc = obj_desc;
 139                 while (last_obj_desc->common.next_object) {
 140                         last_obj_desc = last_obj_desc->common.next_object;
 141                 }
 142 
 143                 /* Install the object at the front of the object list */
 144 
 145                 last_obj_desc->common.next_object = node->object;
 146         }
 147 
 148         node->type = (u8) object_type;
 149         node->object = obj_desc;
 150 
 151         return_ACPI_STATUS(AE_OK);
 152 }
 153 
 154 /*******************************************************************************
 155  *
 156  * FUNCTION:    acpi_ns_detach_object
 157  *
 158  * PARAMETERS:  node           - A Namespace node whose object will be detached
 159  *
 160  * RETURN:      None.
 161  *
 162  * DESCRIPTION: Detach/delete an object associated with a namespace node.
 163  *              if the object is an allocated object, it is freed.
 164  *              Otherwise, the field is simply cleared.
 165  *
 166  ******************************************************************************/
 167 
 168 void acpi_ns_detach_object(struct acpi_namespace_node *node)
 169 {
 170         union acpi_operand_object *obj_desc;
 171 
 172         ACPI_FUNCTION_TRACE(ns_detach_object);
 173 
 174         obj_desc = node->object;
 175 
 176         if (!obj_desc || (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
 177                 return_VOID;
 178         }
 179 
 180         if (node->flags & ANOBJ_ALLOCATED_BUFFER) {
 181 
 182                 /* Free the dynamic aml buffer */
 183 
 184                 if (obj_desc->common.type == ACPI_TYPE_METHOD) {
 185                         ACPI_FREE(obj_desc->method.aml_start);
 186                 }
 187         }
 188 
 189         if (obj_desc->common.type == ACPI_TYPE_REGION) {
 190                 acpi_ut_remove_address_range(obj_desc->region.space_id, node);
 191         }
 192 
 193         /* Clear the Node entry in all cases */
 194 
 195         node->object = NULL;
 196         if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) {
 197 
 198                 /* Unlink object from front of possible object list */
 199 
 200                 node->object = obj_desc->common.next_object;
 201 
 202                 /* Handle possible 2-descriptor object */
 203 
 204                 if (node->object &&
 205                     (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) {
 206                         node->object = node->object->common.next_object;
 207                 }
 208 
 209                 /*
 210                  * Detach the object from any data objects (which are still held by
 211                  * the namespace node)
 212                  */
 213                 if (obj_desc->common.next_object &&
 214                     ((obj_desc->common.next_object)->common.type ==
 215                      ACPI_TYPE_LOCAL_DATA)) {
 216                         obj_desc->common.next_object = NULL;
 217                 }
 218         }
 219 
 220         /* Reset the node type to untyped */
 221 
 222         node->type = ACPI_TYPE_ANY;
 223 
 224         ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
 225                           node, acpi_ut_get_node_name(node), obj_desc));
 226 
 227         /* Remove one reference on the object (and all subobjects) */
 228 
 229         acpi_ut_remove_reference(obj_desc);
 230         return_VOID;
 231 }
 232 
 233 /*******************************************************************************
 234  *
 235  * FUNCTION:    acpi_ns_get_attached_object
 236  *
 237  * PARAMETERS:  node             - Namespace node
 238  *
 239  * RETURN:      Current value of the object field from the Node whose
 240  *              handle is passed
 241  *
 242  * DESCRIPTION: Obtain the object attached to a namespace node.
 243  *
 244  ******************************************************************************/
 245 
 246 union acpi_operand_object *acpi_ns_get_attached_object(struct
 247                                                        acpi_namespace_node
 248                                                        *node)
 249 {
 250         ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node);
 251 
 252         if (!node) {
 253                 ACPI_WARNING((AE_INFO, "Null Node ptr"));
 254                 return_PTR(NULL);
 255         }
 256 
 257         if (!node->object ||
 258             ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND)
 259              && (ACPI_GET_DESCRIPTOR_TYPE(node->object) !=
 260                  ACPI_DESC_TYPE_NAMED))
 261             || ((node->object)->common.type == ACPI_TYPE_LOCAL_DATA)) {
 262                 return_PTR(NULL);
 263         }
 264 
 265         return_PTR(node->object);
 266 }
 267 
 268 /*******************************************************************************
 269  *
 270  * FUNCTION:    acpi_ns_get_secondary_object
 271  *
 272  * PARAMETERS:  node             - Namespace node
 273  *
 274  * RETURN:      Current value of the object field from the Node whose
 275  *              handle is passed.
 276  *
 277  * DESCRIPTION: Obtain a secondary object associated with a namespace node.
 278  *
 279  ******************************************************************************/
 280 
 281 union acpi_operand_object *acpi_ns_get_secondary_object(union
 282                                                         acpi_operand_object
 283                                                         *obj_desc)
 284 {
 285         ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc);
 286 
 287         if ((!obj_desc) ||
 288             (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) ||
 289             (!obj_desc->common.next_object) ||
 290             ((obj_desc->common.next_object)->common.type ==
 291              ACPI_TYPE_LOCAL_DATA)) {
 292                 return_PTR(NULL);
 293         }
 294 
 295         return_PTR(obj_desc->common.next_object);
 296 }
 297 
 298 /*******************************************************************************
 299  *
 300  * FUNCTION:    acpi_ns_attach_data
 301  *
 302  * PARAMETERS:  node            - Namespace node
 303  *              handler         - Handler to be associated with the data
 304  *              data            - Data to be attached
 305  *
 306  * RETURN:      Status
 307  *
 308  * DESCRIPTION: Low-level attach data. Create and attach a Data object.
 309  *
 310  ******************************************************************************/
 311 
 312 acpi_status
 313 acpi_ns_attach_data(struct acpi_namespace_node *node,
 314                     acpi_object_handler handler, void *data)
 315 {
 316         union acpi_operand_object *prev_obj_desc;
 317         union acpi_operand_object *obj_desc;
 318         union acpi_operand_object *data_desc;
 319 
 320         /* We only allow one attachment per handler */
 321 
 322         prev_obj_desc = NULL;
 323         obj_desc = node->object;
 324         while (obj_desc) {
 325                 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
 326                     (obj_desc->data.handler == handler)) {
 327                         return (AE_ALREADY_EXISTS);
 328                 }
 329 
 330                 prev_obj_desc = obj_desc;
 331                 obj_desc = obj_desc->common.next_object;
 332         }
 333 
 334         /* Create an internal object for the data */
 335 
 336         data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA);
 337         if (!data_desc) {
 338                 return (AE_NO_MEMORY);
 339         }
 340 
 341         data_desc->data.handler = handler;
 342         data_desc->data.pointer = data;
 343 
 344         /* Install the data object */
 345 
 346         if (prev_obj_desc) {
 347                 prev_obj_desc->common.next_object = data_desc;
 348         } else {
 349                 node->object = data_desc;
 350         }
 351 
 352         return (AE_OK);
 353 }
 354 
 355 /*******************************************************************************
 356  *
 357  * FUNCTION:    acpi_ns_detach_data
 358  *
 359  * PARAMETERS:  node            - Namespace node
 360  *              handler         - Handler associated with the data
 361  *
 362  * RETURN:      Status
 363  *
 364  * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
 365  *              is responsible for the actual data.
 366  *
 367  ******************************************************************************/
 368 
 369 acpi_status
 370 acpi_ns_detach_data(struct acpi_namespace_node *node,
 371                     acpi_object_handler handler)
 372 {
 373         union acpi_operand_object *obj_desc;
 374         union acpi_operand_object *prev_obj_desc;
 375 
 376         prev_obj_desc = NULL;
 377         obj_desc = node->object;
 378         while (obj_desc) {
 379                 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
 380                     (obj_desc->data.handler == handler)) {
 381                         if (prev_obj_desc) {
 382                                 prev_obj_desc->common.next_object =
 383                                     obj_desc->common.next_object;
 384                         } else {
 385                                 node->object = obj_desc->common.next_object;
 386                         }
 387 
 388                         acpi_ut_remove_reference(obj_desc);
 389                         return (AE_OK);
 390                 }
 391 
 392                 prev_obj_desc = obj_desc;
 393                 obj_desc = obj_desc->common.next_object;
 394         }
 395 
 396         return (AE_NOT_FOUND);
 397 }
 398 
 399 /*******************************************************************************
 400  *
 401  * FUNCTION:    acpi_ns_get_attached_data
 402  *
 403  * PARAMETERS:  node            - Namespace node
 404  *              handler         - Handler associated with the data
 405  *              data            - Where the data is returned
 406  *
 407  * RETURN:      Status
 408  *
 409  * DESCRIPTION: Low level interface to obtain data previously associated with
 410  *              a namespace node.
 411  *
 412  ******************************************************************************/
 413 
 414 acpi_status
 415 acpi_ns_get_attached_data(struct acpi_namespace_node *node,
 416                           acpi_object_handler handler, void **data)
 417 {
 418         union acpi_operand_object *obj_desc;
 419 
 420         obj_desc = node->object;
 421         while (obj_desc) {
 422                 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
 423                     (obj_desc->data.handler == handler)) {
 424                         *data = obj_desc->data.pointer;
 425                         return (AE_OK);
 426                 }
 427 
 428                 obj_desc = obj_desc->common.next_object;
 429         }
 430 
 431         return (AE_NOT_FOUND);
 432 }

/* [<][>][^][v][top][bottom][index][help] */