1 /******************************************************************************
   2  *
   3  * Module Name: nsload - namespace loading/expanding/contracting procedures
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2013, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 #define __NSLOAD_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acnamesp.h"
  49 #include "acdispat.h"
  50 #include "actables.h"
  51 
  52 
  53 #define _COMPONENT          ACPI_NAMESPACE
  54         ACPI_MODULE_NAME    ("nsload")
  55 
  56 /* Local prototypes */
  57 
  58 #ifdef ACPI_FUTURE_IMPLEMENTATION
  59 ACPI_STATUS
  60 AcpiNsUnloadNamespace (
  61     ACPI_HANDLE             Handle);
  62 
  63 static ACPI_STATUS
  64 AcpiNsDeleteSubtree (
  65     ACPI_HANDLE             StartHandle);
  66 #endif
  67 
  68 
  69 #ifndef ACPI_NO_METHOD_EXECUTION
  70 /*******************************************************************************
  71  *
  72  * FUNCTION:    AcpiNsLoadTable
  73  *
  74  * PARAMETERS:  TableIndex      - Index for table to be loaded
  75  *              Node            - Owning NS node
  76  *
  77  * RETURN:      Status
  78  *
  79  * DESCRIPTION: Load one ACPI table into the namespace
  80  *
  81  ******************************************************************************/
  82 
  83 ACPI_STATUS
  84 AcpiNsLoadTable (
  85     UINT32                  TableIndex,
  86     ACPI_NAMESPACE_NODE     *Node)
  87 {
  88     ACPI_STATUS             Status;
  89 
  90 
  91     ACPI_FUNCTION_TRACE (NsLoadTable);
  92 
  93 
  94     /*
  95      * Parse the table and load the namespace with all named
  96      * objects found within. Control methods are NOT parsed
  97      * at this time. In fact, the control methods cannot be
  98      * parsed until the entire namespace is loaded, because
  99      * if a control method makes a forward reference (call)
 100      * to another control method, we can't continue parsing
 101      * because we don't know how many arguments to parse next!
 102      */
 103     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 104     if (ACPI_FAILURE (Status))
 105     {
 106         return_ACPI_STATUS (Status);
 107     }
 108 
 109     /* If table already loaded into namespace, just return */
 110 
 111     if (AcpiTbIsTableLoaded (TableIndex))
 112     {
 113         Status = AE_ALREADY_EXISTS;
 114         goto Unlock;
 115     }
 116 
 117     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 118         "**** Loading table into namespace ****\n"));
 119 
 120     Status = AcpiTbAllocateOwnerId (TableIndex);
 121     if (ACPI_FAILURE (Status))
 122     {
 123         goto Unlock;
 124     }
 125 
 126     Status = AcpiNsParseTable (TableIndex, Node);
 127     if (ACPI_SUCCESS (Status))
 128     {
 129         AcpiTbSetTableLoadedFlag (TableIndex, TRUE);
 130     }
 131     else
 132     {
 133         (void) AcpiTbReleaseOwnerId (TableIndex);
 134     }
 135 
 136 Unlock:
 137     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 138 
 139     if (ACPI_FAILURE (Status))
 140     {
 141         return_ACPI_STATUS (Status);
 142     }
 143 
 144     /*
 145      * Now we can parse the control methods. We always parse
 146      * them here for a sanity check, and if configured for
 147      * just-in-time parsing, we delete the control method
 148      * parse trees.
 149      */
 150     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 151         "**** Begin Table Method Parsing and Object Initialization\n"));
 152 
 153     Status = AcpiDsInitializeObjects (TableIndex, Node);
 154 
 155     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 156         "**** Completed Table Method Parsing and Object Initialization\n"));
 157 
 158     return_ACPI_STATUS (Status);
 159 }
 160 
 161 
 162 #ifdef ACPI_OBSOLETE_FUNCTIONS
 163 /*******************************************************************************
 164  *
 165  * FUNCTION:    AcpiLoadNamespace
 166  *
 167  * PARAMETERS:  None
 168  *
 169  * RETURN:      Status
 170  *
 171  * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
 172  *              (DSDT points to either the BIOS or a buffer.)
 173  *
 174  ******************************************************************************/
 175 
 176 ACPI_STATUS
 177 AcpiNsLoadNamespace (
 178     void)
 179 {
 180     ACPI_STATUS             Status;
 181 
 182 
 183     ACPI_FUNCTION_TRACE (AcpiLoadNameSpace);
 184 
 185 
 186     /* There must be at least a DSDT installed */
 187 
 188     if (AcpiGbl_DSDT == NULL)
 189     {
 190         ACPI_ERROR ((AE_INFO, "DSDT is not in memory"));
 191         return_ACPI_STATUS (AE_NO_ACPI_TABLES);
 192     }
 193 
 194     /*
 195      * Load the namespace. The DSDT is required,
 196      * but the SSDT and PSDT tables are optional.
 197      */
 198     Status = AcpiNsLoadTableByType (ACPI_TABLE_ID_DSDT);
 199     if (ACPI_FAILURE (Status))
 200     {
 201         return_ACPI_STATUS (Status);
 202     }
 203 
 204     /* Ignore exceptions from these */
 205 
 206     (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_SSDT);
 207     (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_PSDT);
 208 
 209     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
 210         "ACPI Namespace successfully loaded at root %p\n",
 211         AcpiGbl_RootNode));
 212 
 213     return_ACPI_STATUS (Status);
 214 }
 215 #endif
 216 
 217 #ifdef ACPI_FUTURE_IMPLEMENTATION
 218 /*******************************************************************************
 219  *
 220  * FUNCTION:    AcpiNsDeleteSubtree
 221  *
 222  * PARAMETERS:  StartHandle         - Handle in namespace where search begins
 223  *
 224  * RETURNS      Status
 225  *
 226  * DESCRIPTION: Walks the namespace starting at the given handle and deletes
 227  *              all objects, entries, and scopes in the entire subtree.
 228  *
 229  *              Namespace/Interpreter should be locked or the subsystem should
 230  *              be in shutdown before this routine is called.
 231  *
 232  ******************************************************************************/
 233 
 234 static ACPI_STATUS
 235 AcpiNsDeleteSubtree (
 236     ACPI_HANDLE             StartHandle)
 237 {
 238     ACPI_STATUS             Status;
 239     ACPI_HANDLE             ChildHandle;
 240     ACPI_HANDLE             ParentHandle;
 241     ACPI_HANDLE             NextChildHandle;
 242     ACPI_HANDLE             Dummy;
 243     UINT32                  Level;
 244 
 245 
 246     ACPI_FUNCTION_TRACE (NsDeleteSubtree);
 247 
 248 
 249     ParentHandle = StartHandle;
 250     ChildHandle  = NULL;
 251     Level        = 1;
 252 
 253     /*
 254      * Traverse the tree of objects until we bubble back up
 255      * to where we started.
 256      */
 257     while (Level > 0)
 258     {
 259         /* Attempt to get the next object in this scope */
 260 
 261         Status = AcpiGetNextObject (ACPI_TYPE_ANY, ParentHandle,
 262                                     ChildHandle, &NextChildHandle);
 263 
 264         ChildHandle = NextChildHandle;
 265 
 266         /* Did we get a new object? */
 267 
 268         if (ACPI_SUCCESS (Status))
 269         {
 270             /* Check if this object has any children */
 271 
 272             if (ACPI_SUCCESS (AcpiGetNextObject (ACPI_TYPE_ANY, ChildHandle,
 273                                     NULL, &Dummy)))
 274             {
 275                 /*
 276                  * There is at least one child of this object,
 277                  * visit the object
 278                  */
 279                 Level++;
 280                 ParentHandle = ChildHandle;
 281                 ChildHandle  = NULL;
 282             }
 283         }
 284         else
 285         {
 286             /*
 287              * No more children in this object, go back up to
 288              * the object's parent
 289              */
 290             Level--;
 291 
 292             /* Delete all children now */
 293 
 294             AcpiNsDeleteChildren (ChildHandle);
 295 
 296             ChildHandle = ParentHandle;
 297             Status = AcpiGetParent (ParentHandle, &ParentHandle);
 298             if (ACPI_FAILURE (Status))
 299             {
 300                 return_ACPI_STATUS (Status);
 301             }
 302         }
 303     }
 304 
 305     /* Now delete the starting object, and we are done */
 306 
 307     AcpiNsRemoveNode (ChildHandle);
 308     return_ACPI_STATUS (AE_OK);
 309 }
 310 
 311 
 312 /*******************************************************************************
 313  *
 314  *  FUNCTION:       AcpiNsUnloadNameSpace
 315  *
 316  *  PARAMETERS:     Handle          - Root of namespace subtree to be deleted
 317  *
 318  *  RETURN:         Status
 319  *
 320  *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
 321  *                  event. Deletes an entire subtree starting from (and
 322  *                  including) the given handle.
 323  *
 324  ******************************************************************************/
 325 
 326 ACPI_STATUS
 327 AcpiNsUnloadNamespace (
 328     ACPI_HANDLE             Handle)
 329 {
 330     ACPI_STATUS             Status;
 331 
 332 
 333     ACPI_FUNCTION_TRACE (NsUnloadNameSpace);
 334 
 335 
 336     /* Parameter validation */
 337 
 338     if (!AcpiGbl_RootNode)
 339     {
 340         return_ACPI_STATUS (AE_NO_NAMESPACE);
 341     }
 342 
 343     if (!Handle)
 344     {
 345         return_ACPI_STATUS (AE_BAD_PARAMETER);
 346     }
 347 
 348     /* This function does the real work */
 349 
 350     Status = AcpiNsDeleteSubtree (Handle);
 351 
 352     return_ACPI_STATUS (Status);
 353 }
 354 #endif
 355 #endif