195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown *
495b482a8SLen Brown * Module Name: nsload - namespace loading/expanding/contracting procedures
595b482a8SLen Brown *
6*612c2932SBob Moore * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown *
895857638SErik Schmauss *****************************************************************************/
995b482a8SLen Brown
1095b482a8SLen Brown #include <acpi/acpi.h>
11e2f7a777SLen Brown #include "accommon.h"
12e2f7a777SLen Brown #include "acnamesp.h"
13e2f7a777SLen Brown #include "acdispat.h"
14e2f7a777SLen Brown #include "actables.h"
1574f51b80SLv Zheng #include "acinterp.h"
1695b482a8SLen Brown
1795b482a8SLen Brown #define _COMPONENT ACPI_NAMESPACE
1895b482a8SLen Brown ACPI_MODULE_NAME("nsload")
1995b482a8SLen Brown
2095b482a8SLen Brown /* Local prototypes */
2195b482a8SLen Brown #ifdef ACPI_FUTURE_IMPLEMENTATION
2295b482a8SLen Brown acpi_status acpi_ns_unload_namespace(acpi_handle handle);
2395b482a8SLen Brown
2495b482a8SLen Brown static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle);
2595b482a8SLen Brown #endif
2695b482a8SLen Brown
2795b482a8SLen Brown /*******************************************************************************
2895b482a8SLen Brown *
2995b482a8SLen Brown * FUNCTION: acpi_ns_load_table
3095b482a8SLen Brown *
3195b482a8SLen Brown * PARAMETERS: table_index - Index for table to be loaded
32ba494beeSBob Moore * node - Owning NS node
3395b482a8SLen Brown *
3495b482a8SLen Brown * RETURN: Status
3595b482a8SLen Brown *
3695b482a8SLen Brown * DESCRIPTION: Load one ACPI table into the namespace
3795b482a8SLen Brown *
3895b482a8SLen Brown ******************************************************************************/
3995b482a8SLen Brown
4095b482a8SLen Brown acpi_status
acpi_ns_load_table(u32 table_index,struct acpi_namespace_node * node)4195b482a8SLen Brown acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
4295b482a8SLen Brown {
4395b482a8SLen Brown acpi_status status;
4495b482a8SLen Brown
4595b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_load_table);
4695b482a8SLen Brown
4795b482a8SLen Brown /* If table already loaded into namespace, just return */
4895b482a8SLen Brown
4995b482a8SLen Brown if (acpi_tb_is_table_loaded(table_index)) {
5095b482a8SLen Brown status = AE_ALREADY_EXISTS;
5195b482a8SLen Brown goto unlock;
5295b482a8SLen Brown }
5395b482a8SLen Brown
5495b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO,
5595b482a8SLen Brown "**** Loading table into namespace ****\n"));
5695b482a8SLen Brown
5795b482a8SLen Brown status = acpi_tb_allocate_owner_id(table_index);
5895b482a8SLen Brown if (ACPI_FAILURE(status)) {
5995b482a8SLen Brown goto unlock;
6095b482a8SLen Brown }
6195b482a8SLen Brown
6274f51b80SLv Zheng /*
6374f51b80SLv Zheng * Parse the table and load the namespace with all named
6474f51b80SLv Zheng * objects found within. Control methods are NOT parsed
6574f51b80SLv Zheng * at this time. In fact, the control methods cannot be
6674f51b80SLv Zheng * parsed until the entire namespace is loaded, because
6774f51b80SLv Zheng * if a control method makes a forward reference (call)
6874f51b80SLv Zheng * to another control method, we can't continue parsing
6974f51b80SLv Zheng * because we don't know how many arguments to parse next!
7074f51b80SLv Zheng */
7195b482a8SLen Brown status = acpi_ns_parse_table(table_index, node);
7295b482a8SLen Brown if (ACPI_SUCCESS(status)) {
7395b482a8SLen Brown acpi_tb_set_table_loaded_flag(table_index, TRUE);
7495b482a8SLen Brown } else {
754712f71bSBob Moore /*
764712f71bSBob Moore * On error, delete any namespace objects created by this table.
774712f71bSBob Moore * We cannot initialize these objects, so delete them. There are
78c163f90cSErik Schmauss * a couple of especially bad cases:
794712f71bSBob Moore * AE_ALREADY_EXISTS - namespace collision.
804712f71bSBob Moore * AE_NOT_FOUND - the target of a Scope operator does not
814712f71bSBob Moore * exist. This target of Scope must already exist in the
824712f71bSBob Moore * namespace, as per the ACPI specification.
834712f71bSBob Moore */
844712f71bSBob Moore acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list.
854712f71bSBob Moore tables[table_index].owner_id);
864712f71bSBob Moore
8780b28810SLv Zheng acpi_tb_release_owner_id(table_index);
884712f71bSBob Moore return_ACPI_STATUS(status);
8995b482a8SLen Brown }
9095b482a8SLen Brown
9195b482a8SLen Brown unlock:
9295b482a8SLen Brown if (ACPI_FAILURE(status)) {
9395b482a8SLen Brown return_ACPI_STATUS(status);
9495b482a8SLen Brown }
9595b482a8SLen Brown
9695b482a8SLen Brown /*
9795b482a8SLen Brown * Now we can parse the control methods. We always parse
9895b482a8SLen Brown * them here for a sanity check, and if configured for
9995b482a8SLen Brown * just-in-time parsing, we delete the control method
10095b482a8SLen Brown * parse trees.
10195b482a8SLen Brown */
10295b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO,
10322b5afceSBob Moore "**** Begin Table Object Initialization\n"));
10495b482a8SLen Brown
1058633db6bSLv Zheng acpi_ex_enter_interpreter();
10695b482a8SLen Brown status = acpi_ds_initialize_objects(table_index, node);
1078633db6bSLv Zheng acpi_ex_exit_interpreter();
10895b482a8SLen Brown
10995b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO,
11022b5afceSBob Moore "**** Completed Table Object Initialization\n"));
11195b482a8SLen Brown
11295b482a8SLen Brown return_ACPI_STATUS(status);
11395b482a8SLen Brown }
11495b482a8SLen Brown
11595b482a8SLen Brown #ifdef ACPI_OBSOLETE_FUNCTIONS
11695b482a8SLen Brown /*******************************************************************************
11795b482a8SLen Brown *
11895b482a8SLen Brown * FUNCTION: acpi_load_namespace
11995b482a8SLen Brown *
12095b482a8SLen Brown * PARAMETERS: None
12195b482a8SLen Brown *
12295b482a8SLen Brown * RETURN: Status
12395b482a8SLen Brown *
12495b482a8SLen Brown * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
12595b482a8SLen Brown * (DSDT points to either the BIOS or a buffer.)
12695b482a8SLen Brown *
12795b482a8SLen Brown ******************************************************************************/
12895b482a8SLen Brown
acpi_ns_load_namespace(void)12995b482a8SLen Brown acpi_status acpi_ns_load_namespace(void)
13095b482a8SLen Brown {
13195b482a8SLen Brown acpi_status status;
13295b482a8SLen Brown
13395b482a8SLen Brown ACPI_FUNCTION_TRACE(acpi_load_name_space);
13495b482a8SLen Brown
13595b482a8SLen Brown /* There must be at least a DSDT installed */
13695b482a8SLen Brown
13795b482a8SLen Brown if (acpi_gbl_DSDT == NULL) {
13895b482a8SLen Brown ACPI_ERROR((AE_INFO, "DSDT is not in memory"));
13995b482a8SLen Brown return_ACPI_STATUS(AE_NO_ACPI_TABLES);
14095b482a8SLen Brown }
14195b482a8SLen Brown
14295b482a8SLen Brown /*
14395b482a8SLen Brown * Load the namespace. The DSDT is required,
14495b482a8SLen Brown * but the SSDT and PSDT tables are optional.
14595b482a8SLen Brown */
14695b482a8SLen Brown status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT);
14795b482a8SLen Brown if (ACPI_FAILURE(status)) {
14895b482a8SLen Brown return_ACPI_STATUS(status);
14995b482a8SLen Brown }
15095b482a8SLen Brown
15195b482a8SLen Brown /* Ignore exceptions from these */
15295b482a8SLen Brown
15395b482a8SLen Brown (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT);
15495b482a8SLen Brown (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT);
15595b482a8SLen Brown
15695b482a8SLen Brown ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
15795b482a8SLen Brown "ACPI Namespace successfully loaded at root %p\n",
15895b482a8SLen Brown acpi_gbl_root_node));
15995b482a8SLen Brown
16095b482a8SLen Brown return_ACPI_STATUS(status);
16195b482a8SLen Brown }
16295b482a8SLen Brown #endif
16395b482a8SLen Brown
16495b482a8SLen Brown #ifdef ACPI_FUTURE_IMPLEMENTATION
16595b482a8SLen Brown /*******************************************************************************
16695b482a8SLen Brown *
16795b482a8SLen Brown * FUNCTION: acpi_ns_delete_subtree
16895b482a8SLen Brown *
16995b482a8SLen Brown * PARAMETERS: start_handle - Handle in namespace where search begins
17095b482a8SLen Brown *
17195b482a8SLen Brown * RETURNS Status
17295b482a8SLen Brown *
17395b482a8SLen Brown * DESCRIPTION: Walks the namespace starting at the given handle and deletes
17495b482a8SLen Brown * all objects, entries, and scopes in the entire subtree.
17595b482a8SLen Brown *
17695b482a8SLen Brown * Namespace/Interpreter should be locked or the subsystem should
17795b482a8SLen Brown * be in shutdown before this routine is called.
17895b482a8SLen Brown *
17995b482a8SLen Brown ******************************************************************************/
18095b482a8SLen Brown
acpi_ns_delete_subtree(acpi_handle start_handle)18195b482a8SLen Brown static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
18295b482a8SLen Brown {
18395b482a8SLen Brown acpi_status status;
18495b482a8SLen Brown acpi_handle child_handle;
18595b482a8SLen Brown acpi_handle parent_handle;
18695b482a8SLen Brown acpi_handle next_child_handle;
18795b482a8SLen Brown acpi_handle dummy;
18895b482a8SLen Brown u32 level;
18995b482a8SLen Brown
19095b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_delete_subtree);
19195b482a8SLen Brown
19295b482a8SLen Brown parent_handle = start_handle;
19395b482a8SLen Brown child_handle = NULL;
19495b482a8SLen Brown level = 1;
19595b482a8SLen Brown
19695b482a8SLen Brown /*
19795b482a8SLen Brown * Traverse the tree of objects until we bubble back up
19895b482a8SLen Brown * to where we started.
19995b482a8SLen Brown */
20095b482a8SLen Brown while (level > 0) {
20195b482a8SLen Brown
20295b482a8SLen Brown /* Attempt to get the next object in this scope */
20395b482a8SLen Brown
20495b482a8SLen Brown status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle,
20595b482a8SLen Brown child_handle, &next_child_handle);
20695b482a8SLen Brown
20795b482a8SLen Brown child_handle = next_child_handle;
20895b482a8SLen Brown
20995b482a8SLen Brown /* Did we get a new object? */
21095b482a8SLen Brown
21195b482a8SLen Brown if (ACPI_SUCCESS(status)) {
21295b482a8SLen Brown
21395b482a8SLen Brown /* Check if this object has any children */
21495b482a8SLen Brown
21595b482a8SLen Brown if (ACPI_SUCCESS
21695b482a8SLen Brown (acpi_get_next_object
21795b482a8SLen Brown (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) {
21895b482a8SLen Brown /*
21995b482a8SLen Brown * There is at least one child of this object,
22095b482a8SLen Brown * visit the object
22195b482a8SLen Brown */
22295b482a8SLen Brown level++;
22395b482a8SLen Brown parent_handle = child_handle;
22495b482a8SLen Brown child_handle = NULL;
22595b482a8SLen Brown }
22695b482a8SLen Brown } else {
22795b482a8SLen Brown /*
22895b482a8SLen Brown * No more children in this object, go back up to
22995b482a8SLen Brown * the object's parent
23095b482a8SLen Brown */
23195b482a8SLen Brown level--;
23295b482a8SLen Brown
23395b482a8SLen Brown /* Delete all children now */
23495b482a8SLen Brown
23595b482a8SLen Brown acpi_ns_delete_children(child_handle);
23695b482a8SLen Brown
23795b482a8SLen Brown child_handle = parent_handle;
23895b482a8SLen Brown status = acpi_get_parent(parent_handle, &parent_handle);
23995b482a8SLen Brown if (ACPI_FAILURE(status)) {
24095b482a8SLen Brown return_ACPI_STATUS(status);
24195b482a8SLen Brown }
24295b482a8SLen Brown }
24395b482a8SLen Brown }
24495b482a8SLen Brown
24595b482a8SLen Brown /* Now delete the starting object, and we are done */
24695b482a8SLen Brown
2478e4319c4SBob Moore acpi_ns_remove_node(child_handle);
24895b482a8SLen Brown return_ACPI_STATUS(AE_OK);
24995b482a8SLen Brown }
25095b482a8SLen Brown
25195b482a8SLen Brown /*******************************************************************************
25295b482a8SLen Brown *
25395b482a8SLen Brown * FUNCTION: acpi_ns_unload_name_space
25495b482a8SLen Brown *
255ba494beeSBob Moore * PARAMETERS: handle - Root of namespace subtree to be deleted
25695b482a8SLen Brown *
25795b482a8SLen Brown * RETURN: Status
25895b482a8SLen Brown *
25995b482a8SLen Brown * DESCRIPTION: Shrinks the namespace, typically in response to an undocking
26095b482a8SLen Brown * event. Deletes an entire subtree starting from (and
26195b482a8SLen Brown * including) the given handle.
26295b482a8SLen Brown *
26395b482a8SLen Brown ******************************************************************************/
26495b482a8SLen Brown
acpi_ns_unload_namespace(acpi_handle handle)26595b482a8SLen Brown acpi_status acpi_ns_unload_namespace(acpi_handle handle)
26695b482a8SLen Brown {
26795b482a8SLen Brown acpi_status status;
26895b482a8SLen Brown
26995b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_unload_name_space);
27095b482a8SLen Brown
27195b482a8SLen Brown /* Parameter validation */
27295b482a8SLen Brown
27395b482a8SLen Brown if (!acpi_gbl_root_node) {
27495b482a8SLen Brown return_ACPI_STATUS(AE_NO_NAMESPACE);
27595b482a8SLen Brown }
27695b482a8SLen Brown
27795b482a8SLen Brown if (!handle) {
27895b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER);
27995b482a8SLen Brown }
28095b482a8SLen Brown
28195b482a8SLen Brown /* This function does the real work */
28295b482a8SLen Brown
28395b482a8SLen Brown status = acpi_ns_delete_subtree(handle);
28495b482a8SLen Brown return_ACPI_STATUS(status);
28595b482a8SLen Brown }
28695b482a8SLen Brown #endif
287