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
36 #define _COMPONENT ACPI_NAMESPACE
37 MODULE_NAME ("nsload")
40 /*******************************************************************************
42 * FUNCTION: Acpi_load_namespace
44 * PARAMETERS: Display_aml_during_load
48 * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
49 * (DSDT points to either the BIOS or a buffer.)
51 ******************************************************************************/
54 acpi_ns_load_namespace (
60 /* There must be at least a DSDT installed */
62 if (acpi_gbl_DSDT
== NULL
) {
63 return (AE_NO_ACPI_TABLES
);
68 * Load the namespace. The DSDT is required,
69 * but the SSDT and PSDT tables are optional.
72 status
= acpi_ns_load_table_by_type (ACPI_TABLE_DSDT
);
73 if (ACPI_FAILURE (status
)) {
77 /* Ignore exceptions from these */
79 acpi_ns_load_table_by_type (ACPI_TABLE_SSDT
);
80 acpi_ns_load_table_by_type (ACPI_TABLE_PSDT
);
87 /*******************************************************************************
89 * FUNCTION: Acpi_ns_one_parse_pass
97 ******************************************************************************/
100 acpi_ns_one_complete_parse (
102 ACPI_TABLE_DESC
*table_desc
)
104 ACPI_PARSE_DOWNWARDS descending_callback
;
105 ACPI_PARSE_UPWARDS ascending_callback
;
106 ACPI_PARSE_OBJECT
*parse_root
;
110 switch (pass_number
) {
112 descending_callback
= acpi_ds_load1_begin_op
;
113 ascending_callback
= acpi_ds_load1_end_op
;
117 descending_callback
= acpi_ds_load2_begin_op
;
118 ascending_callback
= acpi_ds_load2_end_op
;
122 descending_callback
= acpi_ds_exec_begin_op
;
123 ascending_callback
= acpi_ds_exec_end_op
;
127 return (AE_BAD_PARAMETER
);
130 /* Create and init a Root Node */
132 parse_root
= acpi_ps_alloc_op (AML_SCOPE_OP
);
134 return (AE_NO_MEMORY
);
137 ((ACPI_PARSE2_OBJECT
*) parse_root
)->name
= ACPI_ROOT_NAME
;
140 /* Pass 1: Parse everything except control method bodies */
142 status
= acpi_ps_parse_aml (parse_root
, table_desc
->aml_pointer
,
143 table_desc
->aml_length
,
144 ACPI_PARSE_LOAD_PASS1
| ACPI_PARSE_DELETE_TREE
,
145 NULL
, NULL
, NULL
, descending_callback
,
148 acpi_ps_delete_parse_tree (parse_root
);
154 /*******************************************************************************
156 * FUNCTION: Acpi_ns_parse_table
158 * PARAMETERS: Table_desc - An ACPI table descriptor for table to parse
159 * Start_node - Where to enter the table into the namespace
163 * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
165 ******************************************************************************/
168 acpi_ns_parse_table (
169 ACPI_TABLE_DESC
*table_desc
,
170 ACPI_NAMESPACE_NODE
*start_node
)
178 * In this pass, we load most of the namespace. Control methods
179 * are not parsed until later. A parse tree is not created. Instead,
180 * each Parser Op subtree is deleted when it is finished. This saves
181 * a great deal of memory, and allows a small cache of parse objects
182 * to service the entire parse. The second pass of the parse then
183 * performs another complete parse of the AML..
186 status
= acpi_ns_one_complete_parse (1, table_desc
);
187 if (ACPI_FAILURE (status
)) {
195 * In this pass, we resolve forward references and other things
196 * that could not be completed during the first pass.
197 * Another complete parse of the AML is performed, but the
198 * overhead of this is compensated for by the fact that the
199 * parse objects are all cached.
202 status
= acpi_ns_one_complete_parse (2, table_desc
);
203 if (ACPI_FAILURE (status
)) {
211 /*******************************************************************************
213 * FUNCTION: Acpi_ns_load_table
215 * PARAMETERS: *Pcode_addr - Address of pcode block
216 * Pcode_length - Length of pcode block
220 * DESCRIPTION: Load one ACPI table into the namespace
222 ******************************************************************************/
226 ACPI_TABLE_DESC
*table_desc
,
227 ACPI_NAMESPACE_NODE
*node
)
232 if (!table_desc
->aml_pointer
) {
233 return (AE_BAD_PARAMETER
);
237 if (!table_desc
->aml_length
) {
238 return (AE_BAD_PARAMETER
);
243 * Parse the table and load the namespace with all named
244 * objects found within. Control methods are NOT parsed
245 * at this time. In fact, the control methods cannot be
246 * parsed until the entire namespace is loaded, because
247 * if a control method makes a forward reference (call)
248 * to another control method, we can't continue parsing
249 * because we don't know how many arguments to parse next!
252 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
253 status
= acpi_ns_parse_table (table_desc
, node
->child
);
254 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
256 if (ACPI_FAILURE (status
)) {
261 * Now we can parse the control methods. We always parse
262 * them here for a sanity check, and if configured for
263 * just-in-time parsing, we delete the control method
267 status
= acpi_ds_initialize_objects (table_desc
, node
);
273 /*******************************************************************************
275 * FUNCTION: Acpi_ns_load_table_by_type
277 * PARAMETERS: Table_type - Id of the table type to load
281 * DESCRIPTION: Load an ACPI table or tables into the namespace. All tables
282 * of the given type are loaded. The mechanism allows this
283 * routine to be called repeatedly.
285 ******************************************************************************/
288 acpi_ns_load_table_by_type (
289 ACPI_TABLE_TYPE table_type
)
292 ACPI_STATUS status
= AE_OK
;
293 ACPI_TABLE_HEADER
*table_ptr
;
294 ACPI_TABLE_DESC
*table_desc
;
297 acpi_cm_acquire_mutex (ACPI_MTX_TABLES
);
301 * Table types supported are:
302 * DSDT (one), SSDT/PSDT (multiple)
305 switch (table_type
) {
307 case ACPI_TABLE_DSDT
:
309 table_desc
= &acpi_gbl_acpi_tables
[ACPI_TABLE_DSDT
];
311 /* If table already loaded into namespace, just return */
313 if (table_desc
->loaded_into_namespace
) {
314 goto unlock_and_exit
;
317 table_desc
->table_id
= TABLE_ID_DSDT
;
319 /* Now load the single DSDT */
321 status
= acpi_ns_load_table (table_desc
, acpi_gbl_root_node
);
322 if (ACPI_SUCCESS (status
)) {
323 table_desc
->loaded_into_namespace
= TRUE
;
329 case ACPI_TABLE_SSDT
:
332 * Traverse list of SSDT tables
335 table_desc
= &acpi_gbl_acpi_tables
[ACPI_TABLE_SSDT
];
336 for (i
= 0; i
< acpi_gbl_acpi_tables
[ACPI_TABLE_SSDT
].count
; i
++) {
337 table_ptr
= table_desc
->pointer
;
340 * Only attempt to load table if it is not
344 if (!table_desc
->loaded_into_namespace
) {
345 status
= acpi_ns_load_table (table_desc
, acpi_gbl_root_node
);
346 if (ACPI_FAILURE (status
)) {
350 table_desc
->loaded_into_namespace
= TRUE
;
353 table_desc
= table_desc
->next
;
358 case ACPI_TABLE_PSDT
:
361 * Traverse list of PSDT tables
364 table_desc
= &acpi_gbl_acpi_tables
[ACPI_TABLE_PSDT
];
366 for (i
= 0; i
< acpi_gbl_acpi_tables
[ACPI_TABLE_PSDT
].count
; i
++) {
367 table_ptr
= table_desc
->pointer
;
369 /* Only attempt to load table if it is not already loaded! */
371 if (!table_desc
->loaded_into_namespace
) {
372 status
= acpi_ns_load_table (table_desc
, acpi_gbl_root_node
);
373 if (ACPI_FAILURE (status
)) {
377 table_desc
->loaded_into_namespace
= TRUE
;
380 table_desc
= table_desc
->next
;
394 acpi_cm_release_mutex (ACPI_MTX_TABLES
);
401 /*******************************************************************************
403 * FUNCTION: Acpi_ns_delete_subtree
405 * PARAMETERS: Start_handle - Handle in namespace where search begins
409 * DESCRIPTION: Walks the namespace starting at the given handle and deletes
410 * all objects, entries, and scopes in the entire subtree.
412 * TBD: [Investigate] What if any part of this subtree is in use?
413 * (i.e. on one of the object stacks?)
415 ******************************************************************************/
418 acpi_ns_delete_subtree (
419 ACPI_HANDLE start_handle
)
422 ACPI_HANDLE child_handle
;
423 ACPI_HANDLE parent_handle
;
424 ACPI_HANDLE next_child_handle
;
429 parent_handle
= start_handle
;
434 * Traverse the tree of objects until we bubble back up
435 * to where we started.
439 /* Attempt to get the next object in this scope */
441 status
= acpi_get_next_object (ACPI_TYPE_ANY
, parent_handle
,
442 child_handle
, &next_child_handle
);
444 child_handle
= next_child_handle
;
447 /* Did we get a new object? */
449 if (ACPI_SUCCESS (status
)) {
450 /* Check if this object has any children */
452 if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY
, child_handle
,
455 * There is at least one child of this object,
460 parent_handle
= child_handle
;
467 * No more children in this object, go back up to
468 * the object's parent
472 /* Delete all children now */
474 acpi_ns_delete_children (child_handle
);
476 child_handle
= parent_handle
;
477 acpi_get_parent (parent_handle
, &parent_handle
);
481 /* Now delete the starting object, and we are done */
483 acpi_ns_delete_node (child_handle
);
489 /*******************************************************************************
491 * FUNCTION: Acpi_ns_unload_name_space
493 * PARAMETERS: Handle - Root of namespace subtree to be deleted
497 * DESCRIPTION: Shrinks the namespace, typically in response to an undocking
498 * event. Deletes an entire subtree starting from (and
499 * including) the given handle.
501 ******************************************************************************/
504 acpi_ns_unload_namespace (
510 /* Parameter validation */
512 if (!acpi_gbl_root_node
) {
513 return (AE_NO_NAMESPACE
);
517 return (AE_BAD_PARAMETER
);
521 /* This function does the real work */
523 status
= acpi_ns_delete_subtree (handle
);