1/******************************************************************************
2 *
3 * Module Name: dsobject - Dispatcher object management routines
4 *              $Revision: 1.1.1.1 $
5 *
6 *****************************************************************************/
7
8/*
9 *  Copyright (C) 2000, 2001 R. Byron Moore
10 *
11 *  This program is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License as published by
13 *  the Free Software Foundation; either version 2 of the License, or
14 *  (at your option) any later version.
15 *
16 *  This program is distributed in the hope that it will be useful,
17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 *  GNU General Public License for more details.
20 *
21 *  You should have received a copy of the GNU General Public License
22 *  along with this program; if not, write to the Free Software
23 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 */
25
26
27#include "acpi.h"
28#include "acparser.h"
29#include "amlcode.h"
30#include "acdispat.h"
31#include "acinterp.h"
32#include "acnamesp.h"
33
34#define _COMPONENT          ACPI_DISPATCHER
35	 MODULE_NAME         ("dsobject")
36
37
38/*******************************************************************************
39 *
40 * FUNCTION:    Acpi_ds_init_one_object
41 *
42 * PARAMETERS:  Obj_handle      - Node
43 *              Level           - Current nesting level
44 *              Context         - Points to a init info struct
45 *              Return_value    - Not used
46 *
47 * RETURN:      Status
48 *
49 * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object
50 *              within the  namespace.
51 *
52 *              Currently, the only objects that require initialization are:
53 *              1) Methods
54 *              2) Op Regions
55 *
56 ******************************************************************************/
57
58acpi_status
59acpi_ds_init_one_object (
60	acpi_handle             obj_handle,
61	u32                     level,
62	void                    *context,
63	void                    **return_value)
64{
65	acpi_object_type8       type;
66	acpi_status             status;
67	acpi_init_walk_info     *info = (acpi_init_walk_info *) context;
68	u8                      table_revision;
69
70
71	PROC_NAME ("Ds_init_one_object");
72
73
74	info->object_count++;
75	table_revision = info->table_desc->pointer->revision;
76
77	/*
78	 * We are only interested in objects owned by the table that
79	 * was just loaded
80	 */
81	if (((acpi_namespace_node *) obj_handle)->owner_id !=
82			info->table_desc->table_id) {
83		return (AE_OK);
84	}
85
86
87	/* And even then, we are only interested in a few object types */
88
89	type = acpi_ns_get_type (obj_handle);
90
91	switch (type) {
92
93	case ACPI_TYPE_REGION:
94
95		acpi_ds_initialize_region (obj_handle);
96
97		info->op_region_count++;
98		break;
99
100
101	case ACPI_TYPE_METHOD:
102
103		info->method_count++;
104
105		if (!(acpi_dbg_level & ACPI_LV_INIT)) {
106			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
107		}
108
109		/*
110		 * Set the execution data width (32 or 64) based upon the
111		 * revision number of the parent ACPI table.
112		 */
113		if (table_revision == 1) {
114			((acpi_namespace_node *)obj_handle)->flags |= ANOBJ_DATA_WIDTH_32;
115		}
116
117		/*
118		 * Always parse methods to detect errors, we may delete
119		 * the parse tree below
120		 */
121		status = acpi_ds_parse_method (obj_handle);
122		if (ACPI_FAILURE (status)) {
123			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n",
124				obj_handle, (char*)&((acpi_namespace_node *)obj_handle)->name,
125				acpi_format_exception (status)));
126
127			/* This parse failed, but we will continue parsing more methods */
128
129			break;
130		}
131
132		/*
133		 * Delete the parse tree.  We simple re-parse the method
134		 * for every execution since there isn't much overhead
135		 */
136		acpi_ns_delete_namespace_subtree (obj_handle);
137		break;
138
139	default:
140		break;
141	}
142
143	/*
144	 * We ignore errors from above, and always return OK, since
145	 * we don't want to abort the walk on a single error.
146	 */
147	return (AE_OK);
148}
149
150
151/*******************************************************************************
152 *
153 * FUNCTION:    Acpi_ds_initialize_objects
154 *
155 * PARAMETERS:  None
156 *
157 * RETURN:      Status
158 *
159 * DESCRIPTION: Walk the entire namespace and perform any necessary
160 *              initialization on the objects found therein
161 *
162 ******************************************************************************/
163
164acpi_status
165acpi_ds_initialize_objects (
166	acpi_table_desc         *table_desc,
167	acpi_namespace_node     *start_node)
168{
169	acpi_status             status;
170	acpi_init_walk_info     info;
171
172
173	FUNCTION_TRACE ("Ds_initialize_objects");
174
175
176	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
177		"**** Starting initialization of namespace objects ****\n"));
178	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Parsing Methods:"));
179
180
181	info.method_count   = 0;
182	info.op_region_count = 0;
183	info.object_count   = 0;
184	info.table_desc     = table_desc;
185
186
187	/* Walk entire namespace from the supplied root */
188
189	status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
190			  acpi_ds_init_one_object, &info, NULL);
191	if (ACPI_FAILURE (status)) {
192		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %x\n", status));
193	}
194
195	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK,
196		"\n%d Control Methods found and parsed (%d nodes total)\n",
197		info.method_count, info.object_count));
198	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
199		"%d Control Methods found\n", info.method_count));
200	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
201		"%d Op Regions found\n", info.op_region_count));
202
203	return_ACPI_STATUS (AE_OK);
204}
205
206
207/*****************************************************************************
208 *
209 * FUNCTION:    Acpi_ds_init_object_from_op
210 *
211 * PARAMETERS:  Op              - Parser op used to init the internal object
212 *              Opcode          - AML opcode associated with the object
213 *              Obj_desc        - Namespace object to be initialized
214 *
215 * RETURN:      Status
216 *
217 * DESCRIPTION: Initialize a namespace object from a parser Op and its
218 *              associated arguments.  The namespace object is a more compact
219 *              representation of the Op and its arguments.
220 *
221 ****************************************************************************/
222
223acpi_status
224acpi_ds_init_object_from_op (
225	acpi_walk_state         *walk_state,
226	acpi_parse_object       *op,
227	u16                     opcode,
228	acpi_operand_object     **ret_obj_desc)
229{
230	acpi_status             status;
231	acpi_parse_object       *arg;
232	acpi_parse2_object      *byte_list;
233	acpi_operand_object     *arg_desc;
234	const acpi_opcode_info  *op_info;
235	acpi_operand_object     *obj_desc;
236
237
238	PROC_NAME ("Ds_init_object_from_op");
239
240
241	obj_desc = *ret_obj_desc;
242	op_info = acpi_ps_get_opcode_info (opcode);
243	if (op_info->class == AML_CLASS_UNKNOWN) {
244		/* Unknown opcode */
245
246		return (AE_TYPE);
247	}
248
249
250	/* Get and prepare the first argument */
251
252	switch (obj_desc->common.type) {
253	case ACPI_TYPE_BUFFER:
254
255		/* First arg is a number */
256
257		acpi_ds_create_operand (walk_state, op->value.arg, 0);
258		arg_desc = walk_state->operands [walk_state->num_operands - 1];
259		acpi_ds_obj_stack_pop (1, walk_state);
260
261		/* Resolve the object (could be an arg or local) */
262
263		status = acpi_ex_resolve_to_value (&arg_desc, walk_state);
264		if (ACPI_FAILURE (status)) {
265			acpi_ut_remove_reference (arg_desc);
266			return (status);
267		}
268
269		/* We are expecting a number */
270
271		if (arg_desc->common.type != ACPI_TYPE_INTEGER) {
272			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
273				"Expecting number, got obj: %p type %X\n",
274				arg_desc, arg_desc->common.type));
275			acpi_ut_remove_reference (arg_desc);
276			return (AE_TYPE);
277		}
278
279		/* Get the value, delete the internal object */
280
281		obj_desc->buffer.length = (u32) arg_desc->integer.value;
282		acpi_ut_remove_reference (arg_desc);
283
284		/* Allocate the buffer */
285
286		if (obj_desc->buffer.length == 0) {
287			obj_desc->buffer.pointer = NULL;
288			REPORT_WARNING (("Buffer created with zero length in AML\n"));
289			break;
290		}
291
292		else {
293			obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
294					   obj_desc->buffer.length);
295
296			if (!obj_desc->buffer.pointer) {
297				return (AE_NO_MEMORY);
298			}
299		}
300
301		/*
302		 * Second arg is the buffer data (optional) Byte_list can be either
303		 * individual bytes or a string initializer.
304		 */
305		arg = op->value.arg;         /* skip first arg */
306
307		byte_list = (acpi_parse2_object *) arg->next;
308		if (byte_list) {
309			if (byte_list->opcode != AML_INT_BYTELIST_OP) {
310				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Expecting bytelist, got: %p\n",
311					byte_list));
312				return (AE_TYPE);
313			}
314
315			MEMCPY (obj_desc->buffer.pointer, byte_list->data,
316					obj_desc->buffer.length);
317		}
318
319		break;
320
321
322	case ACPI_TYPE_PACKAGE:
323
324		/*
325		 * When called, an internal package object has already been built and
326		 * is pointed to by Obj_desc. Acpi_ds_build_internal_object builds another
327		 * internal package object, so remove reference to the original so
328		 * that it is deleted.  Error checking is done within the remove
329		 * reference function.
330		 */
331		acpi_ut_remove_reference (obj_desc);
332		status = acpi_ds_build_internal_object (walk_state, op, ret_obj_desc);
333		break;
334
335	case ACPI_TYPE_INTEGER:
336		obj_desc->integer.value = op->value.integer;
337		break;
338
339
340	case ACPI_TYPE_STRING:
341		obj_desc->string.pointer = op->value.string;
342		obj_desc->string.length = STRLEN (op->value.string);
343
344		/*
345		 * The string is contained in the ACPI table, don't ever try
346		 * to delete it
347		 */
348		obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
349		break;
350
351
352	case ACPI_TYPE_METHOD:
353		break;
354
355
356	case INTERNAL_TYPE_REFERENCE:
357
358		switch (op_info->type) {
359		case AML_TYPE_LOCAL_VARIABLE:
360
361			/* Split the opcode into a base opcode + offset */
362
363			obj_desc->reference.opcode = AML_LOCAL_OP;
364			obj_desc->reference.offset = opcode - AML_LOCAL_OP;
365			break;
366
367
368		case AML_TYPE_METHOD_ARGUMENT:
369
370			/* Split the opcode into a base opcode + offset */
371
372			obj_desc->reference.opcode = AML_ARG_OP;
373			obj_desc->reference.offset = opcode - AML_ARG_OP;
374			break;
375
376
377		default: /* Constants, Literals, etc.. */
378
379			if (op->opcode == AML_INT_NAMEPATH_OP) {
380				/* Node was saved in Op */
381
382				obj_desc->reference.node = op->node;
383			}
384
385			obj_desc->reference.opcode = opcode;
386			break;
387		}
388
389		break;
390
391
392	default:
393
394		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %x\n",
395			obj_desc->common.type));
396
397		break;
398	}
399
400	return (AE_OK);
401}
402
403
404/*****************************************************************************
405 *
406 * FUNCTION:    Acpi_ds_build_internal_simple_obj
407 *
408 * PARAMETERS:  Op              - Parser object to be translated
409 *              Obj_desc_ptr    - Where the ACPI internal object is returned
410 *
411 * RETURN:      Status
412 *
413 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
414 *              Simple objects are any objects other than a package object!
415 *
416 ****************************************************************************/
417
418static acpi_status
419acpi_ds_build_internal_simple_obj (
420	acpi_walk_state         *walk_state,
421	acpi_parse_object       *op,
422	acpi_operand_object     **obj_desc_ptr)
423{
424	acpi_operand_object     *obj_desc;
425	acpi_object_type8       type;
426	acpi_status             status;
427	u32                     length;
428	char                    *name;
429
430
431	FUNCTION_TRACE ("Ds_build_internal_simple_obj");
432
433
434	if (op->opcode == AML_INT_NAMEPATH_OP) {
435		/*
436		 * This is an object reference.  If The name was
437		 * previously looked up in the NS, it is stored in this op.
438		 * Otherwise, go ahead and look it up now
439		 */
440		if (!op->node) {
441			status = acpi_ns_lookup (walk_state->scope_info,
442					  op->value.string, ACPI_TYPE_ANY,
443					  IMODE_EXECUTE,
444					  NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
445					  NULL,
446					  (acpi_namespace_node **)&(op->node));
447
448			if (ACPI_FAILURE (status)) {
449				if (status == AE_NOT_FOUND) {
450					name = NULL;
451					acpi_ns_externalize_name (ACPI_UINT32_MAX, op->value.string, &length, &name);
452
453					if (name) {
454						REPORT_WARNING (("Reference %s at AML %X not found\n",
455								 name, op->aml_offset));
456						ACPI_MEM_FREE (name);
457					}
458
459					else {
460						REPORT_WARNING (("Reference %s at AML %X not found\n",
461								   op->value.string, op->aml_offset));
462					}
463
464					*obj_desc_ptr = NULL;
465				}
466
467				else {
468					return_ACPI_STATUS (status);
469				}
470			}
471		}
472
473		/*
474		 * The reference will be a Reference
475		 * TBD: [Restructure] unless we really need a separate
476		 *  type of INTERNAL_TYPE_REFERENCE change
477		 *  Acpi_ds_map_opcode_to_data_type to handle this case
478		 */
479		type = INTERNAL_TYPE_REFERENCE;
480	}
481	else {
482		type = acpi_ds_map_opcode_to_data_type (op->opcode, NULL);
483	}
484
485
486	/* Create and init the internal ACPI object */
487
488	obj_desc = acpi_ut_create_internal_object (type);
489	if (!obj_desc) {
490		return_ACPI_STATUS (AE_NO_MEMORY);
491	}
492
493	status = acpi_ds_init_object_from_op (walk_state, op, op->opcode, &obj_desc);
494	if (ACPI_FAILURE (status)) {
495		acpi_ut_remove_reference (obj_desc);
496		return_ACPI_STATUS (status);
497	}
498
499	*obj_desc_ptr = obj_desc;
500
501	return_ACPI_STATUS (AE_OK);
502}
503
504
505/*****************************************************************************
506 *
507 * FUNCTION:    Acpi_ds_build_internal_package_obj
508 *
509 * PARAMETERS:  Op              - Parser object to be translated
510 *              Obj_desc_ptr    - Where the ACPI internal object is returned
511 *
512 * RETURN:      Status
513 *
514 * DESCRIPTION: Translate a parser Op package object to the equivalent
515 *              namespace object
516 *
517 ****************************************************************************/
518
519acpi_status
520acpi_ds_build_internal_package_obj (
521	acpi_walk_state         *walk_state,
522	acpi_parse_object       *op,
523	acpi_operand_object     **obj_desc_ptr)
524{
525	acpi_parse_object       *arg;
526	acpi_operand_object     *obj_desc;
527	acpi_status             status = AE_OK;
528
529
530	FUNCTION_TRACE ("Ds_build_internal_package_obj");
531
532
533	obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
534	*obj_desc_ptr = obj_desc;
535	if (!obj_desc) {
536		return_ACPI_STATUS (AE_NO_MEMORY);
537	}
538
539	if (op->opcode == AML_VAR_PACKAGE_OP) {
540		/*
541		 * Variable length package parameters are evaluated JIT
542		 */
543		return_ACPI_STATUS (AE_OK);
544	}
545
546	/* The first argument must be the package length */
547
548	arg = op->value.arg;
549	obj_desc->package.count = arg->value.integer32;
550
551	/*
552	 * Allocate the array of pointers (ptrs to the
553	 * individual objects) Add an extra pointer slot so
554	 * that the list is always null terminated.
555	 */
556	obj_desc->package.elements = ACPI_MEM_CALLOCATE (
557			 (obj_desc->package.count + 1) * sizeof (void *));
558
559	if (!obj_desc->package.elements) {
560		acpi_ut_delete_object_desc (obj_desc);
561		return_ACPI_STATUS (AE_NO_MEMORY);
562	}
563
564	obj_desc->package.next_element = obj_desc->package.elements;
565
566	/*
567	 * Now init the elements of the package
568	 */
569	arg = arg->next;
570	while (arg) {
571		if (arg->opcode == AML_PACKAGE_OP) {
572			status = acpi_ds_build_internal_package_obj (walk_state, arg,
573					  obj_desc->package.next_element);
574		}
575
576		else {
577			status = acpi_ds_build_internal_simple_obj (walk_state, arg,
578					  obj_desc->package.next_element);
579		}
580
581		obj_desc->package.next_element++;
582		arg = arg->next;
583	}
584
585	obj_desc->package.flags |= AOPOBJ_DATA_VALID;
586	return_ACPI_STATUS (status);
587}
588
589
590/*****************************************************************************
591 *
592 * FUNCTION:    Acpi_ds_build_internal_object
593 *
594 * PARAMETERS:  Op              - Parser object to be translated
595 *              Obj_desc_ptr    - Where the ACPI internal object is returned
596 *
597 * RETURN:      Status
598 *
599 * DESCRIPTION: Translate a parser Op object to the equivalent namespace
600 *              object
601 *
602 ****************************************************************************/
603
604acpi_status
605acpi_ds_build_internal_object (
606	acpi_walk_state         *walk_state,
607	acpi_parse_object       *op,
608	acpi_operand_object     **obj_desc_ptr)
609{
610	acpi_status             status;
611
612
613	switch (op->opcode) {
614	case AML_PACKAGE_OP:
615	case AML_VAR_PACKAGE_OP:
616
617		status = acpi_ds_build_internal_package_obj (walk_state, op, obj_desc_ptr);
618		break;
619
620
621	default:
622
623		status = acpi_ds_build_internal_simple_obj (walk_state, op, obj_desc_ptr);
624		break;
625	}
626
627	return (status);
628}
629
630
631/*****************************************************************************
632 *
633 * FUNCTION:    Acpi_ds_create_node
634 *
635 * PARAMETERS:  Op              - Parser object to be translated
636 *              Obj_desc_ptr    - Where the ACPI internal object is returned
637 *
638 * RETURN:      Status
639 *
640 * DESCRIPTION:
641 *
642 ****************************************************************************/
643
644acpi_status
645acpi_ds_create_node (
646	acpi_walk_state         *walk_state,
647	acpi_namespace_node     *node,
648	acpi_parse_object       *op)
649{
650	acpi_status             status;
651	acpi_operand_object     *obj_desc;
652
653
654	FUNCTION_TRACE_PTR ("Ds_create_node", op);
655
656
657	/*
658	 * Because of the execution pass through the non-control-method
659	 * parts of the table, we can arrive here twice.  Only init
660	 * the named object node the first time through
661	 */
662	if (node->object) {
663		return_ACPI_STATUS (AE_OK);
664	}
665
666	if (!op->value.arg) {
667		/* No arguments, there is nothing to do */
668
669		return_ACPI_STATUS (AE_OK);
670	}
671
672	/* Build an internal object for the argument(s) */
673
674	status = acpi_ds_build_internal_object (walk_state, op->value.arg, &obj_desc);
675	if (ACPI_FAILURE (status)) {
676		return_ACPI_STATUS (status);
677	}
678
679	/* Re-type the object according to it's argument */
680
681	node->type = obj_desc->common.type;
682
683	/* Init obj */
684
685	status = acpi_ns_attach_object (node, obj_desc, (u8) node->type);
686
687	/* Remove local reference to the object */
688
689	acpi_ut_remove_reference (obj_desc);
690	return_ACPI_STATUS (status);
691}
692
693
694