Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /*******************************************************************************
0003  *
0004  * Module Name: nsobject - Utilities for objects attached to namespace
0005  *                         table entries
0006  *
0007  ******************************************************************************/
0008 
0009 #include <acpi/acpi.h>
0010 #include "accommon.h"
0011 #include "acnamesp.h"
0012 
0013 #define _COMPONENT          ACPI_NAMESPACE
0014 ACPI_MODULE_NAME("nsobject")
0015 
0016 /*******************************************************************************
0017  *
0018  * FUNCTION:    acpi_ns_attach_object
0019  *
0020  * PARAMETERS:  node                - Parent Node
0021  *              object              - Object to be attached
0022  *              type                - Type of object, or ACPI_TYPE_ANY if not
0023  *                                    known
0024  *
0025  * RETURN:      Status
0026  *
0027  * DESCRIPTION: Record the given object as the value associated with the
0028  *              name whose acpi_handle is passed. If Object is NULL
0029  *              and Type is ACPI_TYPE_ANY, set the name as having no value.
0030  *              Note: Future may require that the Node->Flags field be passed
0031  *              as a parameter.
0032  *
0033  * MUTEX:       Assumes namespace is locked
0034  *
0035  ******************************************************************************/
0036 acpi_status
0037 acpi_ns_attach_object(struct acpi_namespace_node *node,
0038               union acpi_operand_object *object, acpi_object_type type)
0039 {
0040     union acpi_operand_object *obj_desc;
0041     union acpi_operand_object *last_obj_desc;
0042     acpi_object_type object_type = ACPI_TYPE_ANY;
0043 
0044     ACPI_FUNCTION_TRACE(ns_attach_object);
0045 
0046     /*
0047      * Parameter validation
0048      */
0049     if (!node) {
0050 
0051         /* Invalid handle */
0052 
0053         ACPI_ERROR((AE_INFO, "Null NamedObj handle"));
0054         return_ACPI_STATUS(AE_BAD_PARAMETER);
0055     }
0056 
0057     if (!object && (ACPI_TYPE_ANY != type)) {
0058 
0059         /* Null object */
0060 
0061         ACPI_ERROR((AE_INFO,
0062                 "Null object, but type not ACPI_TYPE_ANY"));
0063         return_ACPI_STATUS(AE_BAD_PARAMETER);
0064     }
0065 
0066     if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
0067 
0068         /* Not a name handle */
0069 
0070         ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
0071                 node, acpi_ut_get_descriptor_name(node)));
0072         return_ACPI_STATUS(AE_BAD_PARAMETER);
0073     }
0074 
0075     /* Check if this object is already attached */
0076 
0077     if (node->object == object) {
0078         ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0079                   "Obj %p already installed in NameObj %p\n",
0080                   object, node));
0081 
0082         return_ACPI_STATUS(AE_OK);
0083     }
0084 
0085     /* If null object, we will just install it */
0086 
0087     if (!object) {
0088         obj_desc = NULL;
0089         object_type = ACPI_TYPE_ANY;
0090     }
0091 
0092     /*
0093      * If the source object is a namespace Node with an attached object,
0094      * we will use that (attached) object
0095      */
0096     else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
0097          ((struct acpi_namespace_node *)object)->object) {
0098         /*
0099          * Value passed is a name handle and that name has a
0100          * non-null value. Use that name's value and type.
0101          */
0102         obj_desc = ((struct acpi_namespace_node *)object)->object;
0103         object_type = ((struct acpi_namespace_node *)object)->type;
0104     }
0105 
0106     /*
0107      * Otherwise, we will use the parameter object, but we must type
0108      * it first
0109      */
0110     else {
0111         obj_desc = (union acpi_operand_object *)object;
0112 
0113         /* Use the given type */
0114 
0115         object_type = type;
0116     }
0117 
0118     ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
0119               obj_desc, node, acpi_ut_get_node_name(node)));
0120 
0121     /* Detach an existing attached object if present */
0122 
0123     if (node->object) {
0124         acpi_ns_detach_object(node);
0125     }
0126 
0127     if (obj_desc) {
0128         /*
0129          * Must increment the new value's reference count
0130          * (if it is an internal object)
0131          */
0132         acpi_ut_add_reference(obj_desc);
0133 
0134         /*
0135          * Handle objects with multiple descriptors - walk
0136          * to the end of the descriptor list
0137          */
0138         last_obj_desc = obj_desc;
0139         while (last_obj_desc->common.next_object) {
0140             last_obj_desc = last_obj_desc->common.next_object;
0141         }
0142 
0143         /* Install the object at the front of the object list */
0144 
0145         last_obj_desc->common.next_object = node->object;
0146     }
0147 
0148     node->type = (u8) object_type;
0149     node->object = obj_desc;
0150 
0151     return_ACPI_STATUS(AE_OK);
0152 }
0153 
0154 /*******************************************************************************
0155  *
0156  * FUNCTION:    acpi_ns_detach_object
0157  *
0158  * PARAMETERS:  node           - A Namespace node whose object will be detached
0159  *
0160  * RETURN:      None.
0161  *
0162  * DESCRIPTION: Detach/delete an object associated with a namespace node.
0163  *              if the object is an allocated object, it is freed.
0164  *              Otherwise, the field is simply cleared.
0165  *
0166  ******************************************************************************/
0167 
0168 void acpi_ns_detach_object(struct acpi_namespace_node *node)
0169 {
0170     union acpi_operand_object *obj_desc;
0171 
0172     ACPI_FUNCTION_TRACE(ns_detach_object);
0173 
0174     obj_desc = node->object;
0175 
0176     if (!obj_desc || (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
0177         return_VOID;
0178     }
0179 
0180     if (node->flags & ANOBJ_ALLOCATED_BUFFER) {
0181 
0182         /* Free the dynamic aml buffer */
0183 
0184         if (obj_desc->common.type == ACPI_TYPE_METHOD) {
0185             ACPI_FREE(obj_desc->method.aml_start);
0186         }
0187     }
0188 
0189     if (obj_desc->common.type == ACPI_TYPE_REGION) {
0190         acpi_ut_remove_address_range(obj_desc->region.space_id, node);
0191     }
0192 
0193     /* Clear the Node entry in all cases */
0194 
0195     node->object = NULL;
0196     if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) {
0197 
0198         /* Unlink object from front of possible object list */
0199 
0200         node->object = obj_desc->common.next_object;
0201 
0202         /* Handle possible 2-descriptor object */
0203 
0204         if (node->object &&
0205             (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) {
0206             node->object = node->object->common.next_object;
0207         }
0208 
0209         /*
0210          * Detach the object from any data objects (which are still held by
0211          * the namespace node)
0212          */
0213         if (obj_desc->common.next_object &&
0214             ((obj_desc->common.next_object)->common.type ==
0215              ACPI_TYPE_LOCAL_DATA)) {
0216             obj_desc->common.next_object = NULL;
0217         }
0218     }
0219 
0220     /* Reset the node type to untyped */
0221 
0222     node->type = ACPI_TYPE_ANY;
0223 
0224     ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
0225               node, acpi_ut_get_node_name(node), obj_desc));
0226 
0227     /* Remove one reference on the object (and all subobjects) */
0228 
0229     acpi_ut_remove_reference(obj_desc);
0230     return_VOID;
0231 }
0232 
0233 /*******************************************************************************
0234  *
0235  * FUNCTION:    acpi_ns_get_attached_object
0236  *
0237  * PARAMETERS:  node             - Namespace node
0238  *
0239  * RETURN:      Current value of the object field from the Node whose
0240  *              handle is passed
0241  *
0242  * DESCRIPTION: Obtain the object attached to a namespace node.
0243  *
0244  ******************************************************************************/
0245 
0246 union acpi_operand_object *acpi_ns_get_attached_object(struct
0247                                acpi_namespace_node
0248                                *node)
0249 {
0250     ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node);
0251 
0252     if (!node) {
0253         ACPI_WARNING((AE_INFO, "Null Node ptr"));
0254         return_PTR(NULL);
0255     }
0256 
0257     if (!node->object ||
0258         ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND)
0259          && (ACPI_GET_DESCRIPTOR_TYPE(node->object) !=
0260          ACPI_DESC_TYPE_NAMED))
0261         || ((node->object)->common.type == ACPI_TYPE_LOCAL_DATA)) {
0262         return_PTR(NULL);
0263     }
0264 
0265     return_PTR(node->object);
0266 }
0267 
0268 /*******************************************************************************
0269  *
0270  * FUNCTION:    acpi_ns_get_secondary_object
0271  *
0272  * PARAMETERS:  node             - Namespace node
0273  *
0274  * RETURN:      Current value of the object field from the Node whose
0275  *              handle is passed.
0276  *
0277  * DESCRIPTION: Obtain a secondary object associated with a namespace node.
0278  *
0279  ******************************************************************************/
0280 
0281 union acpi_operand_object *acpi_ns_get_secondary_object(union
0282                             acpi_operand_object
0283                             *obj_desc)
0284 {
0285     ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc);
0286 
0287     if ((!obj_desc) ||
0288         (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) ||
0289         (!obj_desc->common.next_object) ||
0290         ((obj_desc->common.next_object)->common.type ==
0291          ACPI_TYPE_LOCAL_DATA)) {
0292         return_PTR(NULL);
0293     }
0294 
0295     return_PTR(obj_desc->common.next_object);
0296 }
0297 
0298 /*******************************************************************************
0299  *
0300  * FUNCTION:    acpi_ns_attach_data
0301  *
0302  * PARAMETERS:  node            - Namespace node
0303  *              handler         - Handler to be associated with the data
0304  *              data            - Data to be attached
0305  *
0306  * RETURN:      Status
0307  *
0308  * DESCRIPTION: Low-level attach data. Create and attach a Data object.
0309  *
0310  ******************************************************************************/
0311 
0312 acpi_status
0313 acpi_ns_attach_data(struct acpi_namespace_node *node,
0314             acpi_object_handler handler, void *data)
0315 {
0316     union acpi_operand_object *prev_obj_desc;
0317     union acpi_operand_object *obj_desc;
0318     union acpi_operand_object *data_desc;
0319 
0320     /* We only allow one attachment per handler */
0321 
0322     prev_obj_desc = NULL;
0323     obj_desc = node->object;
0324     while (obj_desc) {
0325         if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
0326             (obj_desc->data.handler == handler)) {
0327             return (AE_ALREADY_EXISTS);
0328         }
0329 
0330         prev_obj_desc = obj_desc;
0331         obj_desc = obj_desc->common.next_object;
0332     }
0333 
0334     /* Create an internal object for the data */
0335 
0336     data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA);
0337     if (!data_desc) {
0338         return (AE_NO_MEMORY);
0339     }
0340 
0341     data_desc->data.handler = handler;
0342     data_desc->data.pointer = data;
0343 
0344     /* Install the data object */
0345 
0346     if (prev_obj_desc) {
0347         prev_obj_desc->common.next_object = data_desc;
0348     } else {
0349         node->object = data_desc;
0350     }
0351 
0352     return (AE_OK);
0353 }
0354 
0355 /*******************************************************************************
0356  *
0357  * FUNCTION:    acpi_ns_detach_data
0358  *
0359  * PARAMETERS:  node            - Namespace node
0360  *              handler         - Handler associated with the data
0361  *
0362  * RETURN:      Status
0363  *
0364  * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
0365  *              is responsible for the actual data.
0366  *
0367  ******************************************************************************/
0368 
0369 acpi_status
0370 acpi_ns_detach_data(struct acpi_namespace_node *node,
0371             acpi_object_handler handler)
0372 {
0373     union acpi_operand_object *obj_desc;
0374     union acpi_operand_object *prev_obj_desc;
0375 
0376     prev_obj_desc = NULL;
0377     obj_desc = node->object;
0378     while (obj_desc) {
0379         if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
0380             (obj_desc->data.handler == handler)) {
0381             if (prev_obj_desc) {
0382                 prev_obj_desc->common.next_object =
0383                     obj_desc->common.next_object;
0384             } else {
0385                 node->object = obj_desc->common.next_object;
0386             }
0387 
0388             acpi_ut_remove_reference(obj_desc);
0389             return (AE_OK);
0390         }
0391 
0392         prev_obj_desc = obj_desc;
0393         obj_desc = obj_desc->common.next_object;
0394     }
0395 
0396     return (AE_NOT_FOUND);
0397 }
0398 
0399 /*******************************************************************************
0400  *
0401  * FUNCTION:    acpi_ns_get_attached_data
0402  *
0403  * PARAMETERS:  node            - Namespace node
0404  *              handler         - Handler associated with the data
0405  *              data            - Where the data is returned
0406  *
0407  * RETURN:      Status
0408  *
0409  * DESCRIPTION: Low level interface to obtain data previously associated with
0410  *              a namespace node.
0411  *
0412  ******************************************************************************/
0413 
0414 acpi_status
0415 acpi_ns_get_attached_data(struct acpi_namespace_node *node,
0416               acpi_object_handler handler, void **data)
0417 {
0418     union acpi_operand_object *obj_desc;
0419 
0420     obj_desc = node->object;
0421     while (obj_desc) {
0422         if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
0423             (obj_desc->data.handler == handler)) {
0424             *data = obj_desc->data.pointer;
0425             return (AE_OK);
0426         }
0427 
0428         obj_desc = obj_desc->common.next_object;
0429     }
0430 
0431     return (AE_NOT_FOUND);
0432 }