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