Branch data Line data Source code
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 - 2020, 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 : 30 : acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) 42 : : { 43 : 30 : acpi_status status; 44 : : 45 : 30 : ACPI_FUNCTION_TRACE(ns_load_table); 46 : : 47 : : /* If table already loaded into namespace, just return */ 48 : : 49 [ - + ]: 30 : if (acpi_tb_is_table_loaded(table_index)) { 50 : 0 : status = AE_ALREADY_EXISTS; 51 : 0 : goto unlock; 52 : : } 53 : : 54 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, 55 : 30 : "**** Loading table into namespace ****\n")); 56 : : 57 : 30 : status = acpi_tb_allocate_owner_id(table_index); 58 [ - + ]: 30 : if (ACPI_FAILURE(status)) { 59 : 0 : 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 : 30 : status = acpi_ns_parse_table(table_index, node); 72 [ + - ]: 30 : if (ACPI_SUCCESS(status)) { 73 : 30 : 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 : 0 : acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list. 85 : 0 : tables[table_index].owner_id); 86 : : 87 : 0 : acpi_tb_release_owner_id(table_index); 88 : 0 : return_ACPI_STATUS(status); 89 : : } 90 : : 91 : 30 : unlock: 92 [ - + ]: 30 : if (ACPI_FAILURE(status)) { 93 : 0 : 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 : 30 : "**** Begin Table Object Initialization\n")); 104 : : 105 : 30 : acpi_ex_enter_interpreter(); 106 : 30 : status = acpi_ds_initialize_objects(table_index, node); 107 : 30 : acpi_ex_exit_interpreter(); 108 : : 109 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, 110 : 30 : "**** Completed Table Object Initialization\n")); 111 : : 112 : 30 : return_ACPI_STATUS(status); 113 : : } 114 : : 115 : : #ifdef ACPI_OBSOLETE_FUNCTIONS 116 : : /******************************************************************************* 117 : : * 118 : : * FUNCTION: acpi_load_namespace 119 : : * 120 : : * PARAMETERS: None 121 : : * 122 : : * RETURN: Status 123 : : * 124 : : * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. 125 : : * (DSDT points to either the BIOS or a buffer.) 126 : : * 127 : : ******************************************************************************/ 128 : : 129 : : acpi_status acpi_ns_load_namespace(void) 130 : : { 131 : : acpi_status status; 132 : : 133 : : ACPI_FUNCTION_TRACE(acpi_load_name_space); 134 : : 135 : : /* There must be at least a DSDT installed */ 136 : : 137 : : if (acpi_gbl_DSDT == NULL) { 138 : : ACPI_ERROR((AE_INFO, "DSDT is not in memory")); 139 : : return_ACPI_STATUS(AE_NO_ACPI_TABLES); 140 : : } 141 : : 142 : : /* 143 : : * Load the namespace. The DSDT is required, 144 : : * but the SSDT and PSDT tables are optional. 145 : : */ 146 : : status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT); 147 : : if (ACPI_FAILURE(status)) { 148 : : return_ACPI_STATUS(status); 149 : : } 150 : : 151 : : /* Ignore exceptions from these */ 152 : : 153 : : (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT); 154 : : (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT); 155 : : 156 : : ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, 157 : : "ACPI Namespace successfully loaded at root %p\n", 158 : : acpi_gbl_root_node)); 159 : : 160 : : return_ACPI_STATUS(status); 161 : : } 162 : : #endif 163 : : 164 : : #ifdef ACPI_FUTURE_IMPLEMENTATION 165 : : /******************************************************************************* 166 : : * 167 : : * FUNCTION: acpi_ns_delete_subtree 168 : : * 169 : : * PARAMETERS: start_handle - Handle in namespace where search begins 170 : : * 171 : : * RETURNS Status 172 : : * 173 : : * DESCRIPTION: Walks the namespace starting at the given handle and deletes 174 : : * all objects, entries, and scopes in the entire subtree. 175 : : * 176 : : * Namespace/Interpreter should be locked or the subsystem should 177 : : * be in shutdown before this routine is called. 178 : : * 179 : : ******************************************************************************/ 180 : : 181 : : static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) 182 : : { 183 : : acpi_status status; 184 : : acpi_handle child_handle; 185 : : acpi_handle parent_handle; 186 : : acpi_handle next_child_handle; 187 : : acpi_handle dummy; 188 : : u32 level; 189 : : 190 : : ACPI_FUNCTION_TRACE(ns_delete_subtree); 191 : : 192 : : parent_handle = start_handle; 193 : : child_handle = NULL; 194 : : level = 1; 195 : : 196 : : /* 197 : : * Traverse the tree of objects until we bubble back up 198 : : * to where we started. 199 : : */ 200 : : while (level > 0) { 201 : : 202 : : /* Attempt to get the next object in this scope */ 203 : : 204 : : status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, 205 : : child_handle, &next_child_handle); 206 : : 207 : : child_handle = next_child_handle; 208 : : 209 : : /* Did we get a new object? */ 210 : : 211 : : if (ACPI_SUCCESS(status)) { 212 : : 213 : : /* Check if this object has any children */ 214 : : 215 : : if (ACPI_SUCCESS 216 : : (acpi_get_next_object 217 : : (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) { 218 : : /* 219 : : * There is at least one child of this object, 220 : : * visit the object 221 : : */ 222 : : level++; 223 : : parent_handle = child_handle; 224 : : child_handle = NULL; 225 : : } 226 : : } else { 227 : : /* 228 : : * No more children in this object, go back up to 229 : : * the object's parent 230 : : */ 231 : : level--; 232 : : 233 : : /* Delete all children now */ 234 : : 235 : : acpi_ns_delete_children(child_handle); 236 : : 237 : : child_handle = parent_handle; 238 : : status = acpi_get_parent(parent_handle, &parent_handle); 239 : : if (ACPI_FAILURE(status)) { 240 : : return_ACPI_STATUS(status); 241 : : } 242 : : } 243 : : } 244 : : 245 : : /* Now delete the starting object, and we are done */ 246 : : 247 : : acpi_ns_remove_node(child_handle); 248 : : return_ACPI_STATUS(AE_OK); 249 : : } 250 : : 251 : : /******************************************************************************* 252 : : * 253 : : * FUNCTION: acpi_ns_unload_name_space 254 : : * 255 : : * PARAMETERS: handle - Root of namespace subtree to be deleted 256 : : * 257 : : * RETURN: Status 258 : : * 259 : : * DESCRIPTION: Shrinks the namespace, typically in response to an undocking 260 : : * event. Deletes an entire subtree starting from (and 261 : : * including) the given handle. 262 : : * 263 : : ******************************************************************************/ 264 : : 265 : : acpi_status acpi_ns_unload_namespace(acpi_handle handle) 266 : : { 267 : : acpi_status status; 268 : : 269 : : ACPI_FUNCTION_TRACE(ns_unload_name_space); 270 : : 271 : : /* Parameter validation */ 272 : : 273 : : if (!acpi_gbl_root_node) { 274 : : return_ACPI_STATUS(AE_NO_NAMESPACE); 275 : : } 276 : : 277 : : if (!handle) { 278 : : return_ACPI_STATUS(AE_BAD_PARAMETER); 279 : : } 280 : : 281 : : /* This function does the real work */ 282 : : 283 : : status = acpi_ns_delete_subtree(handle); 284 : : return_ACPI_STATUS(status); 285 : : } 286 : : #endif