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