Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: nsload - namespace loading/expanding/contracting procedures
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acnamesp.h"
0013 #include "acdispat.h"
0014 #include "actables.h"
0015 #include "acinterp.h"
0016 
0017 #define _COMPONENT          ACPI_NAMESPACE
0018 ACPI_MODULE_NAME("nsload")
0019 
0020 /* Local prototypes */
0021 #ifdef ACPI_FUTURE_IMPLEMENTATION
0022 acpi_status acpi_ns_unload_namespace(acpi_handle handle);
0023 
0024 static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle);
0025 #endif
0026 
0027 /*******************************************************************************
0028  *
0029  * FUNCTION:    acpi_ns_load_table
0030  *
0031  * PARAMETERS:  table_index     - Index for table to be loaded
0032  *              node            - Owning NS node
0033  *
0034  * RETURN:      Status
0035  *
0036  * DESCRIPTION: Load one ACPI table into the namespace
0037  *
0038  ******************************************************************************/
0039 
0040 acpi_status
0041 acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
0042 {
0043     acpi_status status;
0044 
0045     ACPI_FUNCTION_TRACE(ns_load_table);
0046 
0047     /* If table already loaded into namespace, just return */
0048 
0049     if (acpi_tb_is_table_loaded(table_index)) {
0050         status = AE_ALREADY_EXISTS;
0051         goto unlock;
0052     }
0053 
0054     ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0055               "**** Loading table into namespace ****\n"));
0056 
0057     status = acpi_tb_allocate_owner_id(table_index);
0058     if (ACPI_FAILURE(status)) {
0059         goto unlock;
0060     }
0061 
0062     /*
0063      * Parse the table and load the namespace with all named
0064      * objects found within. Control methods are NOT parsed
0065      * at this time. In fact, the control methods cannot be
0066      * parsed until the entire namespace is loaded, because
0067      * if a control method makes a forward reference (call)
0068      * to another control method, we can't continue parsing
0069      * because we don't know how many arguments to parse next!
0070      */
0071     status = acpi_ns_parse_table(table_index, node);
0072     if (ACPI_SUCCESS(status)) {
0073         acpi_tb_set_table_loaded_flag(table_index, TRUE);
0074     } else {
0075         /*
0076          * On error, delete any namespace objects created by this table.
0077          * We cannot initialize these objects, so delete them. There are
0078          * a couple of especially bad cases:
0079          * AE_ALREADY_EXISTS - namespace collision.
0080          * AE_NOT_FOUND - the target of a Scope operator does not
0081          * exist. This target of Scope must already exist in the
0082          * namespace, as per the ACPI specification.
0083          */
0084         acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list.
0085                           tables[table_index].owner_id);
0086 
0087         acpi_tb_release_owner_id(table_index);
0088         return_ACPI_STATUS(status);
0089     }
0090 
0091 unlock:
0092     if (ACPI_FAILURE(status)) {
0093         return_ACPI_STATUS(status);
0094     }
0095 
0096     /*
0097      * Now we can parse the control methods. We always parse
0098      * them here for a sanity check, and if configured for
0099      * just-in-time parsing, we delete the control method
0100      * parse trees.
0101      */
0102     ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0103               "**** Begin Table Object Initialization\n"));
0104 
0105     acpi_ex_enter_interpreter();
0106     status = acpi_ds_initialize_objects(table_index, node);
0107     acpi_ex_exit_interpreter();
0108 
0109     ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0110               "**** Completed Table Object Initialization\n"));
0111 
0112     return_ACPI_STATUS(status);
0113 }
0114 
0115 #ifdef ACPI_OBSOLETE_FUNCTIONS
0116 /*******************************************************************************
0117  *
0118  * FUNCTION:    acpi_load_namespace
0119  *
0120  * PARAMETERS:  None
0121  *
0122  * RETURN:      Status
0123  *
0124  * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
0125  *              (DSDT points to either the BIOS or a buffer.)
0126  *
0127  ******************************************************************************/
0128 
0129 acpi_status acpi_ns_load_namespace(void)
0130 {
0131     acpi_status status;
0132 
0133     ACPI_FUNCTION_TRACE(acpi_load_name_space);
0134 
0135     /* There must be at least a DSDT installed */
0136 
0137     if (acpi_gbl_DSDT == NULL) {
0138         ACPI_ERROR((AE_INFO, "DSDT is not in memory"));
0139         return_ACPI_STATUS(AE_NO_ACPI_TABLES);
0140     }
0141 
0142     /*
0143      * Load the namespace. The DSDT is required,
0144      * but the SSDT and PSDT tables are optional.
0145      */
0146     status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT);
0147     if (ACPI_FAILURE(status)) {
0148         return_ACPI_STATUS(status);
0149     }
0150 
0151     /* Ignore exceptions from these */
0152 
0153     (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT);
0154     (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT);
0155 
0156     ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
0157                   "ACPI Namespace successfully loaded at root %p\n",
0158                   acpi_gbl_root_node));
0159 
0160     return_ACPI_STATUS(status);
0161 }
0162 #endif
0163 
0164 #ifdef ACPI_FUTURE_IMPLEMENTATION
0165 /*******************************************************************************
0166  *
0167  * FUNCTION:    acpi_ns_delete_subtree
0168  *
0169  * PARAMETERS:  start_handle        - Handle in namespace where search begins
0170  *
0171  * RETURNS      Status
0172  *
0173  * DESCRIPTION: Walks the namespace starting at the given handle and deletes
0174  *              all objects, entries, and scopes in the entire subtree.
0175  *
0176  *              Namespace/Interpreter should be locked or the subsystem should
0177  *              be in shutdown before this routine is called.
0178  *
0179  ******************************************************************************/
0180 
0181 static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
0182 {
0183     acpi_status status;
0184     acpi_handle child_handle;
0185     acpi_handle parent_handle;
0186     acpi_handle next_child_handle;
0187     acpi_handle dummy;
0188     u32 level;
0189 
0190     ACPI_FUNCTION_TRACE(ns_delete_subtree);
0191 
0192     parent_handle = start_handle;
0193     child_handle = NULL;
0194     level = 1;
0195 
0196     /*
0197      * Traverse the tree of objects until we bubble back up
0198      * to where we started.
0199      */
0200     while (level > 0) {
0201 
0202         /* Attempt to get the next object in this scope */
0203 
0204         status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle,
0205                           child_handle, &next_child_handle);
0206 
0207         child_handle = next_child_handle;
0208 
0209         /* Did we get a new object? */
0210 
0211         if (ACPI_SUCCESS(status)) {
0212 
0213             /* Check if this object has any children */
0214 
0215             if (ACPI_SUCCESS
0216                 (acpi_get_next_object
0217                  (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) {
0218                 /*
0219                  * There is at least one child of this object,
0220                  * visit the object
0221                  */
0222                 level++;
0223                 parent_handle = child_handle;
0224                 child_handle = NULL;
0225             }
0226         } else {
0227             /*
0228              * No more children in this object, go back up to
0229              * the object's parent
0230              */
0231             level--;
0232 
0233             /* Delete all children now */
0234 
0235             acpi_ns_delete_children(child_handle);
0236 
0237             child_handle = parent_handle;
0238             status = acpi_get_parent(parent_handle, &parent_handle);
0239             if (ACPI_FAILURE(status)) {
0240                 return_ACPI_STATUS(status);
0241             }
0242         }
0243     }
0244 
0245     /* Now delete the starting object, and we are done */
0246 
0247     acpi_ns_remove_node(child_handle);
0248     return_ACPI_STATUS(AE_OK);
0249 }
0250 
0251 /*******************************************************************************
0252  *
0253  *  FUNCTION:       acpi_ns_unload_name_space
0254  *
0255  *  PARAMETERS:     handle          - Root of namespace subtree to be deleted
0256  *
0257  *  RETURN:         Status
0258  *
0259  *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
0260  *                  event. Deletes an entire subtree starting from (and
0261  *                  including) the given handle.
0262  *
0263  ******************************************************************************/
0264 
0265 acpi_status acpi_ns_unload_namespace(acpi_handle handle)
0266 {
0267     acpi_status status;
0268 
0269     ACPI_FUNCTION_TRACE(ns_unload_name_space);
0270 
0271     /* Parameter validation */
0272 
0273     if (!acpi_gbl_root_node) {
0274         return_ACPI_STATUS(AE_NO_NAMESPACE);
0275     }
0276 
0277     if (!handle) {
0278         return_ACPI_STATUS(AE_BAD_PARAMETER);
0279     }
0280 
0281     /* This function does the real work */
0282 
0283     status = acpi_ns_delete_subtree(handle);
0284     return_ACPI_STATUS(status);
0285 }
0286 #endif