1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: nsload - namespace loading/expanding/contracting procedures 5 * 6 * Copyright (C) 2000 - 2019, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 #include <acpi/acpi.h> 11 #include "accommon.h" 12 #include "acnamesp.h" 13 #include "acdispat.h" 14 #include "actables.h" 15 #include "acinterp.h" 16 17 #define _COMPONENT ACPI_NAMESPACE 18 ACPI_MODULE_NAME("nsload") 19 20 /* Local prototypes */ 21 #ifdef ACPI_FUTURE_IMPLEMENTATION 22 acpi_status acpi_ns_unload_namespace(acpi_handle handle); 23 24 static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle); 25 #endif 26 27 /******************************************************************************* 28 * 29 * FUNCTION: acpi_ns_load_table 30 * 31 * PARAMETERS: table_index - Index for table to be loaded 32 * node - Owning NS node 33 * 34 * RETURN: Status 35 * 36 * DESCRIPTION: Load one ACPI table into the namespace 37 * 38 ******************************************************************************/ 39 40 acpi_status 41 acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) 42 { 43 acpi_status status; 44 45 ACPI_FUNCTION_TRACE(ns_load_table); 46 47 /* If table already loaded into namespace, just return */ 48 49 if (acpi_tb_is_table_loaded(table_index)) { 50 status = AE_ALREADY_EXISTS; 51 goto unlock; 52 } 53 54 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 55 "**** Loading table into namespace ****\n")); 56 57 status = acpi_tb_allocate_owner_id(table_index); 58 if (ACPI_FAILURE(status)) { 59 goto unlock; 60 } 61 62 /* 63 * Parse the table and load the namespace with all named 64 * objects found within. Control methods are NOT parsed 65 * at this time. In fact, the control methods cannot be 66 * parsed until the entire namespace is loaded, because 67 * if a control method makes a forward reference (call) 68 * to another control method, we can't continue parsing 69 * because we don't know how many arguments to parse next! 70 */ 71 status = acpi_ns_parse_table(table_index, node); 72 if (ACPI_SUCCESS(status)) { 73 acpi_tb_set_table_loaded_flag(table_index, TRUE); 74 } else { 75 /* 76 * On error, delete any namespace objects created by this table. 77 * We cannot initialize these objects, so delete them. There are 78 * a couple of especially bad cases: 79 * AE_ALREADY_EXISTS - namespace collision. 80 * AE_NOT_FOUND - the target of a Scope operator does not 81 * exist. This target of Scope must already exist in the 82 * namespace, as per the ACPI specification. 83 */ 84 acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list. 85 tables[table_index].owner_id); 86 87 acpi_tb_release_owner_id(table_index); 88 return_ACPI_STATUS(status); 89 } 90 91 unlock: 92 if (ACPI_FAILURE(status)) { 93 return_ACPI_STATUS(status); 94 } 95 96 /* 97 * Now we can parse the control methods. We always parse 98 * them here for a sanity check, and if configured for 99 * just-in-time parsing, we delete the control method 100 * parse trees. 101 */ 102 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 103 "**** Begin Table Object Initialization\n")); 104 105 acpi_ex_enter_interpreter(); 106 status = acpi_ds_initialize_objects(table_index, node); 107 acpi_ex_exit_interpreter(); 108 109 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 110 "**** Completed Table Object Initialization\n")); 111 112 /* 113 * This case handles the legacy option that groups all module-level 114 * code blocks together and defers execution until all of the tables 115 * are loaded. Execute all of these blocks at this time. 116 * Execute any module-level code that was detected during the table 117 * load phase. 118 * 119 * Note: this option is deprecated and will be eliminated in the 120 * future. Use of this option can cause problems with AML code that 121 * depends upon in-order immediate execution of module-level code. 122 */ 123 acpi_ns_exec_module_code_list(); 124 return_ACPI_STATUS(status); 125 } 126 127 #ifdef ACPI_OBSOLETE_FUNCTIONS 128 /******************************************************************************* 129 * 130 * FUNCTION: acpi_load_namespace 131 * 132 * PARAMETERS: None 133 * 134 * RETURN: Status 135 * 136 * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. 137 * (DSDT points to either the BIOS or a buffer.) 138 * 139 ******************************************************************************/ 140 141 acpi_status acpi_ns_load_namespace(void) 142 { 143 acpi_status status; 144 145 ACPI_FUNCTION_TRACE(acpi_load_name_space); 146 147 /* There must be at least a DSDT installed */ 148 149 if (acpi_gbl_DSDT == NULL) { 150 ACPI_ERROR((AE_INFO, "DSDT is not in memory")); 151 return_ACPI_STATUS(AE_NO_ACPI_TABLES); 152 } 153 154 /* 155 * Load the namespace. The DSDT is required, 156 * but the SSDT and PSDT tables are optional. 157 */ 158 status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT); 159 if (ACPI_FAILURE(status)) { 160 return_ACPI_STATUS(status); 161 } 162 163 /* Ignore exceptions from these */ 164 165 (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT); 166 (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT); 167 168 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, 169 "ACPI Namespace successfully loaded at root %p\n", 170 acpi_gbl_root_node)); 171 172 return_ACPI_STATUS(status); 173 } 174 #endif 175 176 #ifdef ACPI_FUTURE_IMPLEMENTATION 177 /******************************************************************************* 178 * 179 * FUNCTION: acpi_ns_delete_subtree 180 * 181 * PARAMETERS: start_handle - Handle in namespace where search begins 182 * 183 * RETURNS Status 184 * 185 * DESCRIPTION: Walks the namespace starting at the given handle and deletes 186 * all objects, entries, and scopes in the entire subtree. 187 * 188 * Namespace/Interpreter should be locked or the subsystem should 189 * be in shutdown before this routine is called. 190 * 191 ******************************************************************************/ 192 193 static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) 194 { 195 acpi_status status; 196 acpi_handle child_handle; 197 acpi_handle parent_handle; 198 acpi_handle next_child_handle; 199 acpi_handle dummy; 200 u32 level; 201 202 ACPI_FUNCTION_TRACE(ns_delete_subtree); 203 204 parent_handle = start_handle; 205 child_handle = NULL; 206 level = 1; 207 208 /* 209 * Traverse the tree of objects until we bubble back up 210 * to where we started. 211 */ 212 while (level > 0) { 213 214 /* Attempt to get the next object in this scope */ 215 216 status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, 217 child_handle, &next_child_handle); 218 219 child_handle = next_child_handle; 220 221 /* Did we get a new object? */ 222 223 if (ACPI_SUCCESS(status)) { 224 225 /* Check if this object has any children */ 226 227 if (ACPI_SUCCESS 228 (acpi_get_next_object 229 (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) { 230 /* 231 * There is at least one child of this object, 232 * visit the object 233 */ 234 level++; 235 parent_handle = child_handle; 236 child_handle = NULL; 237 } 238 } else { 239 /* 240 * No more children in this object, go back up to 241 * the object's parent 242 */ 243 level--; 244 245 /* Delete all children now */ 246 247 acpi_ns_delete_children(child_handle); 248 249 child_handle = parent_handle; 250 status = acpi_get_parent(parent_handle, &parent_handle); 251 if (ACPI_FAILURE(status)) { 252 return_ACPI_STATUS(status); 253 } 254 } 255 } 256 257 /* Now delete the starting object, and we are done */ 258 259 acpi_ns_remove_node(child_handle); 260 return_ACPI_STATUS(AE_OK); 261 } 262 263 /******************************************************************************* 264 * 265 * FUNCTION: acpi_ns_unload_name_space 266 * 267 * PARAMETERS: handle - Root of namespace subtree to be deleted 268 * 269 * RETURN: Status 270 * 271 * DESCRIPTION: Shrinks the namespace, typically in response to an undocking 272 * event. Deletes an entire subtree starting from (and 273 * including) the given handle. 274 * 275 ******************************************************************************/ 276 277 acpi_status acpi_ns_unload_namespace(acpi_handle handle) 278 { 279 acpi_status status; 280 281 ACPI_FUNCTION_TRACE(ns_unload_name_space); 282 283 /* Parameter validation */ 284 285 if (!acpi_gbl_root_node) { 286 return_ACPI_STATUS(AE_NO_NAMESPACE); 287 } 288 289 if (!handle) { 290 return_ACPI_STATUS(AE_BAD_PARAMETER); 291 } 292 293 /* This function does the real work */ 294 295 status = acpi_ns_delete_subtree(handle); 296 return_ACPI_STATUS(status); 297 } 298 #endif 299