xref: /netbsd-src/sys/external/bsd/acpica/dist/namespace/nsload.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
128c506b8Sjruoho /******************************************************************************
228c506b8Sjruoho  *
328c506b8Sjruoho  * Module Name: nsload - namespace loading/expanding/contracting procedures
428c506b8Sjruoho  *
528c506b8Sjruoho  *****************************************************************************/
628c506b8Sjruoho 
7124f4c82Sjruoho /*
8*046a2985Schristos  * Copyright (C) 2000 - 2023, Intel Corp.
928c506b8Sjruoho  * All rights reserved.
1028c506b8Sjruoho  *
11124f4c82Sjruoho  * Redistribution and use in source and binary forms, with or without
12124f4c82Sjruoho  * modification, are permitted provided that the following conditions
13124f4c82Sjruoho  * are met:
14124f4c82Sjruoho  * 1. Redistributions of source code must retain the above copyright
15124f4c82Sjruoho  *    notice, this list of conditions, and the following disclaimer,
16124f4c82Sjruoho  *    without modification.
17124f4c82Sjruoho  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18124f4c82Sjruoho  *    substantially similar to the "NO WARRANTY" disclaimer below
19124f4c82Sjruoho  *    ("Disclaimer") and any redistribution must be conditioned upon
20124f4c82Sjruoho  *    including a substantially similar Disclaimer requirement for further
21124f4c82Sjruoho  *    binary redistribution.
22124f4c82Sjruoho  * 3. Neither the names of the above-listed copyright holders nor the names
23124f4c82Sjruoho  *    of any contributors may be used to endorse or promote products derived
24124f4c82Sjruoho  *    from this software without specific prior written permission.
2528c506b8Sjruoho  *
26124f4c82Sjruoho  * Alternatively, this software may be distributed under the terms of the
27124f4c82Sjruoho  * GNU General Public License ("GPL") version 2 as published by the Free
28124f4c82Sjruoho  * Software Foundation.
2928c506b8Sjruoho  *
30124f4c82Sjruoho  * NO WARRANTY
31124f4c82Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32124f4c82Sjruoho  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3346a330b4Schristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34124f4c82Sjruoho  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35124f4c82Sjruoho  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36124f4c82Sjruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37124f4c82Sjruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38124f4c82Sjruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39124f4c82Sjruoho  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40124f4c82Sjruoho  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41124f4c82Sjruoho  * POSSIBILITY OF SUCH DAMAGES.
42124f4c82Sjruoho  */
4328c506b8Sjruoho 
4428c506b8Sjruoho #include "acpi.h"
4528c506b8Sjruoho #include "accommon.h"
4628c506b8Sjruoho #include "acnamesp.h"
4728c506b8Sjruoho #include "acdispat.h"
4828c506b8Sjruoho #include "actables.h"
49d0e1da26Schristos #include "acinterp.h"
5028c506b8Sjruoho 
5128c506b8Sjruoho 
5228c506b8Sjruoho #define _COMPONENT          ACPI_NAMESPACE
5328c506b8Sjruoho         ACPI_MODULE_NAME    ("nsload")
5428c506b8Sjruoho 
5528c506b8Sjruoho /* Local prototypes */
5628c506b8Sjruoho 
5728c506b8Sjruoho #ifdef ACPI_FUTURE_IMPLEMENTATION
5828c506b8Sjruoho ACPI_STATUS
5928c506b8Sjruoho AcpiNsUnloadNamespace (
6028c506b8Sjruoho     ACPI_HANDLE             Handle);
6128c506b8Sjruoho 
6228c506b8Sjruoho static ACPI_STATUS
6328c506b8Sjruoho AcpiNsDeleteSubtree (
6428c506b8Sjruoho     ACPI_HANDLE             StartHandle);
6528c506b8Sjruoho #endif
6628c506b8Sjruoho 
6728c506b8Sjruoho 
6828c506b8Sjruoho /*******************************************************************************
6928c506b8Sjruoho  *
7028c506b8Sjruoho  * FUNCTION:    AcpiNsLoadTable
7128c506b8Sjruoho  *
7228c506b8Sjruoho  * PARAMETERS:  TableIndex      - Index for table to be loaded
7328c506b8Sjruoho  *              Node            - Owning NS node
7428c506b8Sjruoho  *
7528c506b8Sjruoho  * RETURN:      Status
7628c506b8Sjruoho  *
7728c506b8Sjruoho  * DESCRIPTION: Load one ACPI table into the namespace
7828c506b8Sjruoho  *
7928c506b8Sjruoho  ******************************************************************************/
8028c506b8Sjruoho 
8128c506b8Sjruoho ACPI_STATUS
AcpiNsLoadTable(UINT32 TableIndex,ACPI_NAMESPACE_NODE * Node)8228c506b8Sjruoho AcpiNsLoadTable (
8328c506b8Sjruoho     UINT32                  TableIndex,
8428c506b8Sjruoho     ACPI_NAMESPACE_NODE     *Node)
8528c506b8Sjruoho {
8628c506b8Sjruoho     ACPI_STATUS             Status;
8728c506b8Sjruoho 
8828c506b8Sjruoho 
8928c506b8Sjruoho     ACPI_FUNCTION_TRACE (NsLoadTable);
9028c506b8Sjruoho 
9128c506b8Sjruoho 
9228c506b8Sjruoho     /* If table already loaded into namespace, just return */
9328c506b8Sjruoho 
9428c506b8Sjruoho     if (AcpiTbIsTableLoaded (TableIndex))
9528c506b8Sjruoho     {
9628c506b8Sjruoho         Status = AE_ALREADY_EXISTS;
9728c506b8Sjruoho         goto Unlock;
9828c506b8Sjruoho     }
9928c506b8Sjruoho 
10028c506b8Sjruoho     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
10128c506b8Sjruoho         "**** Loading table into namespace ****\n"));
10228c506b8Sjruoho 
10328c506b8Sjruoho     Status = AcpiTbAllocateOwnerId (TableIndex);
10428c506b8Sjruoho     if (ACPI_FAILURE (Status))
10528c506b8Sjruoho     {
10628c506b8Sjruoho         goto Unlock;
10728c506b8Sjruoho     }
10828c506b8Sjruoho 
109d0e1da26Schristos     /*
110d0e1da26Schristos      * Parse the table and load the namespace with all named
111d0e1da26Schristos      * objects found within. Control methods are NOT parsed
112d0e1da26Schristos      * at this time. In fact, the control methods cannot be
113d0e1da26Schristos      * parsed until the entire namespace is loaded, because
114d0e1da26Schristos      * if a control method makes a forward reference (call)
115d0e1da26Schristos      * to another control method, we can't continue parsing
116d0e1da26Schristos      * because we don't know how many arguments to parse next!
117d0e1da26Schristos      */
11828c506b8Sjruoho     Status = AcpiNsParseTable (TableIndex, Node);
11928c506b8Sjruoho     if (ACPI_SUCCESS (Status))
12028c506b8Sjruoho     {
12128c506b8Sjruoho         AcpiTbSetTableLoadedFlag (TableIndex, TRUE);
12228c506b8Sjruoho     }
12328c506b8Sjruoho     else
12428c506b8Sjruoho     {
12571e38f1dSchristos         /*
12671e38f1dSchristos          * On error, delete any namespace objects created by this table.
12771e38f1dSchristos          * We cannot initialize these objects, so delete them. There are
12894783addSchristos          * a couple of especially bad cases:
12971e38f1dSchristos          * AE_ALREADY_EXISTS - namespace collision.
13071e38f1dSchristos          * AE_NOT_FOUND - the target of a Scope operator does not
13171e38f1dSchristos          * exist. This target of Scope must already exist in the
13271e38f1dSchristos          * namespace, as per the ACPI specification.
13371e38f1dSchristos          */
13471e38f1dSchristos         AcpiNsDeleteNamespaceByOwner (
13571e38f1dSchristos             AcpiGbl_RootTableList.Tables[TableIndex].OwnerId);
13671e38f1dSchristos 
137cfbb7280Schristos         AcpiTbReleaseOwnerId (TableIndex);
13871e38f1dSchristos         return_ACPI_STATUS (Status);
13928c506b8Sjruoho     }
14028c506b8Sjruoho 
14128c506b8Sjruoho Unlock:
14228c506b8Sjruoho     if (ACPI_FAILURE (Status))
14328c506b8Sjruoho     {
14428c506b8Sjruoho         return_ACPI_STATUS (Status);
14528c506b8Sjruoho     }
14628c506b8Sjruoho 
14728c506b8Sjruoho     /*
14828c506b8Sjruoho      * Now we can parse the control methods. We always parse
14928c506b8Sjruoho      * them here for a sanity check, and if configured for
15028c506b8Sjruoho      * just-in-time parsing, we delete the control method
15128c506b8Sjruoho      * parse trees.
15228c506b8Sjruoho      */
15328c506b8Sjruoho     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
154460301d4Schristos         "**** Begin Table Object Initialization\n"));
15528c506b8Sjruoho 
1560b89cdedSchristos     AcpiExEnterInterpreter ();
15728c506b8Sjruoho     Status = AcpiDsInitializeObjects (TableIndex, Node);
1580b89cdedSchristos     AcpiExExitInterpreter ();
15928c506b8Sjruoho 
16028c506b8Sjruoho     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
161460301d4Schristos         "**** Completed Table Object Initialization\n"));
16228c506b8Sjruoho 
16328c506b8Sjruoho     return_ACPI_STATUS (Status);
16428c506b8Sjruoho }
16528c506b8Sjruoho 
16628c506b8Sjruoho 
16728c506b8Sjruoho #ifdef ACPI_OBSOLETE_FUNCTIONS
16828c506b8Sjruoho /*******************************************************************************
16928c506b8Sjruoho  *
17028c506b8Sjruoho  * FUNCTION:    AcpiLoadNamespace
17128c506b8Sjruoho  *
17228c506b8Sjruoho  * PARAMETERS:  None
17328c506b8Sjruoho  *
17428c506b8Sjruoho  * RETURN:      Status
17528c506b8Sjruoho  *
17628c506b8Sjruoho  * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
17728c506b8Sjruoho  *              (DSDT points to either the BIOS or a buffer.)
17828c506b8Sjruoho  *
17928c506b8Sjruoho  ******************************************************************************/
18028c506b8Sjruoho 
18128c506b8Sjruoho ACPI_STATUS
AcpiNsLoadNamespace(void)18228c506b8Sjruoho AcpiNsLoadNamespace (
18328c506b8Sjruoho     void)
18428c506b8Sjruoho {
18528c506b8Sjruoho     ACPI_STATUS             Status;
18628c506b8Sjruoho 
18728c506b8Sjruoho 
18828c506b8Sjruoho     ACPI_FUNCTION_TRACE (AcpiLoadNameSpace);
18928c506b8Sjruoho 
19028c506b8Sjruoho 
19128c506b8Sjruoho     /* There must be at least a DSDT installed */
19228c506b8Sjruoho 
19328c506b8Sjruoho     if (AcpiGbl_DSDT == NULL)
19428c506b8Sjruoho     {
19528c506b8Sjruoho         ACPI_ERROR ((AE_INFO, "DSDT is not in memory"));
19628c506b8Sjruoho         return_ACPI_STATUS (AE_NO_ACPI_TABLES);
19728c506b8Sjruoho     }
19828c506b8Sjruoho 
19928c506b8Sjruoho     /*
20028c506b8Sjruoho      * Load the namespace. The DSDT is required,
20128c506b8Sjruoho      * but the SSDT and PSDT tables are optional.
20228c506b8Sjruoho      */
20328c506b8Sjruoho     Status = AcpiNsLoadTableByType (ACPI_TABLE_ID_DSDT);
20428c506b8Sjruoho     if (ACPI_FAILURE (Status))
20528c506b8Sjruoho     {
20628c506b8Sjruoho         return_ACPI_STATUS (Status);
20728c506b8Sjruoho     }
20828c506b8Sjruoho 
20928c506b8Sjruoho     /* Ignore exceptions from these */
21028c506b8Sjruoho 
21128c506b8Sjruoho     (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_SSDT);
21228c506b8Sjruoho     (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_PSDT);
21328c506b8Sjruoho 
21428c506b8Sjruoho     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
21528c506b8Sjruoho         "ACPI Namespace successfully loaded at root %p\n",
21628c506b8Sjruoho         AcpiGbl_RootNode));
21728c506b8Sjruoho 
21828c506b8Sjruoho     return_ACPI_STATUS (Status);
21928c506b8Sjruoho }
22028c506b8Sjruoho #endif
22128c506b8Sjruoho 
22228c506b8Sjruoho #ifdef ACPI_FUTURE_IMPLEMENTATION
22328c506b8Sjruoho /*******************************************************************************
22428c506b8Sjruoho  *
22528c506b8Sjruoho  * FUNCTION:    AcpiNsDeleteSubtree
22628c506b8Sjruoho  *
22728c506b8Sjruoho  * PARAMETERS:  StartHandle         - Handle in namespace where search begins
22828c506b8Sjruoho  *
22928c506b8Sjruoho  * RETURNS      Status
23028c506b8Sjruoho  *
23128c506b8Sjruoho  * DESCRIPTION: Walks the namespace starting at the given handle and deletes
23228c506b8Sjruoho  *              all objects, entries, and scopes in the entire subtree.
23328c506b8Sjruoho  *
23428c506b8Sjruoho  *              Namespace/Interpreter should be locked or the subsystem should
23528c506b8Sjruoho  *              be in shutdown before this routine is called.
23628c506b8Sjruoho  *
23728c506b8Sjruoho  ******************************************************************************/
23828c506b8Sjruoho 
23928c506b8Sjruoho static ACPI_STATUS
AcpiNsDeleteSubtree(ACPI_HANDLE StartHandle)24028c506b8Sjruoho AcpiNsDeleteSubtree (
24128c506b8Sjruoho     ACPI_HANDLE             StartHandle)
24228c506b8Sjruoho {
24328c506b8Sjruoho     ACPI_STATUS             Status;
24428c506b8Sjruoho     ACPI_HANDLE             ChildHandle;
24528c506b8Sjruoho     ACPI_HANDLE             ParentHandle;
24628c506b8Sjruoho     ACPI_HANDLE             NextChildHandle;
24728c506b8Sjruoho     ACPI_HANDLE             Dummy;
24828c506b8Sjruoho     UINT32                  Level;
24928c506b8Sjruoho 
25028c506b8Sjruoho 
25128c506b8Sjruoho     ACPI_FUNCTION_TRACE (NsDeleteSubtree);
25228c506b8Sjruoho 
25328c506b8Sjruoho 
25428c506b8Sjruoho     ParentHandle = StartHandle;
25528c506b8Sjruoho     ChildHandle = NULL;
25628c506b8Sjruoho     Level = 1;
25728c506b8Sjruoho 
25828c506b8Sjruoho     /*
25928c506b8Sjruoho      * Traverse the tree of objects until we bubble back up
26028c506b8Sjruoho      * to where we started.
26128c506b8Sjruoho      */
26228c506b8Sjruoho     while (Level > 0)
26328c506b8Sjruoho     {
26428c506b8Sjruoho         /* Attempt to get the next object in this scope */
26528c506b8Sjruoho 
26628c506b8Sjruoho         Status = AcpiGetNextObject (ACPI_TYPE_ANY, ParentHandle,
26728c506b8Sjruoho             ChildHandle, &NextChildHandle);
26828c506b8Sjruoho 
26928c506b8Sjruoho         ChildHandle = NextChildHandle;
27028c506b8Sjruoho 
27128c506b8Sjruoho         /* Did we get a new object? */
27228c506b8Sjruoho 
27328c506b8Sjruoho         if (ACPI_SUCCESS (Status))
27428c506b8Sjruoho         {
27528c506b8Sjruoho             /* Check if this object has any children */
27628c506b8Sjruoho 
27728c506b8Sjruoho             if (ACPI_SUCCESS (AcpiGetNextObject (ACPI_TYPE_ANY, ChildHandle,
27828c506b8Sjruoho                 NULL, &Dummy)))
27928c506b8Sjruoho             {
28028c506b8Sjruoho                 /*
28128c506b8Sjruoho                  * There is at least one child of this object,
28228c506b8Sjruoho                  * visit the object
28328c506b8Sjruoho                  */
28428c506b8Sjruoho                 Level++;
28528c506b8Sjruoho                 ParentHandle = ChildHandle;
28628c506b8Sjruoho                 ChildHandle  = NULL;
28728c506b8Sjruoho             }
28828c506b8Sjruoho         }
28928c506b8Sjruoho         else
29028c506b8Sjruoho         {
29128c506b8Sjruoho             /*
29228c506b8Sjruoho              * No more children in this object, go back up to
29328c506b8Sjruoho              * the object's parent
29428c506b8Sjruoho              */
29528c506b8Sjruoho             Level--;
29628c506b8Sjruoho 
29728c506b8Sjruoho             /* Delete all children now */
29828c506b8Sjruoho 
29928c506b8Sjruoho             AcpiNsDeleteChildren (ChildHandle);
30028c506b8Sjruoho 
30128c506b8Sjruoho             ChildHandle = ParentHandle;
30228c506b8Sjruoho             Status = AcpiGetParent (ParentHandle, &ParentHandle);
30328c506b8Sjruoho             if (ACPI_FAILURE (Status))
30428c506b8Sjruoho             {
30528c506b8Sjruoho                 return_ACPI_STATUS (Status);
30628c506b8Sjruoho             }
30728c506b8Sjruoho         }
30828c506b8Sjruoho     }
30928c506b8Sjruoho 
31028c506b8Sjruoho     /* Now delete the starting object, and we are done */
31128c506b8Sjruoho 
31228c506b8Sjruoho     AcpiNsRemoveNode (ChildHandle);
31328c506b8Sjruoho     return_ACPI_STATUS (AE_OK);
31428c506b8Sjruoho }
31528c506b8Sjruoho 
31628c506b8Sjruoho 
31728c506b8Sjruoho /*******************************************************************************
31828c506b8Sjruoho  *
31928c506b8Sjruoho  *  FUNCTION:       AcpiNsUnloadNameSpace
32028c506b8Sjruoho  *
32128c506b8Sjruoho  *  PARAMETERS:     Handle          - Root of namespace subtree to be deleted
32228c506b8Sjruoho  *
32328c506b8Sjruoho  *  RETURN:         Status
32428c506b8Sjruoho  *
32528c506b8Sjruoho  *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
32628c506b8Sjruoho  *                  event. Deletes an entire subtree starting from (and
32728c506b8Sjruoho  *                  including) the given handle.
32828c506b8Sjruoho  *
32928c506b8Sjruoho  ******************************************************************************/
33028c506b8Sjruoho 
33128c506b8Sjruoho ACPI_STATUS
AcpiNsUnloadNamespace(ACPI_HANDLE Handle)33228c506b8Sjruoho AcpiNsUnloadNamespace (
33328c506b8Sjruoho     ACPI_HANDLE             Handle)
33428c506b8Sjruoho {
33528c506b8Sjruoho     ACPI_STATUS             Status;
33628c506b8Sjruoho 
33728c506b8Sjruoho 
33828c506b8Sjruoho     ACPI_FUNCTION_TRACE (NsUnloadNameSpace);
33928c506b8Sjruoho 
34028c506b8Sjruoho 
34128c506b8Sjruoho     /* Parameter validation */
34228c506b8Sjruoho 
34328c506b8Sjruoho     if (!AcpiGbl_RootNode)
34428c506b8Sjruoho     {
34528c506b8Sjruoho         return_ACPI_STATUS (AE_NO_NAMESPACE);
34628c506b8Sjruoho     }
34728c506b8Sjruoho 
34828c506b8Sjruoho     if (!Handle)
34928c506b8Sjruoho     {
35028c506b8Sjruoho         return_ACPI_STATUS (AE_BAD_PARAMETER);
35128c506b8Sjruoho     }
35228c506b8Sjruoho 
35328c506b8Sjruoho     /* This function does the real work */
35428c506b8Sjruoho 
35528c506b8Sjruoho     Status = AcpiNsDeleteSubtree (Handle);
35628c506b8Sjruoho     return_ACPI_STATUS (Status);
35728c506b8Sjruoho }
35828c506b8Sjruoho #endif
359