brintos

brintos / linux-shallow public Read only

0
0
Text · 11.3 KiB · 79d86da Raw
433 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/*******************************************************************************3 *4 * Module Name: nsobject - Utilities for objects attached to namespace5 *                         table entries6 *7 ******************************************************************************/8 9#include <acpi/acpi.h>10#include "accommon.h"11#include "acnamesp.h"12 13#define _COMPONENT          ACPI_NAMESPACE14ACPI_MODULE_NAME("nsobject")15 16/*******************************************************************************17 *18 * FUNCTION:    acpi_ns_attach_object19 *20 * PARAMETERS:  node                - Parent Node21 *              object              - Object to be attached22 *              type                - Type of object, or ACPI_TYPE_ANY if not23 *                                    known24 *25 * RETURN:      Status26 *27 * DESCRIPTION: Record the given object as the value associated with the28 *              name whose acpi_handle is passed. If Object is NULL29 *              and Type is ACPI_TYPE_ANY, set the name as having no value.30 *              Note: Future may require that the Node->Flags field be passed31 *              as a parameter.32 *33 * MUTEX:       Assumes namespace is locked34 *35 ******************************************************************************/36acpi_status37acpi_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 validation48	 */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) object95	 */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 a100		 * 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 type108	 * it first109	 */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 count130		 * (if it is an internal object)131		 */132		acpi_ut_add_reference(obj_desc);133 134		/*135		 * Handle objects with multiple descriptors - walk136		 * to the end of the descriptor list137		 */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_object157 *158 * PARAMETERS:  node           - A Namespace node whose object will be detached159 *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 168void 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 by211		 * 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_object236 *237 * PARAMETERS:  node             - Namespace node238 *239 * RETURN:      Current value of the object field from the Node whose240 *              handle is passed241 *242 * DESCRIPTION: Obtain the object attached to a namespace node.243 *244 ******************************************************************************/245 246union acpi_operand_object *acpi_ns_get_attached_object(struct247						       acpi_namespace_node248						       *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_object271 *272 * PARAMETERS:  node             - Namespace node273 *274 * RETURN:      Current value of the object field from the Node whose275 *              handle is passed.276 *277 * DESCRIPTION: Obtain a secondary object associated with a namespace node.278 *279 ******************************************************************************/280 281union acpi_operand_object *acpi_ns_get_secondary_object(union282							acpi_operand_object283							*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_data301 *302 * PARAMETERS:  node            - Namespace node303 *              handler         - Handler to be associated with the data304 *              data            - Data to be attached305 *306 * RETURN:      Status307 *308 * DESCRIPTION: Low-level attach data. Create and attach a Data object.309 *310 ******************************************************************************/311 312acpi_status313acpi_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_data358 *359 * PARAMETERS:  node            - Namespace node360 *              handler         - Handler associated with the data361 *362 * RETURN:      Status363 *364 * DESCRIPTION: Low-level detach data. Delete the data node, but the caller365 *              is responsible for the actual data.366 *367 ******************************************************************************/368 369acpi_status370acpi_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_data402 *403 * PARAMETERS:  node            - Namespace node404 *              handler         - Handler associated with the data405 *              data            - Where the data is returned406 *407 * RETURN:      Status408 *409 * DESCRIPTION: Low level interface to obtain data previously associated with410 *              a namespace node.411 *412 ******************************************************************************/413 414acpi_status415acpi_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}433