Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6595 serge 1
/*******************************************************************************
2
 *
3
 * Module Name: nsobject - Utilities for objects attached to namespace
4
 *                         table entries
5
 *
6
 ******************************************************************************/
7
 
8
/*
9
 * Copyright (C) 2000 - 2015, Intel Corp.
10
 * All rights reserved.
11
 *
12
 * Redistribution and use in source and binary forms, with or without
13
 * modification, are permitted provided that the following conditions
14
 * are met:
15
 * 1. Redistributions of source code must retain the above copyright
16
 *    notice, this list of conditions, and the following disclaimer,
17
 *    without modification.
18
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19
 *    substantially similar to the "NO WARRANTY" disclaimer below
20
 *    ("Disclaimer") and any redistribution must be conditioned upon
21
 *    including a substantially similar Disclaimer requirement for further
22
 *    binary redistribution.
23
 * 3. Neither the names of the above-listed copyright holders nor the names
24
 *    of any contributors may be used to endorse or promote products derived
25
 *    from this software without specific prior written permission.
26
 *
27
 * Alternatively, this software may be distributed under the terms of the
28
 * GNU General Public License ("GPL") version 2 as published by the Free
29
 * Software Foundation.
30
 *
31
 * NO WARRANTY
32
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42
 * POSSIBILITY OF SUCH DAMAGES.
43
 */
44
 
45
#include 
46
#include "accommon.h"
47
#include "acnamesp.h"
48
 
49
#define _COMPONENT          ACPI_NAMESPACE
50
ACPI_MODULE_NAME("nsobject")
51
 
52
/*******************************************************************************
53
 *
54
 * FUNCTION:    acpi_ns_attach_object
55
 *
56
 * PARAMETERS:  node                - Parent Node
57
 *              object              - Object to be attached
58
 *              type                - Type of object, or ACPI_TYPE_ANY if not
59
 *                                    known
60
 *
61
 * RETURN:      Status
62
 *
63
 * DESCRIPTION: Record the given object as the value associated with the
64
 *              name whose acpi_handle is passed. If Object is NULL
65
 *              and Type is ACPI_TYPE_ANY, set the name as having no value.
66
 *              Note: Future may require that the Node->Flags field be passed
67
 *              as a parameter.
68
 *
69
 * MUTEX:       Assumes namespace is locked
70
 *
71
 ******************************************************************************/
72
acpi_status
73
acpi_ns_attach_object(struct acpi_namespace_node *node,
74
		      union acpi_operand_object *object, acpi_object_type type)
75
{
76
	union acpi_operand_object *obj_desc;
77
	union acpi_operand_object *last_obj_desc;
78
	acpi_object_type object_type = ACPI_TYPE_ANY;
79
 
80
	ACPI_FUNCTION_TRACE(ns_attach_object);
81
 
82
	/*
83
	 * Parameter validation
84
	 */
85
	if (!node) {
86
 
87
		/* Invalid handle */
88
 
89
		ACPI_ERROR((AE_INFO, "Null NamedObj handle"));
90
		return_ACPI_STATUS(AE_BAD_PARAMETER);
91
	}
92
 
93
	if (!object && (ACPI_TYPE_ANY != type)) {
94
 
95
		/* Null object */
96
 
97
		ACPI_ERROR((AE_INFO,
98
			    "Null object, but type not ACPI_TYPE_ANY"));
99
		return_ACPI_STATUS(AE_BAD_PARAMETER);
100
	}
101
 
102
	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
103
 
104
		/* Not a name handle */
105
 
106
		ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
107
			    node, acpi_ut_get_descriptor_name(node)));
108
		return_ACPI_STATUS(AE_BAD_PARAMETER);
109
	}
110
 
111
	/* Check if this object is already attached */
112
 
113
	if (node->object == object) {
114
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
115
				  "Obj %p already installed in NameObj %p\n",
116
				  object, node));
117
 
118
		return_ACPI_STATUS(AE_OK);
119
	}
120
 
121
	/* If null object, we will just install it */
122
 
123
	if (!object) {
124
		obj_desc = NULL;
125
		object_type = ACPI_TYPE_ANY;
126
	}
127
 
128
	/*
129
	 * If the source object is a namespace Node with an attached object,
130
	 * we will use that (attached) object
131
	 */
132
	else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
133
		 ((struct acpi_namespace_node *)object)->object) {
134
		/*
135
		 * Value passed is a name handle and that name has a
136
		 * non-null value. Use that name's value and type.
137
		 */
138
		obj_desc = ((struct acpi_namespace_node *)object)->object;
139
		object_type = ((struct acpi_namespace_node *)object)->type;
140
	}
141
 
142
	/*
143
	 * Otherwise, we will use the parameter object, but we must type
144
	 * it first
145
	 */
146
	else {
147
		obj_desc = (union acpi_operand_object *)object;
148
 
149
		/* Use the given type */
150
 
151
		object_type = type;
152
	}
153
 
154
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
155
			  obj_desc, node, acpi_ut_get_node_name(node)));
156
 
157
	/* Detach an existing attached object if present */
158
 
159
	if (node->object) {
160
		acpi_ns_detach_object(node);
161
	}
162
 
163
	if (obj_desc) {
164
		/*
165
		 * Must increment the new value's reference count
166
		 * (if it is an internal object)
167
		 */
168
		acpi_ut_add_reference(obj_desc);
169
 
170
		/*
171
		 * Handle objects with multiple descriptors - walk
172
		 * to the end of the descriptor list
173
		 */
174
		last_obj_desc = obj_desc;
175
		while (last_obj_desc->common.next_object) {
176
			last_obj_desc = last_obj_desc->common.next_object;
177
		}
178
 
179
		/* Install the object at the front of the object list */
180
 
181
		last_obj_desc->common.next_object = node->object;
182
	}
183
 
184
	node->type = (u8) object_type;
185
	node->object = obj_desc;
186
 
187
	return_ACPI_STATUS(AE_OK);
188
}
189
 
190
/*******************************************************************************
191
 *
192
 * FUNCTION:    acpi_ns_detach_object
193
 *
194
 * PARAMETERS:  node           - A Namespace node whose object will be detached
195
 *
196
 * RETURN:      None.
197
 *
198
 * DESCRIPTION: Detach/delete an object associated with a namespace node.
199
 *              if the object is an allocated object, it is freed.
200
 *              Otherwise, the field is simply cleared.
201
 *
202
 ******************************************************************************/
203
 
204
void acpi_ns_detach_object(struct acpi_namespace_node *node)
205
{
206
	union acpi_operand_object *obj_desc;
207
 
208
	ACPI_FUNCTION_TRACE(ns_detach_object);
209
 
210
	obj_desc = node->object;
211
 
212
	if (!obj_desc || (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
213
		return_VOID;
214
	}
215
 
216
	if (node->flags & ANOBJ_ALLOCATED_BUFFER) {
217
 
218
		/* Free the dynamic aml buffer */
219
 
220
		if (obj_desc->common.type == ACPI_TYPE_METHOD) {
221
			ACPI_FREE(obj_desc->method.aml_start);
222
		}
223
	}
224
 
225
	/* Clear the Node entry in all cases */
226
 
227
	node->object = NULL;
228
	if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) {
229
 
230
		/* Unlink object from front of possible object list */
231
 
232
		node->object = obj_desc->common.next_object;
233
 
234
		/* Handle possible 2-descriptor object */
235
 
236
		if (node->object &&
237
		    (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) {
238
			node->object = node->object->common.next_object;
239
		}
240
 
241
		/*
242
		 * Detach the object from any data objects (which are still held by
243
		 * the namespace node)
244
		 */
245
		if (obj_desc->common.next_object &&
246
		    ((obj_desc->common.next_object)->common.type ==
247
		     ACPI_TYPE_LOCAL_DATA)) {
248
			obj_desc->common.next_object = NULL;
249
		}
250
	}
251
 
252
	/* Reset the node type to untyped */
253
 
254
	node->type = ACPI_TYPE_ANY;
255
 
256
	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
257
			  node, acpi_ut_get_node_name(node), obj_desc));
258
 
259
	/* Remove one reference on the object (and all subobjects) */
260
 
261
	acpi_ut_remove_reference(obj_desc);
262
	return_VOID;
263
}
264
 
265
/*******************************************************************************
266
 *
267
 * FUNCTION:    acpi_ns_get_attached_object
268
 *
269
 * PARAMETERS:  node             - Namespace node
270
 *
271
 * RETURN:      Current value of the object field from the Node whose
272
 *              handle is passed
273
 *
274
 * DESCRIPTION: Obtain the object attached to a namespace node.
275
 *
276
 ******************************************************************************/
277
 
278
union acpi_operand_object *acpi_ns_get_attached_object(struct
279
						       acpi_namespace_node
280
						       *node)
281
{
282
	ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node);
283
 
284
	if (!node) {
285
		ACPI_WARNING((AE_INFO, "Null Node ptr"));
286
		return_PTR(NULL);
287
	}
288
 
289
	if (!node->object ||
290
	    ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND)
291
	     && (ACPI_GET_DESCRIPTOR_TYPE(node->object) !=
292
		 ACPI_DESC_TYPE_NAMED))
293
	    || ((node->object)->common.type == ACPI_TYPE_LOCAL_DATA)) {
294
		return_PTR(NULL);
295
	}
296
 
297
	return_PTR(node->object);
298
}
299
 
300
/*******************************************************************************
301
 *
302
 * FUNCTION:    acpi_ns_get_secondary_object
303
 *
304
 * PARAMETERS:  node             - Namespace node
305
 *
306
 * RETURN:      Current value of the object field from the Node whose
307
 *              handle is passed.
308
 *
309
 * DESCRIPTION: Obtain a secondary object associated with a namespace node.
310
 *
311
 ******************************************************************************/
312
 
313
union acpi_operand_object *acpi_ns_get_secondary_object(union
314
							acpi_operand_object
315
							*obj_desc)
316
{
317
	ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc);
318
 
319
	if ((!obj_desc) ||
320
	    (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) ||
321
	    (!obj_desc->common.next_object) ||
322
	    ((obj_desc->common.next_object)->common.type ==
323
	     ACPI_TYPE_LOCAL_DATA)) {
324
		return_PTR(NULL);
325
	}
326
 
327
	return_PTR(obj_desc->common.next_object);
328
}
329
 
330
/*******************************************************************************
331
 *
332
 * FUNCTION:    acpi_ns_attach_data
333
 *
334
 * PARAMETERS:  node            - Namespace node
335
 *              handler         - Handler to be associated with the data
336
 *              data            - Data to be attached
337
 *
338
 * RETURN:      Status
339
 *
340
 * DESCRIPTION: Low-level attach data. Create and attach a Data object.
341
 *
342
 ******************************************************************************/
343
 
344
acpi_status
345
acpi_ns_attach_data(struct acpi_namespace_node *node,
346
		    acpi_object_handler handler, void *data)
347
{
348
	union acpi_operand_object *prev_obj_desc;
349
	union acpi_operand_object *obj_desc;
350
	union acpi_operand_object *data_desc;
351
 
352
	/* We only allow one attachment per handler */
353
 
354
	prev_obj_desc = NULL;
355
	obj_desc = node->object;
356
	while (obj_desc) {
357
		if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
358
		    (obj_desc->data.handler == handler)) {
359
			return (AE_ALREADY_EXISTS);
360
		}
361
 
362
		prev_obj_desc = obj_desc;
363
		obj_desc = obj_desc->common.next_object;
364
	}
365
 
366
	/* Create an internal object for the data */
367
 
368
	data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA);
369
	if (!data_desc) {
370
		return (AE_NO_MEMORY);
371
	}
372
 
373
	data_desc->data.handler = handler;
374
	data_desc->data.pointer = data;
375
 
376
	/* Install the data object */
377
 
378
	if (prev_obj_desc) {
379
		prev_obj_desc->common.next_object = data_desc;
380
	} else {
381
		node->object = data_desc;
382
	}
383
 
384
	return (AE_OK);
385
}
386
 
387
/*******************************************************************************
388
 *
389
 * FUNCTION:    acpi_ns_detach_data
390
 *
391
 * PARAMETERS:  node            - Namespace node
392
 *              handler         - Handler associated with the data
393
 *
394
 * RETURN:      Status
395
 *
396
 * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
397
 *              is responsible for the actual data.
398
 *
399
 ******************************************************************************/
400
 
401
acpi_status
402
acpi_ns_detach_data(struct acpi_namespace_node * node,
403
		    acpi_object_handler handler)
404
{
405
	union acpi_operand_object *obj_desc;
406
	union acpi_operand_object *prev_obj_desc;
407
 
408
	prev_obj_desc = NULL;
409
	obj_desc = node->object;
410
	while (obj_desc) {
411
		if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
412
		    (obj_desc->data.handler == handler)) {
413
			if (prev_obj_desc) {
414
				prev_obj_desc->common.next_object =
415
				    obj_desc->common.next_object;
416
			} else {
417
				node->object = obj_desc->common.next_object;
418
			}
419
 
420
			acpi_ut_remove_reference(obj_desc);
421
			return (AE_OK);
422
		}
423
 
424
		prev_obj_desc = obj_desc;
425
		obj_desc = obj_desc->common.next_object;
426
	}
427
 
428
	return (AE_NOT_FOUND);
429
}
430
 
431
/*******************************************************************************
432
 *
433
 * FUNCTION:    acpi_ns_get_attached_data
434
 *
435
 * PARAMETERS:  node            - Namespace node
436
 *              handler         - Handler associated with the data
437
 *              data            - Where the data is returned
438
 *
439
 * RETURN:      Status
440
 *
441
 * DESCRIPTION: Low level interface to obtain data previously associated with
442
 *              a namespace node.
443
 *
444
 ******************************************************************************/
445
 
446
acpi_status
447
acpi_ns_get_attached_data(struct acpi_namespace_node * node,
448
			  acpi_object_handler handler, void **data)
449
{
450
	union acpi_operand_object *obj_desc;
451
 
452
	obj_desc = node->object;
453
	while (obj_desc) {
454
		if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
455
		    (obj_desc->data.handler == handler)) {
456
			*data = obj_desc->data.pointer;
457
			return (AE_OK);
458
		}
459
 
460
		obj_desc = obj_desc->common.next_object;
461
	}
462
 
463
	return (AE_NOT_FOUND);
464
}