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