File: /usr/src/linux/drivers/acpi/namespace/nsload.c

1     /******************************************************************************
2      *
3      * Module Name: nsload - namespace loading/expanding/contracting procedures
4      *              $Revision: 43 $
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 "acinterp.h"
29     #include "acnamesp.h"
30     #include "amlcode.h"
31     #include "acparser.h"
32     #include "acdispat.h"
33     #include "acdebug.h"
34     
35     
36     #define _COMPONENT          ACPI_NAMESPACE
37     	 MODULE_NAME         ("nsload")
38     
39     
40     /*******************************************************************************
41      *
42      * FUNCTION:    Acpi_load_namespace
43      *
44      * PARAMETERS:  Display_aml_during_load
45      *
46      * RETURN:      Status
47      *
48      * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
49      *              (DSDT points to either the BIOS or a buffer.)
50      *
51      ******************************************************************************/
52     
53     acpi_status
54     acpi_ns_load_namespace (
55     	void)
56     {
57     	acpi_status             status;
58     
59     
60     	FUNCTION_TRACE ("Acpi_load_name_space");
61     
62     
63     	/* There must be at least a DSDT installed */
64     
65     	if (acpi_gbl_DSDT == NULL) {
66     		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n"));
67     		return_ACPI_STATUS (AE_NO_ACPI_TABLES);
68     	}
69     
70     
71     	/*
72     	 * Load the namespace.  The DSDT is required,
73     	 * but the SSDT and PSDT tables are optional.
74     	 */
75     	status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
76     	if (ACPI_FAILURE (status)) {
77     		return_ACPI_STATUS (status);
78     	}
79     
80     	/* Ignore exceptions from these */
81     
82     	acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
83     	acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
84     
85     
86     	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK,
87     		"ACPI Namespace successfully loaded at root %p\n",
88     		acpi_gbl_root_node));
89     
90     
91     	return_ACPI_STATUS (status);
92     }
93     
94     
95     /*******************************************************************************
96      *
97      * FUNCTION:    Acpi_ns_one_parse_pass
98      *
99      * PARAMETERS:
100      *
101      * RETURN:      Status
102      *
103      * DESCRIPTION:
104      *
105      ******************************************************************************/
106     
107     acpi_status
108     acpi_ns_one_complete_parse (
109     	u32                     pass_number,
110     	acpi_table_desc         *table_desc)
111     {
112     	acpi_parse_downwards    descending_callback;
113     	acpi_parse_upwards      ascending_callback;
114     	acpi_parse_object       *parse_root;
115     	acpi_status             status;
116     
117     
118     	FUNCTION_TRACE ("Ns_one_complete_parse");
119     
120     
121     	switch (pass_number) {
122     	case 1:
123     		descending_callback = acpi_ds_load1_begin_op;
124     		ascending_callback = acpi_ds_load1_end_op;
125     		break;
126     
127     	case 2:
128     		descending_callback = acpi_ds_load2_begin_op;
129     		ascending_callback = acpi_ds_load2_end_op;
130     		break;
131     
132     	case 3:
133     		descending_callback = acpi_ds_exec_begin_op;
134     		ascending_callback = acpi_ds_exec_end_op;
135     		break;
136     
137     	default:
138     		return (AE_BAD_PARAMETER);
139     	}
140     
141     	/* Create and init a Root Node */
142     
143     	parse_root = acpi_ps_alloc_op (AML_SCOPE_OP);
144     	if (!parse_root) {
145     		return_ACPI_STATUS (AE_NO_MEMORY);
146     	}
147     
148     	((acpi_parse2_object *) parse_root)->name = ACPI_ROOT_NAME;
149     
150     
151     	/* Pass 1:  Parse everything except control method bodies */
152     
153     	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "*PARSE* pass %d parse\n", pass_number));
154     
155     	status = acpi_ps_parse_aml (parse_root, table_desc->aml_pointer,
156     			 table_desc->aml_length,
157     			 ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE,
158     			 NULL, NULL, NULL, descending_callback,
159     			 ascending_callback);
160     
161     	acpi_ps_delete_parse_tree (parse_root);
162     	return_ACPI_STATUS (status);
163     }
164     
165     
166     /*******************************************************************************
167      *
168      * FUNCTION:    Acpi_ns_parse_table
169      *
170      * PARAMETERS:  Table_desc      - An ACPI table descriptor for table to parse
171      *              Start_node      - Where to enter the table into the namespace
172      *
173      * RETURN:      Status
174      *
175      * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
176      *
177      ******************************************************************************/
178     
179     acpi_status
180     acpi_ns_parse_table (
181     	acpi_table_desc         *table_desc,
182     	acpi_namespace_node     *start_node)
183     {
184     	acpi_status             status;
185     
186     
187     	FUNCTION_TRACE ("Ns_parse_table");
188     
189     
190     	/*
191     	 * AML Parse, pass 1
192     	 *
193     	 * In this pass, we load most of the namespace.  Control methods
194     	 * are not parsed until later.  A parse tree is not created.  Instead,
195     	 * each Parser Op subtree is deleted when it is finished.  This saves
196     	 * a great deal of memory, and allows a small cache of parse objects
197     	 * to service the entire parse.  The second pass of the parse then
198     	 * performs another complete parse of the AML..
199     	 */
200     	status = acpi_ns_one_complete_parse (1, table_desc);
201     	if (ACPI_FAILURE (status)) {
202     		return_ACPI_STATUS (status);
203     	}
204     
205     
206     	/*
207     	 * AML Parse, pass 2
208     	 *
209     	 * In this pass, we resolve forward references and other things
210     	 * that could not be completed during the first pass.
211     	 * Another complete parse of the AML is performed, but the
212     	 * overhead of this is compensated for by the fact that the
213     	 * parse objects are all cached.
214     	 */
215     	status = acpi_ns_one_complete_parse (2, table_desc);
216     	if (ACPI_FAILURE (status)) {
217     		return_ACPI_STATUS (status);
218     	}
219     
220     	return_ACPI_STATUS (status);
221     }
222     
223     
224     /*******************************************************************************
225      *
226      * FUNCTION:    Acpi_ns_load_table
227      *
228      * PARAMETERS:  *Pcode_addr         - Address of pcode block
229      *              Pcode_length        - Length of pcode block
230      *
231      * RETURN:      Status
232      *
233      * DESCRIPTION: Load one ACPI table into the namespace
234      *
235      ******************************************************************************/
236     
237     acpi_status
238     acpi_ns_load_table (
239     	acpi_table_desc         *table_desc,
240     	acpi_namespace_node     *node)
241     {
242     	acpi_status             status;
243     
244     
245     	FUNCTION_TRACE ("Ns_load_table");
246     
247     
248     	if (!table_desc->aml_pointer) {
249     		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null AML pointer\n"));
250     		return_ACPI_STATUS (AE_BAD_PARAMETER);
251     	}
252     
253     	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AML block at %p\n", table_desc->aml_pointer));
254     
255     
256     	if (!table_desc->aml_length) {
257     		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Zero-length AML block\n"));
258     		return_ACPI_STATUS (AE_BAD_PARAMETER);
259     	}
260     
261     
262     	/*
263     	 * Parse the table and load the namespace with all named
264     	 * objects found within.  Control methods are NOT parsed
265     	 * at this time.  In fact, the control methods cannot be
266     	 * parsed until the entire namespace is loaded, because
267     	 * if a control method makes a forward reference (call)
268     	 * to another control method, we can't continue parsing
269     	 * because we don't know how many arguments to parse next!
270     	 */
271     	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Loading table into namespace ****\n"));
272     
273     	acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
274     	status = acpi_ns_parse_table (table_desc, node->child);
275     	acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
276     
277     	if (ACPI_FAILURE (status)) {
278     		return_ACPI_STATUS (status);
279     	}
280     
281     	/*
282     	 * Now we can parse the control methods.  We always parse
283     	 * them here for a sanity check, and if configured for
284     	 * just-in-time parsing, we delete the control method
285     	 * parse trees.
286     	 */
287     	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
288     		"**** Begin Table Method Parsing and Object Initialization ****\n"));
289     
290     	status = acpi_ds_initialize_objects (table_desc, node);
291     
292     	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
293     		"**** Completed Table Method Parsing and Object Initialization ****\n"));
294     
295     	return_ACPI_STATUS (status);
296     }
297     
298     
299     /*******************************************************************************
300      *
301      * FUNCTION:    Acpi_ns_load_table_by_type
302      *
303      * PARAMETERS:  Table_type          - Id of the table type to load
304      *
305      * RETURN:      Status
306      *
307      * DESCRIPTION: Load an ACPI table or tables into the namespace.  All tables
308      *              of the given type are loaded.  The mechanism allows this
309      *              routine to be called repeatedly.
310      *
311      ******************************************************************************/
312     
313     acpi_status
314     acpi_ns_load_table_by_type (
315     	acpi_table_type         table_type)
316     {
317     	u32                     i;
318     	acpi_status             status = AE_OK;
319     	acpi_table_desc         *table_desc;
320     
321     
322     	FUNCTION_TRACE ("Ns_load_table_by_type");
323     
324     
325     	acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
326     
327     
328     	/*
329     	 * Table types supported are:
330     	 * DSDT (one), SSDT/PSDT (multiple)
331     	 */
332     	switch (table_type) {
333     
334     	case ACPI_TABLE_DSDT:
335     
336     		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDT\n"));
337     
338     		table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_DSDT];
339     
340     		/* If table already loaded into namespace, just return */
341     
342     		if (table_desc->loaded_into_namespace) {
343     			goto unlock_and_exit;
344     		}
345     
346     		table_desc->table_id = TABLE_ID_DSDT;
347     
348     		/* Now load the single DSDT */
349     
350     		status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
351     		if (ACPI_SUCCESS (status)) {
352     			table_desc->loaded_into_namespace = TRUE;
353     		}
354     
355     		break;
356     
357     
358     	case ACPI_TABLE_SSDT:
359     
360     		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTs\n",
361     			acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count));
362     
363     		/*
364     		 * Traverse list of SSDT tables
365     		 */
366     		table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT];
367     		for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) {
368     			/*
369     			 * Only attempt to load table if it is not
370     			 * already loaded!
371     			 */
372     			if (!table_desc->loaded_into_namespace) {
373     				status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
374     				if (ACPI_FAILURE (status)) {
375     					break;
376     				}
377     
378     				table_desc->loaded_into_namespace = TRUE;
379     			}
380     
381     			table_desc = table_desc->next;
382     		}
383     		break;
384     
385     
386     	case ACPI_TABLE_PSDT:
387     
388     		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTs\n",
389     			acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count));
390     
391     		/*
392     		 * Traverse list of PSDT tables
393     		 */
394     		table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT];
395     
396     		for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) {
397     			/* Only attempt to load table if it is not already loaded! */
398     
399     			if (!table_desc->loaded_into_namespace) {
400     				status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
401     				if (ACPI_FAILURE (status)) {
402     					break;
403     				}
404     
405     				table_desc->loaded_into_namespace = TRUE;
406     			}
407     
408     			table_desc = table_desc->next;
409     		}
410     
411     		break;
412     
413     
414     	default:
415     		status = AE_SUPPORT;
416     		break;
417     	}
418     
419     
420     unlock_and_exit:
421     
422     	acpi_ut_release_mutex (ACPI_MTX_TABLES);
423     
424     	return_ACPI_STATUS (status);
425     
426     }
427     
428     
429     /*******************************************************************************
430      *
431      * FUNCTION:    Acpi_ns_delete_subtree
432      *
433      * PARAMETERS:  Start_handle        - Handle in namespace where search begins
434      *
435      * RETURNS      Status
436      *
437      * DESCRIPTION: Walks the namespace starting at the given handle and deletes
438      *              all objects, entries, and scopes in the entire subtree.
439      *
440      *              TBD: [Investigate] What if any part of this subtree is in use?
441      *              (i.e. on one of the object stacks?)
442      *
443      ******************************************************************************/
444     
445     acpi_status
446     acpi_ns_delete_subtree (
447     	acpi_handle             start_handle)
448     {
449     	acpi_status             status;
450     	acpi_handle             child_handle;
451     	acpi_handle             parent_handle;
452     	acpi_handle             next_child_handle;
453     	acpi_handle             dummy;
454     	u32                     level;
455     
456     
457     	FUNCTION_TRACE ("Ns_delete_subtree");
458     
459     
460     	parent_handle = start_handle;
461     	child_handle = 0;
462     	level        = 1;
463     
464     	/*
465     	 * Traverse the tree of objects until we bubble back up
466     	 * to where we started.
467     	 */
468     	while (level > 0) {
469     		/* Attempt to get the next object in this scope */
470     
471     		status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle,
472     				  child_handle, &next_child_handle);
473     
474     		child_handle = next_child_handle;
475     
476     
477     		/* Did we get a new object? */
478     
479     		if (ACPI_SUCCESS (status)) {
480     			/* Check if this object has any children */
481     
482     			if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle,
483     					 0, &dummy))) {
484     				/*
485     				 * There is at least one child of this object,
486     				 * visit the object
487     				 */
488     				level++;
489     				parent_handle = child_handle;
490     				child_handle = 0;
491     			}
492     		}
493     
494     		else {
495     			/*
496     			 * No more children in this object, go back up to
497     			 * the object's parent
498     			 */
499     			level--;
500     
501     			/* Delete all children now */
502     
503     			acpi_ns_delete_children (child_handle);
504     
505     			child_handle = parent_handle;
506     			acpi_get_parent (parent_handle, &parent_handle);
507     		}
508     	}
509     
510     	/* Now delete the starting object, and we are done */
511     
512     	acpi_ns_delete_node (child_handle);
513     
514     	return_ACPI_STATUS (AE_OK);
515     }
516     
517     
518     /*******************************************************************************
519      *
520      *  FUNCTION:       Acpi_ns_unload_name_space
521      *
522      *  PARAMETERS:     Handle          - Root of namespace subtree to be deleted
523      *
524      *  RETURN:         Status
525      *
526      *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
527      *                  event.  Deletes an entire subtree starting from (and
528      *                  including) the given handle.
529      *
530      ******************************************************************************/
531     
532     acpi_status
533     acpi_ns_unload_namespace (
534     	acpi_handle             handle)
535     {
536     	acpi_status             status;
537     
538     
539     	FUNCTION_TRACE ("Ns_unload_name_space");
540     
541     
542     	/* Parameter validation */
543     
544     	if (!acpi_gbl_root_node) {
545     		return_ACPI_STATUS (AE_NO_NAMESPACE);
546     	}
547     
548     	if (!handle) {
549     		return_ACPI_STATUS (AE_BAD_PARAMETER);
550     	}
551     
552     
553     	/* This function does the real work */
554     
555     	status = acpi_ns_delete_subtree (handle);
556     
557     	return_ACPI_STATUS (status);
558     }
559     
560     
561