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 /* Alias nodes point directly to other namespace nodes; skip teardown */ 177 if (node->flags & ANOBJ_IS_ALIAS) { 178 node->object = NULL; 179 return_VOID; 180 } 181 182 if (!obj_desc || (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { 183 return_VOID; 184 } 185 186 if (node->flags & ANOBJ_ALLOCATED_BUFFER) { 187 188 /* Free the dynamic aml buffer */ 189 190 if (obj_desc->common.type == ACPI_TYPE_METHOD) { 191 ACPI_FREE(obj_desc->method.aml_start); 192 } 193 } 194 195 if (obj_desc->common.type == ACPI_TYPE_REGION) { 196 acpi_ut_remove_address_range(obj_desc->region.space_id, node); 197 } 198 199 /* Clear the Node entry in all cases */ 200 201 node->object = NULL; 202 if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) { 203 204 /* Unlink object from front of possible object list */ 205 206 node->object = obj_desc->common.next_object; 207 208 /* Handle possible 2-descriptor object */ 209 210 if (node->object && 211 (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) { 212 node->object = node->object->common.next_object; 213 } 214 215 /* 216 * Detach the object from any data objects (which are still held by 217 * the namespace node) 218 */ 219 if (obj_desc->common.next_object && 220 ((obj_desc->common.next_object)->common.type == 221 ACPI_TYPE_LOCAL_DATA)) { 222 obj_desc->common.next_object = NULL; 223 } 224 } 225 226 /* Reset the node type to untyped */ 227 228 node->type = ACPI_TYPE_ANY; 229 230 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n", 231 node, acpi_ut_get_node_name(node), obj_desc)); 232 233 /* Remove one reference on the object (and all subobjects) */ 234 235 acpi_ut_remove_reference(obj_desc); 236 return_VOID; 237 } 238 239 /******************************************************************************* 240 * 241 * FUNCTION: acpi_ns_get_attached_object 242 * 243 * PARAMETERS: node - Namespace node 244 * 245 * RETURN: Current value of the object field from the Node whose 246 * handle is passed 247 * 248 * DESCRIPTION: Obtain the object attached to a namespace node. 249 * 250 ******************************************************************************/ 251 252 union acpi_operand_object *acpi_ns_get_attached_object(struct 253 acpi_namespace_node 254 *node) 255 { 256 ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node); 257 258 if (!node) { 259 ACPI_WARNING((AE_INFO, "Null Node ptr")); 260 return_PTR(NULL); 261 } 262 263 if (!node->object || 264 ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND) 265 && (ACPI_GET_DESCRIPTOR_TYPE(node->object) != 266 ACPI_DESC_TYPE_NAMED)) 267 || ((node->object)->common.type == ACPI_TYPE_LOCAL_DATA)) { 268 return_PTR(NULL); 269 } 270 271 return_PTR(node->object); 272 } 273 274 /******************************************************************************* 275 * 276 * FUNCTION: acpi_ns_get_secondary_object 277 * 278 * PARAMETERS: node - Namespace node 279 * 280 * RETURN: Current value of the object field from the Node whose 281 * handle is passed. 282 * 283 * DESCRIPTION: Obtain a secondary object associated with a namespace node. 284 * 285 ******************************************************************************/ 286 287 union acpi_operand_object *acpi_ns_get_secondary_object(union 288 acpi_operand_object 289 *obj_desc) 290 { 291 ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc); 292 293 if ((!obj_desc) || 294 (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) || 295 (!obj_desc->common.next_object) || 296 ((obj_desc->common.next_object)->common.type == 297 ACPI_TYPE_LOCAL_DATA)) { 298 return_PTR(NULL); 299 } 300 301 return_PTR(obj_desc->common.next_object); 302 } 303 304 /******************************************************************************* 305 * 306 * FUNCTION: acpi_ns_attach_data 307 * 308 * PARAMETERS: node - Namespace node 309 * handler - Handler to be associated with the data 310 * data - Data to be attached 311 * 312 * RETURN: Status 313 * 314 * DESCRIPTION: Low-level attach data. Create and attach a Data object. 315 * 316 ******************************************************************************/ 317 318 acpi_status 319 acpi_ns_attach_data(struct acpi_namespace_node *node, 320 acpi_object_handler handler, void *data) 321 { 322 union acpi_operand_object *prev_obj_desc; 323 union acpi_operand_object *obj_desc; 324 union acpi_operand_object *data_desc; 325 326 /* We only allow one attachment per handler */ 327 328 prev_obj_desc = NULL; 329 obj_desc = node->object; 330 while (obj_desc) { 331 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && 332 (obj_desc->data.handler == handler)) { 333 return (AE_ALREADY_EXISTS); 334 } 335 336 prev_obj_desc = obj_desc; 337 obj_desc = obj_desc->common.next_object; 338 } 339 340 /* Create an internal object for the data */ 341 342 data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA); 343 if (!data_desc) { 344 return (AE_NO_MEMORY); 345 } 346 347 data_desc->data.handler = handler; 348 data_desc->data.pointer = data; 349 350 /* Install the data object */ 351 352 if (prev_obj_desc) { 353 prev_obj_desc->common.next_object = data_desc; 354 } else { 355 node->object = data_desc; 356 } 357 358 return (AE_OK); 359 } 360 361 /******************************************************************************* 362 * 363 * FUNCTION: acpi_ns_detach_data 364 * 365 * PARAMETERS: node - Namespace node 366 * handler - Handler associated with the data 367 * 368 * RETURN: Status 369 * 370 * DESCRIPTION: Low-level detach data. Delete the data node, but the caller 371 * is responsible for the actual data. 372 * 373 ******************************************************************************/ 374 375 acpi_status 376 acpi_ns_detach_data(struct acpi_namespace_node *node, 377 acpi_object_handler handler) 378 { 379 union acpi_operand_object *obj_desc; 380 union acpi_operand_object *prev_obj_desc; 381 382 prev_obj_desc = NULL; 383 obj_desc = node->object; 384 while (obj_desc) { 385 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && 386 (obj_desc->data.handler == handler)) { 387 if (prev_obj_desc) { 388 prev_obj_desc->common.next_object = 389 obj_desc->common.next_object; 390 } else { 391 node->object = obj_desc->common.next_object; 392 } 393 394 acpi_ut_remove_reference(obj_desc); 395 return (AE_OK); 396 } 397 398 prev_obj_desc = obj_desc; 399 obj_desc = obj_desc->common.next_object; 400 } 401 402 return (AE_NOT_FOUND); 403 } 404 405 /******************************************************************************* 406 * 407 * FUNCTION: acpi_ns_get_attached_data 408 * 409 * PARAMETERS: node - Namespace node 410 * handler - Handler associated with the data 411 * data - Where the data is returned 412 * 413 * RETURN: Status 414 * 415 * DESCRIPTION: Low level interface to obtain data previously associated with 416 * a namespace node. 417 * 418 ******************************************************************************/ 419 420 acpi_status 421 acpi_ns_get_attached_data(struct acpi_namespace_node *node, 422 acpi_object_handler handler, void **data) 423 { 424 union acpi_operand_object *obj_desc; 425 426 obj_desc = node->object; 427 while (obj_desc) { 428 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && 429 (obj_desc->data.handler == handler)) { 430 *data = obj_desc->data.pointer; 431 return (AE_OK); 432 } 433 434 obj_desc = obj_desc->common.next_object; 435 } 436 437 return (AE_NOT_FOUND); 438 } 439