Branch data Line data Source code
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 : 2926 : acpi_ns_attach_object(struct acpi_namespace_node *node, 38 : : union acpi_operand_object *object, acpi_object_type type) 39 : : { 40 : 2926 : union acpi_operand_object *obj_desc; 41 : 2926 : union acpi_operand_object *last_obj_desc; 42 : 2926 : acpi_object_type object_type = ACPI_TYPE_ANY; 43 : : 44 : 2926 : ACPI_FUNCTION_TRACE(ns_attach_object); 45 : : 46 : : /* 47 : : * Parameter validation 48 : : */ 49 [ - + ]: 2926 : if (!node) { 50 : : 51 : : /* Invalid handle */ 52 : : 53 : 0 : ACPI_ERROR((AE_INFO, "Null NamedObj handle")); 54 : 0 : return_ACPI_STATUS(AE_BAD_PARAMETER); 55 : : } 56 : : 57 [ - + ]: 2926 : if (!object && (ACPI_TYPE_ANY != type)) { 58 : : 59 : : /* Null object */ 60 : : 61 : 0 : ACPI_ERROR((AE_INFO, 62 : : "Null object, but type not ACPI_TYPE_ANY")); 63 : 0 : return_ACPI_STATUS(AE_BAD_PARAMETER); 64 : : } 65 : : 66 [ - + ]: 2926 : if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { 67 : : 68 : : /* Not a name handle */ 69 : : 70 : 0 : ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]", 71 : : node, acpi_ut_get_descriptor_name(node))); 72 : 0 : return_ACPI_STATUS(AE_BAD_PARAMETER); 73 : : } 74 : : 75 : : /* Check if this object is already attached */ 76 : : 77 [ + - ]: 2926 : 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 [ + - ]: 2926 : 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 [ - + ]: 2926 : else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) && 97 [ # # ]: 0 : ((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 : 0 : obj_desc = ((struct acpi_namespace_node *)object)->object; 103 : 0 : 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 : 2926 : obj_desc, node, acpi_ut_get_node_name(node))); 120 : : 121 : : /* Detach an existing attached object if present */ 122 : : 123 [ + + ]: 2926 : if (node->object) { 124 : 99 : acpi_ns_detach_object(node); 125 : : } 126 : : 127 [ + - ]: 2926 : if (obj_desc) { 128 : : /* 129 : : * Must increment the new value's reference count 130 : : * (if it is an internal object) 131 : : */ 132 : 2926 : 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 : 2926 : last_obj_desc = obj_desc; 139 [ + + ]: 3124 : 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 : 2926 : last_obj_desc->common.next_object = node->object; 146 : : } 147 : : 148 : 2926 : node->type = (u8) object_type; 149 : 2926 : node->object = obj_desc; 150 : : 151 : 2926 : 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 : 1188 : void acpi_ns_detach_object(struct acpi_namespace_node *node) 169 : : { 170 : 1188 : union acpi_operand_object *obj_desc; 171 : : 172 : 1188 : ACPI_FUNCTION_TRACE(ns_detach_object); 173 : : 174 : 1188 : obj_desc = node->object; 175 : : 176 [ + + + + ]: 1188 : if (!obj_desc || (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { 177 : : return_VOID; 178 : : } 179 : : 180 [ - + ]: 880 : if (node->flags & ANOBJ_ALLOCATED_BUFFER) { 181 : : 182 : : /* Free the dynamic aml buffer */ 183 : : 184 [ # # ]: 0 : if (obj_desc->common.type == ACPI_TYPE_METHOD) { 185 : 0 : ACPI_FREE(obj_desc->method.aml_start); 186 : : } 187 : : } 188 : : 189 [ - + ]: 880 : if (obj_desc->common.type == ACPI_TYPE_REGION) { 190 : 0 : acpi_ut_remove_address_range(obj_desc->region.space_id, node); 191 : : } 192 : : 193 : : /* Clear the Node entry in all cases */ 194 : : 195 : 880 : node->object = NULL; 196 [ + - ]: 880 : if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) { 197 : : 198 : : /* Unlink object from front of possible object list */ 199 : : 200 : 880 : node->object = obj_desc->common.next_object; 201 : : 202 : : /* Handle possible 2-descriptor object */ 203 : : 204 [ + + ]: 880 : if (node->object && 205 [ + - ]: 110 : (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) { 206 : 110 : 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 [ + + ]: 880 : if (obj_desc->common.next_object && 214 [ - + ]: 110 : ((obj_desc->common.next_object)->common.type == 215 : : ACPI_TYPE_LOCAL_DATA)) { 216 : 0 : obj_desc->common.next_object = NULL; 217 : : } 218 : : } 219 : : 220 : : /* Reset the node type to untyped */ 221 : : 222 : 880 : node->type = ACPI_TYPE_ANY; 223 : : 224 : : ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n", 225 : 880 : node, acpi_ut_get_node_name(node), obj_desc)); 226 : : 227 : : /* Remove one reference on the object (and all subobjects) */ 228 : : 229 : 880 : acpi_ut_remove_reference(obj_desc); 230 : 880 : 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 : 51865 : union acpi_operand_object *acpi_ns_get_attached_object(struct 247 : : acpi_namespace_node 248 : : *node) 249 : : { 250 : 51865 : ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node); 251 : : 252 [ - + ]: 51865 : if (!node) { 253 : 0 : ACPI_WARNING((AE_INFO, "Null Node ptr")); 254 : 0 : return_PTR(NULL); 255 : : } 256 : : 257 [ + + ]: 51865 : if (!node->object || 258 : 47432 : ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND) 259 [ + - ]: 47432 : && (ACPI_GET_DESCRIPTOR_TYPE(node->object) != 260 : : ACPI_DESC_TYPE_NAMED)) 261 [ + + ]: 47432 : || ((node->object)->common.type == ACPI_TYPE_LOCAL_DATA)) { 262 : 7425 : 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 : 946 : union acpi_operand_object *acpi_ns_get_secondary_object(union 282 : : acpi_operand_object 283 : : *obj_desc) 284 : : { 285 : 946 : ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc); 286 : : 287 [ + - ]: 946 : if ((!obj_desc) || 288 [ + - ]: 946 : (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) || 289 [ + - ]: 946 : (!obj_desc->common.next_object) || 290 [ - + ]: 946 : ((obj_desc->common.next_object)->common.type == 291 : : ACPI_TYPE_LOCAL_DATA)) { 292 : 0 : 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 : 627 : acpi_ns_attach_data(struct acpi_namespace_node *node, 314 : : acpi_object_handler handler, void *data) 315 : : { 316 : 627 : union acpi_operand_object *prev_obj_desc; 317 : 627 : union acpi_operand_object *obj_desc; 318 : 627 : union acpi_operand_object *data_desc; 319 : : 320 : : /* We only allow one attachment per handler */ 321 : : 322 : 627 : prev_obj_desc = NULL; 323 : 627 : obj_desc = node->object; 324 [ + + ]: 649 : while (obj_desc) { 325 [ - + ]: 22 : if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && 326 [ # # ]: 0 : (obj_desc->data.handler == handler)) { 327 : : return (AE_ALREADY_EXISTS); 328 : : } 329 : : 330 : 22 : prev_obj_desc = obj_desc; 331 : 22 : obj_desc = obj_desc->common.next_object; 332 : : } 333 : : 334 : : /* Create an internal object for the data */ 335 : : 336 : 627 : data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA); 337 [ + - ]: 627 : if (!data_desc) { 338 : : return (AE_NO_MEMORY); 339 : : } 340 : : 341 : 627 : data_desc->data.handler = handler; 342 : 627 : data_desc->data.pointer = data; 343 : : 344 : : /* Install the data object */ 345 : : 346 [ + + ]: 627 : if (prev_obj_desc) { 347 : 22 : prev_obj_desc->common.next_object = data_desc; 348 : : } else { 349 : 605 : 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 : 0 : acpi_ns_detach_data(struct acpi_namespace_node *node, 371 : : acpi_object_handler handler) 372 : : { 373 : 0 : union acpi_operand_object *obj_desc; 374 : 0 : union acpi_operand_object *prev_obj_desc; 375 : : 376 : 0 : prev_obj_desc = NULL; 377 : 0 : obj_desc = node->object; 378 [ # # ]: 0 : while (obj_desc) { 379 [ # # ]: 0 : if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && 380 [ # # ]: 0 : (obj_desc->data.handler == handler)) { 381 [ # # ]: 0 : if (prev_obj_desc) { 382 : 0 : prev_obj_desc->common.next_object = 383 : 0 : obj_desc->common.next_object; 384 : : } else { 385 : 0 : node->object = obj_desc->common.next_object; 386 : : } 387 : : 388 : 0 : acpi_ut_remove_reference(obj_desc); 389 : 0 : return (AE_OK); 390 : : } 391 : : 392 : 0 : prev_obj_desc = obj_desc; 393 : 0 : 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 : 5005 : acpi_ns_get_attached_data(struct acpi_namespace_node *node, 416 : : acpi_object_handler handler, void **data) 417 : : { 418 : 5005 : union acpi_operand_object *obj_desc; 419 : : 420 : 5005 : obj_desc = node->object; 421 [ + + ]: 8316 : while (obj_desc) { 422 [ + + ]: 5060 : if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && 423 [ + - ]: 1749 : (obj_desc->data.handler == handler)) { 424 : 1749 : *data = obj_desc->data.pointer; 425 : 1749 : return (AE_OK); 426 : : } 427 : : 428 : 3311 : obj_desc = obj_desc->common.next_object; 429 : : } 430 : : 431 : : return (AE_NOT_FOUND); 432 : : }