1 /******************************************************************************
2  *
3  * Module Name: nsload - namespace loading/expanding/contracting procedures
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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 #include "acpi.h"
45 #include "accommon.h"
46 #include "acnamesp.h"
47 #include "acdispat.h"
48 #include "actables.h"
49 
50 
51 #define _COMPONENT          ACPI_NAMESPACE
52         ACPI_MODULE_NAME    ("nsload")
53 
54 /* Local prototypes */
55 
56 #ifdef ACPI_FUTURE_IMPLEMENTATION
57 ACPI_STATUS
58 AcpiNsUnloadNamespace (
59     ACPI_HANDLE             Handle);
60 
61 static ACPI_STATUS
62 AcpiNsDeleteSubtree (
63     ACPI_HANDLE             StartHandle);
64 #endif
65 
66 
67 #ifndef ACPI_NO_METHOD_EXECUTION
68 /*******************************************************************************
69  *
70  * FUNCTION:    AcpiNsLoadTable
71  *
72  * PARAMETERS:  TableIndex      - Index for table to be loaded
73  *              Node            - Owning NS node
74  *
75  * RETURN:      Status
76  *
77  * DESCRIPTION: Load one ACPI table into the namespace
78  *
79  ******************************************************************************/
80 
81 ACPI_STATUS
82 AcpiNsLoadTable (
83     UINT32                  TableIndex,
84     ACPI_NAMESPACE_NODE     *Node)
85 {
86     ACPI_STATUS             Status;
87 
88 
89     ACPI_FUNCTION_TRACE (NsLoadTable);
90 
91 
92     /*
93      * Parse the table and load the namespace with all named
94      * objects found within. Control methods are NOT parsed
95      * at this time. In fact, the control methods cannot be
96      * parsed until the entire namespace is loaded, because
97      * if a control method makes a forward reference (call)
98      * to another control method, we can't continue parsing
99      * because we don't know how many arguments to parse next!
100      */
101     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
102     if (ACPI_FAILURE (Status))
103     {
104         return_ACPI_STATUS (Status);
105     }
106 
107     /* If table already loaded into namespace, just return */
108 
109     if (AcpiTbIsTableLoaded (TableIndex))
110     {
111         Status = AE_ALREADY_EXISTS;
112         goto Unlock;
113     }
114 
115     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
116         "**** Loading table into namespace ****\n"));
117 
118     Status = AcpiTbAllocateOwnerId (TableIndex);
119     if (ACPI_FAILURE (Status))
120     {
121         goto Unlock;
122     }
123 
124     Status = AcpiNsParseTable (TableIndex, Node);
125     if (ACPI_SUCCESS (Status))
126     {
127         AcpiTbSetTableLoadedFlag (TableIndex, TRUE);
128     }
129     else
130     {
131         /*
132          * On error, delete any namespace objects created by this table.
133          * We cannot initialize these objects, so delete them. There are
134          * a couple of expecially bad cases:
135          * AE_ALREADY_EXISTS - namespace collision.
136          * AE_NOT_FOUND - the target of a Scope operator does not
137          * exist. This target of Scope must already exist in the
138          * namespace, as per the ACPI specification.
139          */
140         (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
141         AcpiNsDeleteNamespaceByOwner (
142             AcpiGbl_RootTableList.Tables[TableIndex].OwnerId);
143             AcpiTbReleaseOwnerId (TableIndex);
144 
145         return_ACPI_STATUS (Status);
146     }
147 
148 Unlock:
149     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
150 
151     if (ACPI_FAILURE (Status))
152     {
153         return_ACPI_STATUS (Status);
154     }
155 
156     /*
157      * Now we can parse the control methods. We always parse
158      * them here for a sanity check, and if configured for
159      * just-in-time parsing, we delete the control method
160      * parse trees.
161      */
162     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
163         "**** Begin Table Object Initialization\n"));
164 
165     Status = AcpiDsInitializeObjects (TableIndex, Node);
166 
167     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
168         "**** Completed Table Object Initialization\n"));
169 
170     return_ACPI_STATUS (Status);
171 }
172 
173 
174 #ifdef ACPI_OBSOLETE_FUNCTIONS
175 /*******************************************************************************
176  *
177  * FUNCTION:    AcpiLoadNamespace
178  *
179  * PARAMETERS:  None
180  *
181  * RETURN:      Status
182  *
183  * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
184  *              (DSDT points to either the BIOS or a buffer.)
185  *
186  ******************************************************************************/
187 
188 ACPI_STATUS
189 AcpiNsLoadNamespace (
190     void)
191 {
192     ACPI_STATUS             Status;
193 
194 
195     ACPI_FUNCTION_TRACE (AcpiLoadNameSpace);
196 
197 
198     /* There must be at least a DSDT installed */
199 
200     if (AcpiGbl_DSDT == NULL)
201     {
202         ACPI_ERROR ((AE_INFO, "DSDT is not in memory"));
203         return_ACPI_STATUS (AE_NO_ACPI_TABLES);
204     }
205 
206     /*
207      * Load the namespace. The DSDT is required,
208      * but the SSDT and PSDT tables are optional.
209      */
210     Status = AcpiNsLoadTableByType (ACPI_TABLE_ID_DSDT);
211     if (ACPI_FAILURE (Status))
212     {
213         return_ACPI_STATUS (Status);
214     }
215 
216     /* Ignore exceptions from these */
217 
218     (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_SSDT);
219     (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_PSDT);
220 
221     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
222         "ACPI Namespace successfully loaded at root %p\n",
223         AcpiGbl_RootNode));
224 
225     return_ACPI_STATUS (Status);
226 }
227 #endif
228 
229 #ifdef ACPI_FUTURE_IMPLEMENTATION
230 /*******************************************************************************
231  *
232  * FUNCTION:    AcpiNsDeleteSubtree
233  *
234  * PARAMETERS:  StartHandle         - Handle in namespace where search begins
235  *
236  * RETURNS      Status
237  *
238  * DESCRIPTION: Walks the namespace starting at the given handle and deletes
239  *              all objects, entries, and scopes in the entire subtree.
240  *
241  *              Namespace/Interpreter should be locked or the subsystem should
242  *              be in shutdown before this routine is called.
243  *
244  ******************************************************************************/
245 
246 static ACPI_STATUS
247 AcpiNsDeleteSubtree (
248     ACPI_HANDLE             StartHandle)
249 {
250     ACPI_STATUS             Status;
251     ACPI_HANDLE             ChildHandle;
252     ACPI_HANDLE             ParentHandle;
253     ACPI_HANDLE             NextChildHandle;
254     ACPI_HANDLE             Dummy;
255     UINT32                  Level;
256 
257 
258     ACPI_FUNCTION_TRACE (NsDeleteSubtree);
259 
260 
261     ParentHandle = StartHandle;
262     ChildHandle  = NULL;
263     Level        = 1;
264 
265     /*
266      * Traverse the tree of objects until we bubble back up
267      * to where we started.
268      */
269     while (Level > 0)
270     {
271         /* Attempt to get the next object in this scope */
272 
273         Status = AcpiGetNextObject (ACPI_TYPE_ANY, ParentHandle,
274                                     ChildHandle, &NextChildHandle);
275 
276         ChildHandle = NextChildHandle;
277 
278         /* Did we get a new object? */
279 
280         if (ACPI_SUCCESS (Status))
281         {
282             /* Check if this object has any children */
283 
284             if (ACPI_SUCCESS (AcpiGetNextObject (ACPI_TYPE_ANY, ChildHandle,
285                                     NULL, &Dummy)))
286             {
287                 /*
288                  * There is at least one child of this object,
289                  * visit the object
290                  */
291                 Level++;
292                 ParentHandle = ChildHandle;
293                 ChildHandle  = NULL;
294             }
295         }
296         else
297         {
298             /*
299              * No more children in this object, go back up to
300              * the object's parent
301              */
302             Level--;
303 
304             /* Delete all children now */
305 
306             AcpiNsDeleteChildren (ChildHandle);
307 
308             ChildHandle = ParentHandle;
309             Status = AcpiGetParent (ParentHandle, &ParentHandle);
310             if (ACPI_FAILURE (Status))
311             {
312                 return_ACPI_STATUS (Status);
313             }
314         }
315     }
316 
317     /* Now delete the starting object, and we are done */
318 
319     AcpiNsRemoveNode (ChildHandle);
320     return_ACPI_STATUS (AE_OK);
321 }
322 
323 
324 /*******************************************************************************
325  *
326  *  FUNCTION:       AcpiNsUnloadNameSpace
327  *
328  *  PARAMETERS:     Handle          - Root of namespace subtree to be deleted
329  *
330  *  RETURN:         Status
331  *
332  *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
333  *                  event. Deletes an entire subtree starting from (and
334  *                  including) the given handle.
335  *
336  ******************************************************************************/
337 
338 ACPI_STATUS
339 AcpiNsUnloadNamespace (
340     ACPI_HANDLE             Handle)
341 {
342     ACPI_STATUS             Status;
343 
344 
345     ACPI_FUNCTION_TRACE (NsUnloadNameSpace);
346 
347 
348     /* Parameter validation */
349 
350     if (!AcpiGbl_RootNode)
351     {
352         return_ACPI_STATUS (AE_NO_NAMESPACE);
353     }
354 
355     if (!Handle)
356     {
357         return_ACPI_STATUS (AE_BAD_PARAMETER);
358     }
359 
360     /* This function does the real work */
361 
362     Status = AcpiNsDeleteSubtree (Handle);
363 
364     return_ACPI_STATUS (Status);
365 }
366 #endif
367 #endif
368