1 /******************************************************************************
3 * Module Name: nsload - namespace loading/expanding/contracting procedures
6 *****************************************************************************/
9 * Copyright (C) 2000, 2001 R. Byron Moore
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.
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.
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
29 #define _COMPONENT ACPI_NAMESPACE
30 MODULE_NAME ("nsload")
33 /*******************************************************************************
35 * FUNCTION: Acpi_load_namespace
37 * PARAMETERS: Display_aml_during_load
41 * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
42 * (DSDT points to either the BIOS or a buffer.)
44 ******************************************************************************/
47 acpi_ns_load_namespace (
53 /* There must be at least a DSDT installed */
55 if (acpi_gbl_DSDT
== NULL
) {
56 return (AE_NO_ACPI_TABLES
);
61 * Load the namespace. The DSDT is required,
62 * but the SSDT and PSDT tables are optional.
65 status
= acpi_ns_load_table_by_type (ACPI_TABLE_DSDT
);
66 if (ACPI_FAILURE (status
)) {
70 /* Ignore exceptions from these */
72 acpi_ns_load_table_by_type (ACPI_TABLE_SSDT
);
73 acpi_ns_load_table_by_type (ACPI_TABLE_PSDT
);
80 /*******************************************************************************
82 * FUNCTION: Acpi_ns_one_parse_pass
90 ******************************************************************************/
93 acpi_ns_one_complete_parse (
95 ACPI_TABLE_DESC
*table_desc
)
97 ACPI_PARSE_DOWNWARDS descending_callback
;
98 ACPI_PARSE_UPWARDS ascending_callback
;
99 ACPI_PARSE_OBJECT
*parse_root
;
103 switch (pass_number
) {
105 descending_callback
= acpi_ds_load1_begin_op
;
106 ascending_callback
= acpi_ds_load1_end_op
;
110 descending_callback
= acpi_ds_load2_begin_op
;
111 ascending_callback
= acpi_ds_load2_end_op
;
115 descending_callback
= acpi_ds_exec_begin_op
;
116 ascending_callback
= acpi_ds_exec_end_op
;
120 return (AE_BAD_PARAMETER
);
123 /* Create and init a Root Node */
125 parse_root
= acpi_ps_alloc_op (AML_SCOPE_OP
);
127 return (AE_NO_MEMORY
);
130 ((ACPI_PARSE2_OBJECT
*) parse_root
)->name
= ACPI_ROOT_NAME
;
133 /* Pass 1: Parse everything except control method bodies */
135 status
= acpi_ps_parse_aml (parse_root
, table_desc
->aml_pointer
,
136 table_desc
->aml_length
,
137 ACPI_PARSE_LOAD_PASS1
| ACPI_PARSE_DELETE_TREE
,
138 NULL
, NULL
, NULL
, descending_callback
,
141 acpi_ps_delete_parse_tree (parse_root
);
147 /*******************************************************************************
149 * FUNCTION: Acpi_ns_parse_table
151 * PARAMETERS: Table_desc - An ACPI table descriptor for table to parse
152 * Start_node - Where to enter the table into the namespace
156 * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
158 ******************************************************************************/
161 acpi_ns_parse_table (
162 ACPI_TABLE_DESC
*table_desc
,
163 ACPI_NAMESPACE_NODE
*start_node
)
171 * In this pass, we load most of the namespace. Control methods
172 * are not parsed until later. A parse tree is not created. Instead,
173 * each Parser Op subtree is deleted when it is finished. This saves
174 * a great deal of memory, and allows a small cache of parse objects
175 * to service the entire parse. The second pass of the parse then
176 * performs another complete parse of the AML..
179 status
= acpi_ns_one_complete_parse (1, table_desc
);
180 if (ACPI_FAILURE (status
)) {
188 * In this pass, we resolve forward references and other things
189 * that could not be completed during the first pass.
190 * Another complete parse of the AML is performed, but the
191 * overhead of this is compensated for by the fact that the
192 * parse objects are all cached.
195 status
= acpi_ns_one_complete_parse (2, table_desc
);
196 if (ACPI_FAILURE (status
)) {
204 /*******************************************************************************
206 * FUNCTION: Acpi_ns_load_table
208 * PARAMETERS: *Pcode_addr - Address of pcode block
209 * Pcode_length - Length of pcode block
213 * DESCRIPTION: Load one ACPI table into the namespace
215 ******************************************************************************/
219 ACPI_TABLE_DESC
*table_desc
,
220 ACPI_NAMESPACE_NODE
*node
)
225 if (!table_desc
->aml_pointer
) {
226 return (AE_BAD_PARAMETER
);
230 if (!table_desc
->aml_length
) {
231 return (AE_BAD_PARAMETER
);
236 * Parse the table and load the namespace with all named
237 * objects found within. Control methods are NOT parsed
238 * at this time. In fact, the control methods cannot be
239 * parsed until the entire namespace is loaded, because
240 * if a control method makes a forward reference (call)
241 * to another control method, we can't continue parsing
242 * because we don't know how many arguments to parse next!
245 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
246 status
= acpi_ns_parse_table (table_desc
, node
->child
);
247 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
249 if (ACPI_FAILURE (status
)) {
254 * Now we can parse the control methods. We always parse
255 * them here for a sanity check, and if configured for
256 * just-in-time parsing, we delete the control method
260 status
= acpi_ds_initialize_objects (table_desc
, node
);
266 /*******************************************************************************
268 * FUNCTION: Acpi_ns_load_table_by_type
270 * PARAMETERS: Table_type - Id of the table type to load
274 * DESCRIPTION: Load an ACPI table or tables into the namespace. All tables
275 * of the given type are loaded. The mechanism allows this
276 * routine to be called repeatedly.
278 ******************************************************************************/
281 acpi_ns_load_table_by_type (
282 ACPI_TABLE_TYPE table_type
)
285 ACPI_STATUS status
= AE_OK
;
286 ACPI_TABLE_HEADER
*table_ptr
;
287 ACPI_TABLE_DESC
*table_desc
;
290 acpi_cm_acquire_mutex (ACPI_MTX_TABLES
);
294 * Table types supported are:
295 * DSDT (one), SSDT/PSDT (multiple)
298 switch (table_type
) {
300 case ACPI_TABLE_DSDT
:
302 table_desc
= &acpi_gbl_acpi_tables
[ACPI_TABLE_DSDT
];
304 /* If table already loaded into namespace, just return */
306 if (table_desc
->loaded_into_namespace
) {
307 goto unlock_and_exit
;
310 table_desc
->table_id
= TABLE_ID_DSDT
;
312 /* Now load the single DSDT */
314 status
= acpi_ns_load_table (table_desc
, acpi_gbl_root_node
);
315 if (ACPI_SUCCESS (status
)) {
316 table_desc
->loaded_into_namespace
= TRUE
;
322 case ACPI_TABLE_SSDT
:
325 * Traverse list of SSDT tables
328 table_desc
= &acpi_gbl_acpi_tables
[ACPI_TABLE_SSDT
];
329 for (i
= 0; i
< acpi_gbl_acpi_tables
[ACPI_TABLE_SSDT
].count
; i
++) {
330 table_ptr
= table_desc
->pointer
;
333 * Only attempt to load table if it is not
337 if (!table_desc
->loaded_into_namespace
) {
338 status
= acpi_ns_load_table (table_desc
, acpi_gbl_root_node
);
339 if (ACPI_FAILURE (status
)) {
343 table_desc
->loaded_into_namespace
= TRUE
;
346 table_desc
= table_desc
->next
;
351 case ACPI_TABLE_PSDT
:
354 * Traverse list of PSDT tables
357 table_desc
= &acpi_gbl_acpi_tables
[ACPI_TABLE_PSDT
];
359 for (i
= 0; i
< acpi_gbl_acpi_tables
[ACPI_TABLE_PSDT
].count
; i
++) {
360 table_ptr
= table_desc
->pointer
;
362 /* Only attempt to load table if it is not already loaded! */
364 if (!table_desc
->loaded_into_namespace
) {
365 status
= acpi_ns_load_table (table_desc
, acpi_gbl_root_node
);
366 if (ACPI_FAILURE (status
)) {
370 table_desc
->loaded_into_namespace
= TRUE
;
373 table_desc
= table_desc
->next
;
387 acpi_cm_release_mutex (ACPI_MTX_TABLES
);
394 /*******************************************************************************
396 * FUNCTION: Acpi_ns_delete_subtree
398 * PARAMETERS: Start_handle - Handle in namespace where search begins
402 * DESCRIPTION: Walks the namespace starting at the given handle and deletes
403 * all objects, entries, and scopes in the entire subtree.
405 * TBD: [Investigate] What if any part of this subtree is in use?
406 * (i.e. on one of the object stacks?)
408 ******************************************************************************/
411 acpi_ns_delete_subtree (
412 ACPI_HANDLE start_handle
)
415 ACPI_HANDLE child_handle
;
416 ACPI_HANDLE parent_handle
;
417 ACPI_HANDLE next_child_handle
;
422 parent_handle
= start_handle
;
427 * Traverse the tree of objects until we bubble back up
428 * to where we started.
432 /* Attempt to get the next object in this scope */
434 status
= acpi_get_next_object (ACPI_TYPE_ANY
, parent_handle
,
435 child_handle
, &next_child_handle
);
437 child_handle
= next_child_handle
;
440 /* Did we get a new object? */
442 if (ACPI_SUCCESS (status
)) {
443 /* Check if this object has any children */
445 if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY
, child_handle
,
448 * There is at least one child of this object,
453 parent_handle
= child_handle
;
460 * No more children in this object, go back up to
461 * the object's parent
465 /* Delete all children now */
467 acpi_ns_delete_children (child_handle
);
469 child_handle
= parent_handle
;
470 acpi_get_parent (parent_handle
, &parent_handle
);
474 /* Now delete the starting object, and we are done */
476 acpi_ns_delete_node (child_handle
);
482 /*******************************************************************************
484 * FUNCTION: Acpi_ns_unload_name_space
486 * PARAMETERS: Handle - Root of namespace subtree to be deleted
490 * DESCRIPTION: Shrinks the namespace, typically in response to an undocking
491 * event. Deletes an entire subtree starting from (and
492 * including) the given handle.
494 ******************************************************************************/
497 acpi_ns_unload_namespace (
503 /* Parameter validation */
505 if (!acpi_gbl_root_node
) {
506 return (AE_NO_NAMESPACE
);
510 return (AE_BAD_PARAMETER
);
514 /* This function does the real work */
516 status
= acpi_ns_delete_subtree (handle
);