1/******************************************************************************
2 *
3 * Module Name: dswload - Dispatcher namespace load callbacks
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#include "acevents.h"
34
35
36#define _COMPONENT          ACPI_DISPATCHER
37	 MODULE_NAME         ("dswload")
38
39
40/*******************************************************************************
41 *
42 * FUNCTION:    Acpi_ds_init_callbacks
43 *
44 * PARAMETERS:  Walk_state      - Current state of the parse tree walk
45 *              Pass_number     - 1, 2, or 3
46 *
47 * RETURN:      Status
48 *
49 * DESCRIPTION: Init walk state callbacks
50 *
51 ******************************************************************************/
52
53acpi_status
54acpi_ds_init_callbacks (
55	acpi_walk_state         *walk_state,
56	u32                     pass_number)
57{
58
59	switch (pass_number) {
60	case 1:
61		walk_state->parse_flags       = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE;
62		walk_state->descending_callback = acpi_ds_load1_begin_op;
63		walk_state->ascending_callback = acpi_ds_load1_end_op;
64		break;
65
66	case 2:
67		walk_state->parse_flags       = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE;
68		walk_state->descending_callback = acpi_ds_load2_begin_op;
69		walk_state->ascending_callback = acpi_ds_load2_end_op;
70		break;
71
72	case 3:
73		walk_state->parse_flags      |= ACPI_PARSE_EXECUTE  | ACPI_PARSE_DELETE_TREE;
74		walk_state->descending_callback = acpi_ds_exec_begin_op;
75		walk_state->ascending_callback = acpi_ds_exec_end_op;
76		break;
77
78	default:
79		return (AE_BAD_PARAMETER);
80		break;
81	}
82
83	return (AE_OK);
84}
85
86
87/*******************************************************************************
88 *
89 * FUNCTION:    Acpi_ds_load1_begin_op
90 *
91 * PARAMETERS:  Walk_state      - Current state of the parse tree walk
92 *              Op              - Op that has been just been reached in the
93 *                                walk;  Arguments have not been evaluated yet.
94 *
95 * RETURN:      Status
96 *
97 * DESCRIPTION: Descending callback used during the loading of ACPI tables.
98 *
99 ******************************************************************************/
100
101acpi_status
102acpi_ds_load1_begin_op (
103	acpi_walk_state         *walk_state,
104	acpi_parse_object       **out_op)
105{
106	acpi_parse_object       *op;
107	acpi_namespace_node     *node;
108	acpi_status             status;
109	acpi_object_type8       data_type;
110	NATIVE_CHAR             *path;
111
112
113	PROC_NAME ("Ds_load1_begin_op");
114
115	op = walk_state->op;
116	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
117
118
119	/* We are only interested in opcodes that have an associated name */
120
121	if (walk_state->op) {
122	   if (!(walk_state->op_info->flags & AML_NAMED)) {
123			*out_op = op;
124			return (AE_OK);
125		}
126
127		/* Check if this object has already been installed in the namespace */
128
129		if (op->node) {
130			*out_op = op;
131			return (AE_OK);
132		}
133	}
134
135	path = acpi_ps_get_next_namestring (&walk_state->parser_state);
136
137	/* Map the raw opcode into an internal object type */
138
139	data_type = acpi_ds_map_named_opcode_to_data_type (walk_state->opcode);
140
141
142	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
143		"State=%p Op=%p Type=%x\n", walk_state, op, data_type));
144
145
146	if (walk_state->opcode == AML_SCOPE_OP) {
147		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
148			"State=%p Op=%p Type=%x\n", walk_state, op, data_type));
149	}
150
151	/*
152	 * Enter the named type into the internal namespace.  We enter the name
153	 * as we go downward in the parse tree.  Any necessary subobjects that involve
154	 * arguments to the opcode must be created as we go back up the parse tree later.
155	 */
156	status = acpi_ns_lookup (walk_state->scope_info, path, data_type,
157			  IMODE_LOAD_PASS1, NS_NO_UPSEARCH, walk_state, &(node));
158
159	if (ACPI_FAILURE (status)) {
160		return (status);
161	}
162
163	if (!op) {
164		/* Create a new op */
165
166		op = acpi_ps_alloc_op (walk_state->opcode);
167		if (!op) {
168			return (AE_NO_MEMORY);
169		}
170	}
171
172	/* Initialize */
173
174	((acpi_parse2_object *)op)->name = node->name;
175
176	/*
177	 * Put the Node in the "op" object that the parser uses, so we
178	 * can get it again quickly when this scope is closed
179	 */
180	op->node = node;
181	acpi_ps_append_arg (acpi_ps_get_parent_scope (&walk_state->parser_state), op);
182
183	*out_op = op;
184	return (status);
185}
186
187
188/*******************************************************************************
189 *
190 * FUNCTION:    Acpi_ds_load1_end_op
191 *
192 * PARAMETERS:  Walk_state      - Current state of the parse tree walk
193 *              Op              - Op that has been just been completed in the
194 *                                walk;  Arguments have now been evaluated.
195 *
196 * RETURN:      Status
197 *
198 * DESCRIPTION: Ascending callback used during the loading of the namespace,
199 *              both control methods and everything else.
200 *
201 ******************************************************************************/
202
203acpi_status
204acpi_ds_load1_end_op (
205	acpi_walk_state         *walk_state)
206{
207	acpi_parse_object       *op;
208	acpi_object_type8       data_type;
209
210
211	PROC_NAME ("Ds_load1_end_op");
212
213	op = walk_state->op;
214	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
215
216
217	/* We are only interested in opcodes that have an associated name */
218
219	if (!(walk_state->op_info->flags & AML_NAMED)) {
220		return (AE_OK);
221	}
222
223	/* Get the type to determine if we should pop the scope */
224
225	data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);
226
227	if (op->opcode == AML_NAME_OP) {
228		/* For Name opcode, check the argument */
229
230		if (op->value.arg) {
231			data_type = acpi_ds_map_opcode_to_data_type (
232					  (op->value.arg)->opcode, NULL);
233			((acpi_namespace_node *)op->node)->type =
234					  (u8) data_type;
235		}
236	}
237
238	/* Pop the scope stack */
239
240	if (acpi_ns_opens_scope (data_type)) {
241		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n",
242			acpi_ut_get_type_name (data_type), op));
243
244		acpi_ds_scope_stack_pop (walk_state);
245	}
246
247	return (AE_OK);
248}
249
250
251/*******************************************************************************
252 *
253 * FUNCTION:    Acpi_ds_load2_begin_op
254 *
255 * PARAMETERS:  Walk_state      - Current state of the parse tree walk
256 *              Op              - Op that has been just been reached in the
257 *                                walk;  Arguments have not been evaluated yet.
258 *
259 * RETURN:      Status
260 *
261 * DESCRIPTION: Descending callback used during the loading of ACPI tables.
262 *
263 ******************************************************************************/
264
265acpi_status
266acpi_ds_load2_begin_op (
267	acpi_walk_state         *walk_state,
268	acpi_parse_object       **out_op)
269{
270	acpi_parse_object       *op;
271	acpi_namespace_node     *node;
272	acpi_status             status;
273	acpi_object_type8       data_type;
274	NATIVE_CHAR             *buffer_ptr;
275	void                    *original = NULL;
276
277
278	PROC_NAME ("Ds_load2_begin_op");
279
280	op = walk_state->op;
281	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
282
283
284	if (op) {
285		/* We only care about Namespace opcodes here */
286
287		if (!(walk_state->op_info->flags & AML_NSOPCODE) &&
288			walk_state->opcode != AML_INT_NAMEPATH_OP) {
289			return (AE_OK);
290		}
291
292		/* TBD: [Restructure] Temp! same code as in psparse */
293
294		if (!(walk_state->op_info->flags & AML_NAMED)) {
295			return (AE_OK);
296		}
297
298		/*
299		 * Get the name we are going to enter or lookup in the namespace
300		 */
301		if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
302			/* For Namepath op, get the path string */
303
304			buffer_ptr = op->value.string;
305			if (!buffer_ptr) {
306				/* No name, just exit */
307
308				return (AE_OK);
309			}
310		}
311		else {
312			/* Get name from the op */
313
314			buffer_ptr = (NATIVE_CHAR *) &((acpi_parse2_object *)op)->name;
315		}
316	}
317	else {
318		buffer_ptr = acpi_ps_get_next_namestring (&walk_state->parser_state);
319	}
320
321
322	/* Map the raw opcode into an internal object type */
323
324	data_type = acpi_ds_map_named_opcode_to_data_type (walk_state->opcode);
325
326	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
327		"State=%p Op=%p Type=%x\n", walk_state, op, data_type));
328
329
330	if (walk_state->opcode == AML_FIELD_OP         ||
331		walk_state->opcode == AML_BANK_FIELD_OP    ||
332		walk_state->opcode == AML_INDEX_FIELD_OP) {
333		node = NULL;
334		status = AE_OK;
335	}
336
337	else if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
338		/*
339		 * The Name_path is an object reference to an existing object. Don't enter the
340		 * name into the namespace, but look it up for use later
341		 */
342		status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type,
343				  IMODE_EXECUTE, NS_SEARCH_PARENT, walk_state, &(node));
344	}
345
346	else {
347		if (op && op->node) {
348			original = op->node;
349			node = op->node;
350
351			if (acpi_ns_opens_scope (data_type)) {
352				status = acpi_ds_scope_stack_push (node, data_type, walk_state);
353				if (ACPI_FAILURE (status)) {
354					return (status);
355				}
356
357			}
358			return (AE_OK);
359		}
360
361		/*
362		 * Enter the named type into the internal namespace.  We enter the name
363		 * as we go downward in the parse tree.  Any necessary subobjects that involve
364		 * arguments to the opcode must be created as we go back up the parse tree later.
365		 */
366		status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type,
367				  IMODE_EXECUTE, NS_NO_UPSEARCH, walk_state, &(node));
368	}
369
370	if (ACPI_SUCCESS (status)) {
371		if (!op) {
372			/* Create a new op */
373
374			op = acpi_ps_alloc_op (walk_state->opcode);
375			if (!op) {
376				return (AE_NO_MEMORY);
377			}
378
379			/* Initialize */
380
381			((acpi_parse2_object *)op)->name = node->name;
382			*out_op = op;
383		}
384
385		/*
386		 * Put the Node in the "op" object that the parser uses, so we
387		 * can get it again quickly when this scope is closed
388		 */
389		op->node = node;
390
391		if (original) {
392			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "old %p new %p\n", original, node));
393
394			if (original != node) {
395				ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
396					"Lookup match error: old %p new %p\n", original, node));
397			}
398		}
399	}
400
401	return (status);
402}
403
404
405/*******************************************************************************
406 *
407 * FUNCTION:    Acpi_ds_load2_end_op
408 *
409 * PARAMETERS:  Walk_state      - Current state of the parse tree walk
410 *              Op              - Op that has been just been completed in the
411 *                                walk;  Arguments have now been evaluated.
412 *
413 * RETURN:      Status
414 *
415 * DESCRIPTION: Ascending callback used during the loading of the namespace,
416 *              both control methods and everything else.
417 *
418 ******************************************************************************/
419
420acpi_status
421acpi_ds_load2_end_op (
422	acpi_walk_state         *walk_state)
423{
424	acpi_parse_object       *op;
425	acpi_status             status = AE_OK;
426	acpi_object_type8       data_type;
427	acpi_namespace_node     *node;
428	acpi_parse_object       *arg;
429	acpi_namespace_node     *new_node;
430	u32                     i;
431
432
433	PROC_NAME ("Ds_load2_end_op");
434
435	op = walk_state->op;
436	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
437
438
439	/* Only interested in opcodes that have namespace objects */
440
441	if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
442		return (AE_OK);
443	}
444
445	if (op->opcode == AML_SCOPE_OP) {
446		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
447			"Ending scope Op=%p State=%p\n", op, walk_state));
448
449		if (((acpi_parse2_object *)op)->name == -1) {
450			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unnamed scope! Op=%p State=%p\n",
451				op, walk_state));
452			return (AE_OK);
453		}
454	}
455
456
457	data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);
458
459	/*
460	 * Get the Node/name from the earlier lookup
461	 * (It was saved in the *op structure)
462	 */
463	node = op->node;
464
465	/*
466	 * Put the Node on the object stack (Contains the ACPI Name of
467	 * this object)
468	 */
469	walk_state->operands[0] = (void *) node;
470	walk_state->num_operands = 1;
471
472	/* Pop the scope stack */
473
474	if (acpi_ns_opens_scope (data_type)) {
475
476		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n",
477			acpi_ut_get_type_name (data_type), op));
478		acpi_ds_scope_stack_pop (walk_state);
479	}
480
481	/*
482	 * Named operations are as follows:
483	 *
484	 * AML_ALIAS
485	 * AML_BANKFIELD
486	 * AML_CREATEBITFIELD
487	 * AML_CREATEBYTEFIELD
488	 * AML_CREATEDWORDFIELD
489	 * AML_CREATEFIELD
490	 * AML_CREATEQWORDFIELD
491	 * AML_CREATEWORDFIELD
492	 * AML_DATA_REGION
493	 * AML_DEVICE
494	 * AML_EVENT
495	 * AML_FIELD
496	 * AML_INDEXFIELD
497	 * AML_METHOD
498	 * AML_METHODCALL
499	 * AML_MUTEX
500	 * AML_NAME
501	 * AML_NAMEDFIELD
502	 * AML_OPREGION
503	 * AML_POWERRES
504	 * AML_PROCESSOR
505	 * AML_SCOPE
506	 * AML_THERMALZONE
507	 */
508
509	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
510		"Create-Load [%s] State=%p Op=%p Named_obj=%p\n",
511		acpi_ps_get_opcode_name (op->opcode), walk_state, op, node));
512
513	/* Decode the opcode */
514
515	arg = op->value.arg;
516
517	switch (walk_state->op_info->type) {
518	case AML_TYPE_CREATE_FIELD:
519
520		/*
521		 * Create the field object, but the field buffer and index must
522		 * be evaluated later during the execution phase
523		 */
524		status = acpi_ds_create_buffer_field (op, walk_state);
525		break;
526
527
528	 case AML_TYPE_NAMED_FIELD:
529
530		arg = op->value.arg;
531		switch (op->opcode) {
532		case AML_INDEX_FIELD_OP:
533
534			status = acpi_ds_create_index_field (op, (acpi_handle) arg->node,
535					   walk_state);
536			break;
537
538
539		case AML_BANK_FIELD_OP:
540
541			status = acpi_ds_create_bank_field (op, arg->node, walk_state);
542			break;
543
544
545		case AML_FIELD_OP:
546
547			status = acpi_ds_create_field (op, arg->node, walk_state);
548			break;
549		}
550		break;
551
552
553	 case AML_TYPE_NAMED_SIMPLE:
554
555		status = acpi_ds_create_operands (walk_state, arg);
556		if (ACPI_FAILURE (status)) {
557			goto cleanup;
558		}
559
560		switch (op->opcode) {
561		case AML_PROCESSOR_OP:
562
563			status = acpi_ex_create_processor (walk_state);
564			break;
565
566
567		case AML_POWER_RES_OP:
568
569			status = acpi_ex_create_power_resource (walk_state);
570			break;
571
572
573		case AML_MUTEX_OP:
574
575			status = acpi_ex_create_mutex (walk_state);
576			break;
577
578
579		case AML_EVENT_OP:
580
581			status = acpi_ex_create_event (walk_state);
582			break;
583
584
585		case AML_DATA_REGION_OP:
586
587			status = acpi_ex_create_table_region (walk_state);
588			break;
589
590		case AML_ALIAS_OP:
591
592			status = acpi_ex_create_alias (walk_state);
593			break;
594
595		default:
596			/* Unknown opcode */
597
598			status = AE_OK;
599			goto cleanup;
600			break;
601		}
602
603		/* Delete operands */
604
605		for (i = 1; i < walk_state->num_operands; i++) {
606			acpi_ut_remove_reference (walk_state->operands[i]);
607			walk_state->operands[i] = NULL;
608		}
609
610		break;
611
612
613	case AML_TYPE_NAMED_COMPLEX:
614
615		switch (op->opcode) {
616		case AML_METHOD_OP:
617			/*
618			 * Method_op Pkg_length Names_string Method_flags Term_list
619			 */
620			ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
621				"LOADING-Method: State=%p Op=%p Named_obj=%p\n",
622				walk_state, op, node));
623
624			if (!node->object) {
625				status = acpi_ds_create_operands (walk_state, arg);
626				if (ACPI_FAILURE (status)) {
627					goto cleanup;
628				}
629
630				status = acpi_ex_create_method (((acpi_parse2_object *) op)->data,
631						   ((acpi_parse2_object *) op)->length,
632						   walk_state);
633			}
634			break;
635
636
637		case AML_REGION_OP:
638			/*
639			 * The Op_region is not fully parsed at this time. Only valid argument is the Space_id.
640			 * (We must save the address of the AML of the address and length operands)
641			 */
642			status = acpi_ex_create_region (((acpi_parse2_object *) op)->data,
643					  ((acpi_parse2_object *) op)->length,
644							 (ACPI_ADR_SPACE_TYPE) arg->value.integer, walk_state);
645			break;
646
647
648		case AML_NAME_OP:
649
650			status = acpi_ds_create_node (walk_state, node, op);
651			break;
652		}
653		break;
654
655
656	case AML_CLASS_INTERNAL:
657
658		/* case AML_INT_NAMEPATH_OP: */
659		break;
660
661
662	case AML_CLASS_METHOD_CALL:
663
664		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
665			"RESOLVING-Method_call: State=%p Op=%p Named_obj=%p\n",
666			walk_state, op, node));
667
668		/*
669		 * Lookup the method name and save the Node
670		 */
671		status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
672				  ACPI_TYPE_ANY, IMODE_LOAD_PASS2,
673				  NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
674				  walk_state, &(new_node));
675		if (ACPI_SUCCESS (status)) {
676			/* TBD: has name already been resolved by here ??*/
677
678			/* TBD: [Restructure] Make sure that what we found is indeed a method! */
679			/* We didn't search for a method on purpose, to see if the name would resolve! */
680
681			/* We could put the returned object (Node) on the object stack for later, but
682			 * for now, we will put it in the "op" object that the parser uses, so we
683			 * can get it again at the end of this scope
684			 */
685			op->node = new_node;
686		}
687
688		break;
689
690
691	default:
692		break;
693	}
694
695
696cleanup:
697
698	/* Remove the Node pushed at the very beginning */
699
700	walk_state->operands[0] = NULL;
701	walk_state->num_operands = 0;
702	return (status);
703}
704
705
706