nsload.c revision 306536
1/******************************************************************************
2 *
3 * Module Name: nsload - namespace loading/expanding/contracting procedures
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, 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 <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/acnamesp.h>
47#include <contrib/dev/acpica/include/acdispat.h>
48#include <contrib/dev/acpica/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
57ACPI_STATUS
58AcpiNsUnloadNamespace (
59    ACPI_HANDLE             Handle);
60
61static ACPI_STATUS
62AcpiNsDeleteSubtree (
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
81ACPI_STATUS
82AcpiNsLoadTable (
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
144        AcpiTbReleaseOwnerId (TableIndex);
145        return_ACPI_STATUS (Status);
146    }
147
148Unlock:
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    /*
171     * Execute any module-level code that was detected during the table load
172     * phase. Although illegal since ACPI 2.0, there are many machines that
173     * contain this type of code. Each block of detected executable AML code
174     * outside of any control method is wrapped with a temporary control
175     * method object and placed on a global list. The methods on this list
176     * are executed below.
177     *
178     * This case executes the module-level code for each table immediately
179     * after the table has been loaded. This provides compatibility with
180     * other ACPI implementations. Optionally, the execution can be deferred
181     * until later, see AcpiInitializeObjects.
182     */
183    if (!AcpiGbl_GroupModuleLevelCode)
184    {
185        AcpiNsExecModuleCodeList ();
186    }
187
188    return_ACPI_STATUS (Status);
189}
190
191
192#ifdef ACPI_OBSOLETE_FUNCTIONS
193/*******************************************************************************
194 *
195 * FUNCTION:    AcpiLoadNamespace
196 *
197 * PARAMETERS:  None
198 *
199 * RETURN:      Status
200 *
201 * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
202 *              (DSDT points to either the BIOS or a buffer.)
203 *
204 ******************************************************************************/
205
206ACPI_STATUS
207AcpiNsLoadNamespace (
208    void)
209{
210    ACPI_STATUS             Status;
211
212
213    ACPI_FUNCTION_TRACE (AcpiLoadNameSpace);
214
215
216    /* There must be at least a DSDT installed */
217
218    if (AcpiGbl_DSDT == NULL)
219    {
220        ACPI_ERROR ((AE_INFO, "DSDT is not in memory"));
221        return_ACPI_STATUS (AE_NO_ACPI_TABLES);
222    }
223
224    /*
225     * Load the namespace. The DSDT is required,
226     * but the SSDT and PSDT tables are optional.
227     */
228    Status = AcpiNsLoadTableByType (ACPI_TABLE_ID_DSDT);
229    if (ACPI_FAILURE (Status))
230    {
231        return_ACPI_STATUS (Status);
232    }
233
234    /* Ignore exceptions from these */
235
236    (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_SSDT);
237    (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_PSDT);
238
239    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
240        "ACPI Namespace successfully loaded at root %p\n",
241        AcpiGbl_RootNode));
242
243    return_ACPI_STATUS (Status);
244}
245#endif
246
247#ifdef ACPI_FUTURE_IMPLEMENTATION
248/*******************************************************************************
249 *
250 * FUNCTION:    AcpiNsDeleteSubtree
251 *
252 * PARAMETERS:  StartHandle         - Handle in namespace where search begins
253 *
254 * RETURNS      Status
255 *
256 * DESCRIPTION: Walks the namespace starting at the given handle and deletes
257 *              all objects, entries, and scopes in the entire subtree.
258 *
259 *              Namespace/Interpreter should be locked or the subsystem should
260 *              be in shutdown before this routine is called.
261 *
262 ******************************************************************************/
263
264static ACPI_STATUS
265AcpiNsDeleteSubtree (
266    ACPI_HANDLE             StartHandle)
267{
268    ACPI_STATUS             Status;
269    ACPI_HANDLE             ChildHandle;
270    ACPI_HANDLE             ParentHandle;
271    ACPI_HANDLE             NextChildHandle;
272    ACPI_HANDLE             Dummy;
273    UINT32                  Level;
274
275
276    ACPI_FUNCTION_TRACE (NsDeleteSubtree);
277
278
279    ParentHandle = StartHandle;
280    ChildHandle = NULL;
281    Level = 1;
282
283    /*
284     * Traverse the tree of objects until we bubble back up
285     * to where we started.
286     */
287    while (Level > 0)
288    {
289        /* Attempt to get the next object in this scope */
290
291        Status = AcpiGetNextObject (ACPI_TYPE_ANY, ParentHandle,
292            ChildHandle, &NextChildHandle);
293
294        ChildHandle = NextChildHandle;
295
296        /* Did we get a new object? */
297
298        if (ACPI_SUCCESS (Status))
299        {
300            /* Check if this object has any children */
301
302            if (ACPI_SUCCESS (AcpiGetNextObject (ACPI_TYPE_ANY, ChildHandle,
303                NULL, &Dummy)))
304            {
305                /*
306                 * There is at least one child of this object,
307                 * visit the object
308                 */
309                Level++;
310                ParentHandle = ChildHandle;
311                ChildHandle  = NULL;
312            }
313        }
314        else
315        {
316            /*
317             * No more children in this object, go back up to
318             * the object's parent
319             */
320            Level--;
321
322            /* Delete all children now */
323
324            AcpiNsDeleteChildren (ChildHandle);
325
326            ChildHandle = ParentHandle;
327            Status = AcpiGetParent (ParentHandle, &ParentHandle);
328            if (ACPI_FAILURE (Status))
329            {
330                return_ACPI_STATUS (Status);
331            }
332        }
333    }
334
335    /* Now delete the starting object, and we are done */
336
337    AcpiNsRemoveNode (ChildHandle);
338    return_ACPI_STATUS (AE_OK);
339}
340
341
342/*******************************************************************************
343 *
344 *  FUNCTION:       AcpiNsUnloadNameSpace
345 *
346 *  PARAMETERS:     Handle          - Root of namespace subtree to be deleted
347 *
348 *  RETURN:         Status
349 *
350 *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
351 *                  event. Deletes an entire subtree starting from (and
352 *                  including) the given handle.
353 *
354 ******************************************************************************/
355
356ACPI_STATUS
357AcpiNsUnloadNamespace (
358    ACPI_HANDLE             Handle)
359{
360    ACPI_STATUS             Status;
361
362
363    ACPI_FUNCTION_TRACE (NsUnloadNameSpace);
364
365
366    /* Parameter validation */
367
368    if (!AcpiGbl_RootNode)
369    {
370        return_ACPI_STATUS (AE_NO_NAMESPACE);
371    }
372
373    if (!Handle)
374    {
375        return_ACPI_STATUS (AE_BAD_PARAMETER);
376    }
377
378    /* This function does the real work */
379
380    Status = AcpiNsDeleteSubtree (Handle);
381    return_ACPI_STATUS (Status);
382}
383#endif
384#endif
385