Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6595 serge 1
/******************************************************************************
2
 *
3
 * Module Name: excreate - Named object creation
4
 *
5
 *****************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2015, Intel Corp.
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions, and the following disclaimer,
16
 *    without modification.
17
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18
 *    substantially similar to the "NO WARRANTY" disclaimer below
19
 *    ("Disclaimer") and any redistribution must be conditioned upon
20
 *    including a substantially similar Disclaimer requirement for further
21
 *    binary redistribution.
22
 * 3. Neither the names of the above-listed copyright holders nor the names
23
 *    of any contributors may be used to endorse or promote products derived
24
 *    from this software without specific prior written permission.
25
 *
26
 * Alternatively, this software may be distributed under the terms of the
27
 * GNU General Public License ("GPL") version 2 as published by the Free
28
 * Software Foundation.
29
 *
30
 * NO WARRANTY
31
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
 * POSSIBILITY OF SUCH DAMAGES.
42
 */
43
 
44
#include 
45
#include "accommon.h"
46
#include "acinterp.h"
47
#include "amlcode.h"
48
#include "acnamesp.h"
49
 
50
#define _COMPONENT          ACPI_EXECUTER
51
ACPI_MODULE_NAME("excreate")
52
#ifndef ACPI_NO_METHOD_EXECUTION
53
/*******************************************************************************
54
 *
55
 * FUNCTION:    acpi_ex_create_alias
56
 *
57
 * PARAMETERS:  walk_state           - Current state, contains operands
58
 *
59
 * RETURN:      Status
60
 *
61
 * DESCRIPTION: Create a new named alias
62
 *
63
 ******************************************************************************/
64
acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
65
{
66
	struct acpi_namespace_node *target_node;
67
	struct acpi_namespace_node *alias_node;
68
	acpi_status status = AE_OK;
69
 
70
	ACPI_FUNCTION_TRACE(ex_create_alias);
71
 
72
	/* Get the source/alias operands (both namespace nodes) */
73
 
74
	alias_node = (struct acpi_namespace_node *)walk_state->operands[0];
75
	target_node = (struct acpi_namespace_node *)walk_state->operands[1];
76
 
77
	if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
78
	    (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
79
		/*
80
		 * Dereference an existing alias so that we don't create a chain
81
		 * of aliases. With this code, we guarantee that an alias is
82
		 * always exactly one level of indirection away from the
83
		 * actual aliased name.
84
		 */
85
		target_node =
86
		    ACPI_CAST_PTR(struct acpi_namespace_node,
87
				  target_node->object);
88
	}
89
 
90
	/*
91
	 * For objects that can never change (i.e., the NS node will
92
	 * permanently point to the same object), we can simply attach
93
	 * the object to the new NS node. For other objects (such as
94
	 * Integers, buffers, etc.), we have to point the Alias node
95
	 * to the original Node.
96
	 */
97
	switch (target_node->type) {
98
 
99
		/* For these types, the sub-object can change dynamically via a Store */
100
 
101
	case ACPI_TYPE_INTEGER:
102
	case ACPI_TYPE_STRING:
103
	case ACPI_TYPE_BUFFER:
104
	case ACPI_TYPE_PACKAGE:
105
	case ACPI_TYPE_BUFFER_FIELD:
106
		/*
107
		 * These types open a new scope, so we need the NS node in order to access
108
		 * any children.
109
		 */
110
	case ACPI_TYPE_DEVICE:
111
	case ACPI_TYPE_POWER:
112
	case ACPI_TYPE_PROCESSOR:
113
	case ACPI_TYPE_THERMAL:
114
	case ACPI_TYPE_LOCAL_SCOPE:
115
		/*
116
		 * The new alias has the type ALIAS and points to the original
117
		 * NS node, not the object itself.
118
		 */
119
		alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
120
		alias_node->object =
121
		    ACPI_CAST_PTR(union acpi_operand_object, target_node);
122
		break;
123
 
124
	case ACPI_TYPE_METHOD:
125
		/*
126
		 * Control method aliases need to be differentiated
127
		 */
128
		alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
129
		alias_node->object =
130
		    ACPI_CAST_PTR(union acpi_operand_object, target_node);
131
		break;
132
 
133
	default:
134
 
135
		/* Attach the original source object to the new Alias Node */
136
 
137
		/*
138
		 * The new alias assumes the type of the target, and it points
139
		 * to the same object. The reference count of the object has an
140
		 * additional reference to prevent deletion out from under either the
141
		 * target node or the alias Node
142
		 */
143
		status = acpi_ns_attach_object(alias_node,
144
					       acpi_ns_get_attached_object
145
					       (target_node),
146
					       target_node->type);
147
		break;
148
	}
149
 
150
	/* Since both operands are Nodes, we don't need to delete them */
151
 
152
	return_ACPI_STATUS(status);
153
}
154
 
155
/*******************************************************************************
156
 *
157
 * FUNCTION:    acpi_ex_create_event
158
 *
159
 * PARAMETERS:  walk_state          - Current state
160
 *
161
 * RETURN:      Status
162
 *
163
 * DESCRIPTION: Create a new event object
164
 *
165
 ******************************************************************************/
166
 
167
acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state)
168
{
169
	acpi_status status;
170
	union acpi_operand_object *obj_desc;
171
 
172
	ACPI_FUNCTION_TRACE(ex_create_event);
173
 
174
	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT);
175
	if (!obj_desc) {
176
		status = AE_NO_MEMORY;
177
		goto cleanup;
178
	}
179
 
180
	/*
181
	 * Create the actual OS semaphore, with zero initial units -- meaning
182
	 * that the event is created in an unsignalled state
183
	 */
184
	status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
185
					  &obj_desc->event.os_semaphore);
186
	if (ACPI_FAILURE(status)) {
187
		goto cleanup;
188
	}
189
 
190
	/* Attach object to the Node */
191
 
192
	status =
193
	    acpi_ns_attach_object((struct acpi_namespace_node *)walk_state->
194
				  operands[0], obj_desc, ACPI_TYPE_EVENT);
195
 
196
cleanup:
197
	/*
198
	 * Remove local reference to the object (on error, will cause deletion
199
	 * of both object and semaphore if present.)
200
	 */
201
	acpi_ut_remove_reference(obj_desc);
202
	return_ACPI_STATUS(status);
203
}
204
 
205
/*******************************************************************************
206
 *
207
 * FUNCTION:    acpi_ex_create_mutex
208
 *
209
 * PARAMETERS:  walk_state          - Current state
210
 *
211
 * RETURN:      Status
212
 *
213
 * DESCRIPTION: Create a new mutex object
214
 *
215
 *              Mutex (Name[0], sync_level[1])
216
 *
217
 ******************************************************************************/
218
 
219
acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
220
{
221
	acpi_status status = AE_OK;
222
	union acpi_operand_object *obj_desc;
223
 
224
	ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS);
225
 
226
	/* Create the new mutex object */
227
 
228
	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX);
229
	if (!obj_desc) {
230
		status = AE_NO_MEMORY;
231
		goto cleanup;
232
	}
233
 
234
	/* Create the actual OS Mutex */
235
 
236
	status = acpi_os_create_mutex(&obj_desc->mutex.os_mutex);
237
	if (ACPI_FAILURE(status)) {
238
		goto cleanup;
239
	}
240
 
241
	/* Init object and attach to NS node */
242
 
243
	obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value;
244
	obj_desc->mutex.node =
245
	    (struct acpi_namespace_node *)walk_state->operands[0];
246
 
247
	status =
248
	    acpi_ns_attach_object(obj_desc->mutex.node, obj_desc,
249
				  ACPI_TYPE_MUTEX);
250
 
251
cleanup:
252
	/*
253
	 * Remove local reference to the object (on error, will cause deletion
254
	 * of both object and semaphore if present.)
255
	 */
256
	acpi_ut_remove_reference(obj_desc);
257
	return_ACPI_STATUS(status);
258
}
259
 
260
/*******************************************************************************
261
 *
262
 * FUNCTION:    acpi_ex_create_region
263
 *
264
 * PARAMETERS:  aml_start           - Pointer to the region declaration AML
265
 *              aml_length          - Max length of the declaration AML
266
 *              space_id            - Address space ID for the region
267
 *              walk_state          - Current state
268
 *
269
 * RETURN:      Status
270
 *
271
 * DESCRIPTION: Create a new operation region object
272
 *
273
 ******************************************************************************/
274
 
275
acpi_status
276
acpi_ex_create_region(u8 * aml_start,
277
		      u32 aml_length,
278
		      u8 space_id, struct acpi_walk_state *walk_state)
279
{
280
	acpi_status status;
281
	union acpi_operand_object *obj_desc;
282
	struct acpi_namespace_node *node;
283
	union acpi_operand_object *region_obj2;
284
 
285
	ACPI_FUNCTION_TRACE(ex_create_region);
286
 
287
	/* Get the Namespace Node */
288
 
289
	node = walk_state->op->common.node;
290
 
291
	/*
292
	 * If the region object is already attached to this node,
293
	 * just return
294
	 */
295
	if (acpi_ns_get_attached_object(node)) {
296
		return_ACPI_STATUS(AE_OK);
297
	}
298
 
299
	/*
300
	 * Space ID must be one of the predefined IDs, or in the user-defined
301
	 * range
302
	 */
303
	if (!acpi_is_valid_space_id(space_id)) {
304
		/*
305
		 * Print an error message, but continue. We don't want to abort
306
		 * a table load for this exception. Instead, if the region is
307
		 * actually used at runtime, abort the executing method.
308
		 */
309
		ACPI_ERROR((AE_INFO,
310
			    "Invalid/unknown Address Space ID: 0x%2.2X",
311
			    space_id));
312
	}
313
 
314
	ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n",
315
			  acpi_ut_get_region_name(space_id), space_id));
316
 
317
	/* Create the region descriptor */
318
 
319
	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
320
	if (!obj_desc) {
321
		status = AE_NO_MEMORY;
322
		goto cleanup;
323
	}
324
 
325
	/*
326
	 * Remember location in AML stream of address & length
327
	 * operands since they need to be evaluated at run time.
328
	 */
329
	region_obj2 = obj_desc->common.next_object;
330
	region_obj2->extra.aml_start = aml_start;
331
	region_obj2->extra.aml_length = aml_length;
332
	if (walk_state->scope_info) {
333
		region_obj2->extra.scope_node =
334
		    walk_state->scope_info->scope.node;
335
	} else {
336
		region_obj2->extra.scope_node = node;
337
	}
338
 
339
	/* Init the region from the operands */
340
 
341
	obj_desc->region.space_id = space_id;
342
	obj_desc->region.address = 0;
343
	obj_desc->region.length = 0;
344
	obj_desc->region.node = node;
345
 
346
	/* Install the new region object in the parent Node */
347
 
348
	status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
349
 
350
cleanup:
351
 
352
	/* Remove local reference to the object */
353
 
354
	acpi_ut_remove_reference(obj_desc);
355
	return_ACPI_STATUS(status);
356
}
357
 
358
/*******************************************************************************
359
 *
360
 * FUNCTION:    acpi_ex_create_processor
361
 *
362
 * PARAMETERS:  walk_state          - Current state
363
 *
364
 * RETURN:      Status
365
 *
366
 * DESCRIPTION: Create a new processor object and populate the fields
367
 *
368
 *              Processor (Name[0], cpu_ID[1], pblock_addr[2], pblock_length[3])
369
 *
370
 ******************************************************************************/
371
 
372
acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state)
373
{
374
	union acpi_operand_object **operand = &walk_state->operands[0];
375
	union acpi_operand_object *obj_desc;
376
	acpi_status status;
377
 
378
	ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state);
379
 
380
	/* Create the processor object */
381
 
382
	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR);
383
	if (!obj_desc) {
384
		return_ACPI_STATUS(AE_NO_MEMORY);
385
	}
386
 
387
	/* Initialize the processor object from the operands */
388
 
389
	obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
390
	obj_desc->processor.length = (u8) operand[3]->integer.value;
391
	obj_desc->processor.address =
392
	    (acpi_io_address) operand[2]->integer.value;
393
 
394
	/* Install the processor object in the parent Node */
395
 
396
	status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
397
				       obj_desc, ACPI_TYPE_PROCESSOR);
398
 
399
	/* Remove local reference to the object */
400
 
401
	acpi_ut_remove_reference(obj_desc);
402
	return_ACPI_STATUS(status);
403
}
404
 
405
/*******************************************************************************
406
 *
407
 * FUNCTION:    acpi_ex_create_power_resource
408
 *
409
 * PARAMETERS:  walk_state          - Current state
410
 *
411
 * RETURN:      Status
412
 *
413
 * DESCRIPTION: Create a new power_resource object and populate the fields
414
 *
415
 *              power_resource (Name[0], system_level[1], resource_order[2])
416
 *
417
 ******************************************************************************/
418
 
419
acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state)
420
{
421
	union acpi_operand_object **operand = &walk_state->operands[0];
422
	acpi_status status;
423
	union acpi_operand_object *obj_desc;
424
 
425
	ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state);
426
 
427
	/* Create the power resource object */
428
 
429
	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER);
430
	if (!obj_desc) {
431
		return_ACPI_STATUS(AE_NO_MEMORY);
432
	}
433
 
434
	/* Initialize the power object from the operands */
435
 
436
	obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
437
	obj_desc->power_resource.resource_order =
438
	    (u16) operand[2]->integer.value;
439
 
440
	/* Install the  power resource object in the parent Node */
441
 
442
	status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
443
				       obj_desc, ACPI_TYPE_POWER);
444
 
445
	/* Remove local reference to the object */
446
 
447
	acpi_ut_remove_reference(obj_desc);
448
	return_ACPI_STATUS(status);
449
}
450
#endif
451
 
452
/*******************************************************************************
453
 *
454
 * FUNCTION:    acpi_ex_create_method
455
 *
456
 * PARAMETERS:  aml_start       - First byte of the method's AML
457
 *              aml_length      - AML byte count for this method
458
 *              walk_state      - Current state
459
 *
460
 * RETURN:      Status
461
 *
462
 * DESCRIPTION: Create a new method object
463
 *
464
 ******************************************************************************/
465
 
466
acpi_status
467
acpi_ex_create_method(u8 * aml_start,
468
		      u32 aml_length, struct acpi_walk_state *walk_state)
469
{
470
	union acpi_operand_object **operand = &walk_state->operands[0];
471
	union acpi_operand_object *obj_desc;
472
	acpi_status status;
473
	u8 method_flags;
474
 
475
	ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state);
476
 
477
	/* Create a new method object */
478
 
479
	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
480
	if (!obj_desc) {
481
		status = AE_NO_MEMORY;
482
		goto exit;
483
	}
484
 
485
	/* Save the method's AML pointer and length  */
486
 
487
	obj_desc->method.aml_start = aml_start;
488
	obj_desc->method.aml_length = aml_length;
489
	obj_desc->method.node = operand[0];
490
 
491
	/*
492
	 * Disassemble the method flags. Split off the arg_count, Serialized
493
	 * flag, and sync_level for efficiency.
494
	 */
495
	method_flags = (u8) operand[1]->integer.value;
496
 
497
	obj_desc->method.param_count =
498
	    (u8) (method_flags & AML_METHOD_ARG_COUNT);
499
 
500
	/*
501
	 * Get the sync_level. If method is serialized, a mutex will be
502
	 * created for this method when it is parsed.
503
	 */
504
	if (method_flags & AML_METHOD_SERIALIZED) {
505
		obj_desc->method.info_flags = ACPI_METHOD_SERIALIZED;
506
 
507
		/*
508
		 * ACPI 1.0: sync_level = 0
509
		 * ACPI 2.0: sync_level = sync_level in method declaration
510
		 */
511
		obj_desc->method.sync_level = (u8)
512
		    ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
513
	}
514
 
515
	/* Attach the new object to the method Node */
516
 
517
	status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
518
				       obj_desc, ACPI_TYPE_METHOD);
519
 
520
	/* Remove local reference to the object */
521
 
522
	acpi_ut_remove_reference(obj_desc);
523
 
524
exit:
525
	/* Remove a reference to the operand */
526
 
527
	acpi_ut_remove_reference(operand[1]);
528
	return_ACPI_STATUS(status);
529
}