blob: 8638f43cfc3d87184c9a0cc91318f07ab5abff8a [file] [log] [blame]
Erik Schmauss95857632018-03-14 16:13:07 -07001// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*******************************************************************************
3 *
4 * Module Name: nsobject - Utilities for objects attached to namespace
5 * table entries
6 *
7 ******************************************************************************/
8
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <acpi/acpi.h>
Len Browne2f7a772009-01-09 00:30:03 -050010#include "accommon.h"
11#include "acnamesp.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070012
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#define _COMPONENT ACPI_NAMESPACE
Len Brown4be44fc2005-08-05 00:44:28 -040014ACPI_MODULE_NAME("nsobject")
Linus Torvalds1da177e2005-04-16 15:20:36 -070015
16/*******************************************************************************
17 *
18 * FUNCTION: acpi_ns_attach_object
19 *
Bob Mooreba494be2012-07-12 09:40:10 +080020 * PARAMETERS: node - Parent Node
21 * object - Object to be attached
22 * type - Type of object, or ACPI_TYPE_ANY if not
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 * known
24 *
Robert Moore44f6c012005-04-18 22:49:35 -040025 * RETURN: Status
26 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 * DESCRIPTION: Record the given object as the value associated with the
Bob Moore73a30902012-10-31 02:26:55 +000028 * name whose acpi_handle is passed. If Object is NULL
Linus Torvalds1da177e2005-04-16 15:20:36 -070029 * 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 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -070036acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -040037acpi_ns_attach_object(struct acpi_namespace_node *node,
38 union acpi_operand_object *object, acpi_object_type type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070039{
Len Brown4be44fc2005-08-05 00:44:28 -040040 union acpi_operand_object *obj_desc;
41 union acpi_operand_object *last_obj_desc;
42 acpi_object_type object_type = ACPI_TYPE_ANY;
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Bob Mooreb229cf92006-04-21 17:15:00 -040044 ACPI_FUNCTION_TRACE(ns_attach_object);
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46 /*
47 * Parameter validation
48 */
49 if (!node) {
Bob Moore52fc0b02006-10-02 00:00:00 -040050
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 /* Invalid handle */
52
Bob Mooreb229cf92006-04-21 17:15:00 -040053 ACPI_ERROR((AE_INFO, "Null NamedObj handle"));
Len Brown4be44fc2005-08-05 00:44:28 -040054 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 }
56
57 if (!object && (ACPI_TYPE_ANY != type)) {
Bob Moore52fc0b02006-10-02 00:00:00 -040058
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 /* Null object */
60
Bob Mooreb8e4d892006-01-27 16:43:00 -050061 ACPI_ERROR((AE_INFO,
62 "Null object, but type not ACPI_TYPE_ANY"));
Len Brown4be44fc2005-08-05 00:44:28 -040063 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 }
65
Len Brown4be44fc2005-08-05 00:44:28 -040066 if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
Bob Moore52fc0b02006-10-02 00:00:00 -040067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 /* Not a name handle */
69
Bob Mooreb8e4d892006-01-27 16:43:00 -050070 ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
71 node, acpi_ut_get_descriptor_name(node)));
Len Brown4be44fc2005-08-05 00:44:28 -040072 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 }
74
75 /* Check if this object is already attached */
76
77 if (node->object == object) {
Len Brown4be44fc2005-08-05 00:44:28 -040078 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
Bob Mooreb229cf92006-04-21 17:15:00 -040079 "Obj %p already installed in NameObj %p\n",
Len Brown4be44fc2005-08-05 00:44:28 -040080 object, node));
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
Len Brown4be44fc2005-08-05 00:44:28 -040082 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 }
84
85 /* If null object, we will just install it */
86
87 if (!object) {
Len Brown4be44fc2005-08-05 00:44:28 -040088 obj_desc = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 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 */
Len Brown4be44fc2005-08-05 00:44:28 -040096 else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
97 ((struct acpi_namespace_node *)object)->object) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 /*
99 * Value passed is a name handle and that name has a
Bob Moore73a30902012-10-31 02:26:55 +0000100 * non-null value. Use that name's value and type.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 */
Len Brown4be44fc2005-08-05 00:44:28 -0400102 obj_desc = ((struct acpi_namespace_node *)object)->object;
103 object_type = ((struct acpi_namespace_node *)object)->type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 }
105
106 /*
107 * Otherwise, we will use the parameter object, but we must type
108 * it first
109 */
110 else {
Len Brown4be44fc2005-08-05 00:44:28 -0400111 obj_desc = (union acpi_operand_object *)object;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113 /* Use the given type */
114
115 object_type = type;
116 }
117
Len Brown4be44fc2005-08-05 00:44:28 -0400118 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
119 obj_desc, node, acpi_ut_get_node_name(node)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121 /* Detach an existing attached object if present */
122
123 if (node->object) {
Len Brown4be44fc2005-08-05 00:44:28 -0400124 acpi_ns_detach_object(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 }
126
127 if (obj_desc) {
128 /*
129 * Must increment the new value's reference count
130 * (if it is an internal object)
131 */
Len Brown4be44fc2005-08-05 00:44:28 -0400132 acpi_ut_add_reference(obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
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
Len Brown4be44fc2005-08-05 00:44:28 -0400148 node->type = (u8) object_type;
149 node->object = obj_desc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Len Brown4be44fc2005-08-05 00:44:28 -0400151 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152}
153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154/*******************************************************************************
155 *
156 * FUNCTION: acpi_ns_detach_object
157 *
Bob Mooreba494be2012-07-12 09:40:10 +0800158 * PARAMETERS: node - A Namespace node whose object will be detached
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 *
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
Len Brown4be44fc2005-08-05 00:44:28 -0400168void acpi_ns_detach_object(struct acpi_namespace_node *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169{
Len Brown4be44fc2005-08-05 00:44:28 -0400170 union acpi_operand_object *obj_desc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Bob Mooreb229cf92006-04-21 17:15:00 -0400172 ACPI_FUNCTION_TRACE(ns_detach_object);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
174 obj_desc = node->object;
175
Bob Moore3371c192009-02-18 14:44:03 +0800176 if (!obj_desc || (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 return_VOID;
178 }
179
Lin Mingb2f7ddc2009-05-21 10:42:09 +0800180 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
Bob Mooref9535292014-02-26 10:33:47 +0800189 /* Clear the Node entry in all cases */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190
191 node->object = NULL;
Len Brown4be44fc2005-08-05 00:44:28 -0400192 if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) {
Bob Mooref9535292014-02-26 10:33:47 +0800193
194 /* Unlink object from front of possible object list */
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 node->object = obj_desc->common.next_object;
Bob Mooref9535292014-02-26 10:33:47 +0800197
198 /* Handle possible 2-descriptor object */
199
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 if (node->object &&
Bob Mooref9535292014-02-26 10:33:47 +0800201 (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 node->object = node->object->common.next_object;
203 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
Bob Moore7817e262014-07-09 08:25:45 +0800205 /*
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 }
David E. Boxe23d9b82014-07-08 10:06:24 +0800214 }
215
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 /* Reset the node type to untyped */
217
218 node->type = ACPI_TYPE_ANY;
219
Len Brown4be44fc2005-08-05 00:44:28 -0400220 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
221 node, acpi_ut_get_node_name(node), obj_desc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
223 /* Remove one reference on the object (and all subobjects) */
224
Len Brown4be44fc2005-08-05 00:44:28 -0400225 acpi_ut_remove_reference(obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 return_VOID;
227}
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229/*******************************************************************************
230 *
231 * FUNCTION: acpi_ns_get_attached_object
232 *
Bob Mooreba494be2012-07-12 09:40:10 +0800233 * PARAMETERS: node - Namespace node
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 *
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
Len Brown4be44fc2005-08-05 00:44:28 -0400242union acpi_operand_object *acpi_ns_get_attached_object(struct
243 acpi_namespace_node
244 *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245{
Bob Mooreb229cf92006-04-21 17:15:00 -0400246 ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
248 if (!node) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500249 ACPI_WARNING((AE_INFO, "Null Node ptr"));
Len Brown4be44fc2005-08-05 00:44:28 -0400250 return_PTR(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 }
252
253 if (!node->object ||
Len Brown4be44fc2005-08-05 00:44:28 -0400254 ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND)
255 && (ACPI_GET_DESCRIPTOR_TYPE(node->object) !=
256 ACPI_DESC_TYPE_NAMED))
Bob Moore3371c192009-02-18 14:44:03 +0800257 || ((node->object)->common.type == ACPI_TYPE_LOCAL_DATA)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400258 return_PTR(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 }
260
Len Brown4be44fc2005-08-05 00:44:28 -0400261 return_PTR(node->object);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262}
263
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264/*******************************************************************************
265 *
266 * FUNCTION: acpi_ns_get_secondary_object
267 *
Bob Mooreba494be2012-07-12 09:40:10 +0800268 * PARAMETERS: node - Namespace node
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 *
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
Len Brown4be44fc2005-08-05 00:44:28 -0400277union acpi_operand_object *acpi_ns_get_secondary_object(union
278 acpi_operand_object
279 *obj_desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280{
Bob Mooreb229cf92006-04-21 17:15:00 -0400281 ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
Len Brown4be44fc2005-08-05 00:44:28 -0400283 if ((!obj_desc) ||
Bob Moore3371c192009-02-18 14:44:03 +0800284 (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) ||
Len Brown4be44fc2005-08-05 00:44:28 -0400285 (!obj_desc->common.next_object) ||
Bob Moore3371c192009-02-18 14:44:03 +0800286 ((obj_desc->common.next_object)->common.type ==
Len Brown4be44fc2005-08-05 00:44:28 -0400287 ACPI_TYPE_LOCAL_DATA)) {
288 return_PTR(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 }
290
Len Brown4be44fc2005-08-05 00:44:28 -0400291 return_PTR(obj_desc->common.next_object);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292}
293
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294/*******************************************************************************
295 *
296 * FUNCTION: acpi_ns_attach_data
297 *
Bob Mooreba494be2012-07-12 09:40:10 +0800298 * PARAMETERS: node - Namespace node
299 * handler - Handler to be associated with the data
300 * data - Data to be attached
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 *
302 * RETURN: Status
303 *
Bob Moore73a30902012-10-31 02:26:55 +0000304 * DESCRIPTION: Low-level attach data. Create and attach a Data object.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 *
306 ******************************************************************************/
307
308acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400309acpi_ns_attach_data(struct acpi_namespace_node *node,
310 acpi_object_handler handler, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311{
Len Brown4be44fc2005-08-05 00:44:28 -0400312 union acpi_operand_object *prev_obj_desc;
313 union acpi_operand_object *obj_desc;
314 union acpi_operand_object *data_desc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
316 /* We only allow one attachment per handler */
317
318 prev_obj_desc = NULL;
319 obj_desc = node->object;
320 while (obj_desc) {
Bob Moore3371c192009-02-18 14:44:03 +0800321 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
Len Brown4be44fc2005-08-05 00:44:28 -0400322 (obj_desc->data.handler == handler)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 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
Len Brown4be44fc2005-08-05 00:44:28 -0400332 data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 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;
Len Brown4be44fc2005-08-05 00:44:28 -0400344 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 node->object = data_desc;
346 }
347
348 return (AE_OK);
349}
350
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351/*******************************************************************************
352 *
353 * FUNCTION: acpi_ns_detach_data
354 *
Bob Mooreba494be2012-07-12 09:40:10 +0800355 * PARAMETERS: node - Namespace node
356 * handler - Handler associated with the data
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 *
358 * RETURN: Status
359 *
Bob Moore73a30902012-10-31 02:26:55 +0000360 * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 * is responsible for the actual data.
362 *
363 ******************************************************************************/
364
365acpi_status
Lv Zhengf5c1e1c2016-05-05 12:57:53 +0800366acpi_ns_detach_data(struct acpi_namespace_node *node,
Len Brown4be44fc2005-08-05 00:44:28 -0400367 acpi_object_handler handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368{
Len Brown4be44fc2005-08-05 00:44:28 -0400369 union acpi_operand_object *obj_desc;
370 union acpi_operand_object *prev_obj_desc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
372 prev_obj_desc = NULL;
373 obj_desc = node->object;
374 while (obj_desc) {
Bob Moore3371c192009-02-18 14:44:03 +0800375 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
Len Brown4be44fc2005-08-05 00:44:28 -0400376 (obj_desc->data.handler == handler)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 if (prev_obj_desc) {
Len Brown4be44fc2005-08-05 00:44:28 -0400378 prev_obj_desc->common.next_object =
379 obj_desc->common.next_object;
380 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 node->object = obj_desc->common.next_object;
382 }
383
Len Brown4be44fc2005-08-05 00:44:28 -0400384 acpi_ut_remove_reference(obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395/*******************************************************************************
396 *
397 * FUNCTION: acpi_ns_get_attached_data
398 *
Bob Mooreba494be2012-07-12 09:40:10 +0800399 * PARAMETERS: node - Namespace node
400 * handler - Handler associated with the data
401 * data - Where the data is returned
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 *
403 * RETURN: Status
404 *
405 * DESCRIPTION: Low level interface to obtain data previously associated with
406 * a namespace node.
407 *
408 ******************************************************************************/
409
410acpi_status
Lv Zhengf5c1e1c2016-05-05 12:57:53 +0800411acpi_ns_get_attached_data(struct acpi_namespace_node *node,
Len Brown4be44fc2005-08-05 00:44:28 -0400412 acpi_object_handler handler, void **data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413{
Len Brown4be44fc2005-08-05 00:44:28 -0400414 union acpi_operand_object *obj_desc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
416 obj_desc = node->object;
417 while (obj_desc) {
Bob Moore3371c192009-02-18 14:44:03 +0800418 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
Len Brown4be44fc2005-08-05 00:44:28 -0400419 (obj_desc->data.handler == handler)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 *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}