xref: /netbsd-src/sys/external/bsd/acpica/dist/namespace/nsparse.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
128c506b8Sjruoho /******************************************************************************
228c506b8Sjruoho  *
328c506b8Sjruoho  * Module Name: nsparse - namespace interface to AML parser
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 "acparser.h"
4828c506b8Sjruoho #include "acdispat.h"
4928c506b8Sjruoho #include "actables.h"
50d0e1da26Schristos #include "acinterp.h"
5128c506b8Sjruoho 
5228c506b8Sjruoho 
5328c506b8Sjruoho #define _COMPONENT          ACPI_NAMESPACE
5428c506b8Sjruoho         ACPI_MODULE_NAME    ("nsparse")
5528c506b8Sjruoho 
5628c506b8Sjruoho 
5728c506b8Sjruoho /*******************************************************************************
5828c506b8Sjruoho  *
59d0e1da26Schristos  * FUNCTION:    NsExecuteTable
60d0e1da26Schristos  *
61d0e1da26Schristos  * PARAMETERS:  TableDesc       - An ACPI table descriptor for table to parse
62d0e1da26Schristos  *              StartNode       - Where to enter the table into the namespace
63d0e1da26Schristos  *
64d0e1da26Schristos  * RETURN:      Status
65d0e1da26Schristos  *
66062782b3Schristos  * DESCRIPTION: Load ACPI/AML table by executing the entire table as a single
67062782b3Schristos  *              large control method.
68062782b3Schristos  *
69062782b3Schristos  * NOTE: The point of this is to execute any module-level code in-place
70062782b3Schristos  * as the table is parsed. Some AML code depends on this behavior.
71062782b3Schristos  *
72062782b3Schristos  * It is a run-time option at this time, but will eventually become
73062782b3Schristos  * the default.
74062782b3Schristos  *
75062782b3Schristos  * Note: This causes the table to only have a single-pass parse.
76062782b3Schristos  * However, this is compatible with other ACPI implementations.
77d0e1da26Schristos  *
78d0e1da26Schristos  ******************************************************************************/
79d0e1da26Schristos 
80d0e1da26Schristos ACPI_STATUS
AcpiNsExecuteTable(UINT32 TableIndex,ACPI_NAMESPACE_NODE * StartNode)81d0e1da26Schristos AcpiNsExecuteTable (
82d0e1da26Schristos     UINT32                  TableIndex,
83d0e1da26Schristos     ACPI_NAMESPACE_NODE     *StartNode)
84d0e1da26Schristos {
85d0e1da26Schristos     ACPI_STATUS             Status;
86d0e1da26Schristos     ACPI_TABLE_HEADER       *Table;
87d0e1da26Schristos     ACPI_OWNER_ID           OwnerId;
88d0e1da26Schristos     ACPI_EVALUATE_INFO      *Info = NULL;
89d0e1da26Schristos     UINT32                  AmlLength;
90d0e1da26Schristos     UINT8                   *AmlStart;
91d0e1da26Schristos     ACPI_OPERAND_OBJECT     *MethodObj = NULL;
92d0e1da26Schristos 
93d0e1da26Schristos 
94d0e1da26Schristos     ACPI_FUNCTION_TRACE (NsExecuteTable);
95d0e1da26Schristos 
96d0e1da26Schristos 
97d0e1da26Schristos     Status = AcpiGetTableByIndex (TableIndex, &Table);
98d0e1da26Schristos     if (ACPI_FAILURE (Status))
99d0e1da26Schristos     {
100d0e1da26Schristos         return_ACPI_STATUS (Status);
101d0e1da26Schristos     }
102d0e1da26Schristos 
103d0e1da26Schristos     /* Table must consist of at least a complete header */
104d0e1da26Schristos 
105d0e1da26Schristos     if (Table->Length < sizeof (ACPI_TABLE_HEADER))
106d0e1da26Schristos     {
107d0e1da26Schristos         return_ACPI_STATUS (AE_BAD_HEADER);
108d0e1da26Schristos     }
109d0e1da26Schristos 
110d0e1da26Schristos     AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER);
111d0e1da26Schristos     AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
112d0e1da26Schristos 
113d0e1da26Schristos     Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
114d0e1da26Schristos     if (ACPI_FAILURE (Status))
115d0e1da26Schristos     {
116d0e1da26Schristos         return_ACPI_STATUS (Status);
117d0e1da26Schristos     }
118d0e1da26Schristos 
119d0e1da26Schristos     /* Create, initialize, and link a new temporary method object */
120d0e1da26Schristos 
121d0e1da26Schristos     MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
122d0e1da26Schristos     if (!MethodObj)
123d0e1da26Schristos     {
124d0e1da26Schristos         return_ACPI_STATUS (AE_NO_MEMORY);
125d0e1da26Schristos     }
126d0e1da26Schristos 
127d0e1da26Schristos     /* Allocate the evaluation information block */
128d0e1da26Schristos 
129d0e1da26Schristos     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
130d0e1da26Schristos     if (!Info)
131d0e1da26Schristos     {
132d0e1da26Schristos         Status = AE_NO_MEMORY;
133d0e1da26Schristos         goto Cleanup;
134d0e1da26Schristos     }
135d0e1da26Schristos 
136062782b3Schristos     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
137062782b3Schristos         "%s: Create table pseudo-method for [%4.4s] @%p, method %p\n",
138062782b3Schristos         ACPI_GET_FUNCTION_NAME, Table->Signature, Table, MethodObj));
139d0e1da26Schristos 
140d0e1da26Schristos     MethodObj->Method.AmlStart = AmlStart;
141d0e1da26Schristos     MethodObj->Method.AmlLength = AmlLength;
142d0e1da26Schristos     MethodObj->Method.OwnerId = OwnerId;
143d0e1da26Schristos     MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL;
144d0e1da26Schristos 
145d0e1da26Schristos     Info->PassNumber = ACPI_IMODE_EXECUTE;
146d0e1da26Schristos     Info->Node = StartNode;
147d0e1da26Schristos     Info->ObjDesc = MethodObj;
148d0e1da26Schristos     Info->NodeFlags = Info->Node->Flags;
149d0e1da26Schristos     Info->FullPathname = AcpiNsGetNormalizedPathname (Info->Node, TRUE);
150d0e1da26Schristos     if (!Info->FullPathname)
151d0e1da26Schristos     {
152d0e1da26Schristos         Status = AE_NO_MEMORY;
153d0e1da26Schristos         goto Cleanup;
154d0e1da26Schristos     }
155d0e1da26Schristos 
1564c4e8184Schristos     /* Optional object evaluation log */
1574c4e8184Schristos 
1584c4e8184Schristos     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION,
1594c4e8184Schristos         "%-26s:  (Definition Block level)\n", "Module-level evaluation"));
1604c4e8184Schristos 
161d0e1da26Schristos     Status = AcpiPsExecuteTable (Info);
162d0e1da26Schristos 
1634c4e8184Schristos     /* Optional object evaluation log */
1644c4e8184Schristos 
1654c4e8184Schristos     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION,
1664c4e8184Schristos         "%-26s:  (Definition Block level)\n", "Module-level complete"));
1674c4e8184Schristos 
168d0e1da26Schristos Cleanup:
169d0e1da26Schristos     if (Info)
170d0e1da26Schristos     {
171d0e1da26Schristos         ACPI_FREE (Info->FullPathname);
172d0e1da26Schristos         Info->FullPathname = NULL;
173d0e1da26Schristos     }
174d0e1da26Schristos     ACPI_FREE (Info);
175d0e1da26Schristos     AcpiUtRemoveReference (MethodObj);
176d0e1da26Schristos     return_ACPI_STATUS (Status);
177d0e1da26Schristos }
178d0e1da26Schristos 
179d0e1da26Schristos 
180d0e1da26Schristos /*******************************************************************************
181d0e1da26Schristos  *
18228c506b8Sjruoho  * FUNCTION:    NsOneCompleteParse
18328c506b8Sjruoho  *
18428c506b8Sjruoho  * PARAMETERS:  PassNumber              - 1 or 2
18528c506b8Sjruoho  *              TableDesc               - The table to be parsed.
18628c506b8Sjruoho  *
18728c506b8Sjruoho  * RETURN:      Status
18828c506b8Sjruoho  *
18928c506b8Sjruoho  * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
19028c506b8Sjruoho  *
19128c506b8Sjruoho  ******************************************************************************/
19228c506b8Sjruoho 
19328c506b8Sjruoho ACPI_STATUS
AcpiNsOneCompleteParse(UINT32 PassNumber,UINT32 TableIndex,ACPI_NAMESPACE_NODE * StartNode)19428c506b8Sjruoho AcpiNsOneCompleteParse (
19528c506b8Sjruoho     UINT32                  PassNumber,
19628c506b8Sjruoho     UINT32                  TableIndex,
19728c506b8Sjruoho     ACPI_NAMESPACE_NODE     *StartNode)
19828c506b8Sjruoho {
19928c506b8Sjruoho     ACPI_PARSE_OBJECT       *ParseRoot;
20028c506b8Sjruoho     ACPI_STATUS             Status;
20128c506b8Sjruoho     UINT32                  AmlLength;
20228c506b8Sjruoho     UINT8                   *AmlStart;
20328c506b8Sjruoho     ACPI_WALK_STATE         *WalkState;
20428c506b8Sjruoho     ACPI_TABLE_HEADER       *Table;
20528c506b8Sjruoho     ACPI_OWNER_ID           OwnerId;
20628c506b8Sjruoho 
20728c506b8Sjruoho 
20828c506b8Sjruoho     ACPI_FUNCTION_TRACE (NsOneCompleteParse);
20928c506b8Sjruoho 
21028c506b8Sjruoho 
211c72da027Schristos     Status = AcpiGetTableByIndex (TableIndex, &Table);
212c72da027Schristos     if (ACPI_FAILURE (Status))
213c72da027Schristos     {
214c72da027Schristos         return_ACPI_STATUS (Status);
215c72da027Schristos     }
216c72da027Schristos 
217c72da027Schristos     /* Table must consist of at least a complete header */
218c72da027Schristos 
219c72da027Schristos     if (Table->Length < sizeof (ACPI_TABLE_HEADER))
220c72da027Schristos     {
221c72da027Schristos         return_ACPI_STATUS (AE_BAD_HEADER);
222c72da027Schristos     }
223c72da027Schristos 
224c72da027Schristos     AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER);
225c72da027Schristos     AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
226c72da027Schristos 
22728c506b8Sjruoho     Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
22828c506b8Sjruoho     if (ACPI_FAILURE (Status))
22928c506b8Sjruoho     {
23028c506b8Sjruoho         return_ACPI_STATUS (Status);
23128c506b8Sjruoho     }
23228c506b8Sjruoho 
23328c506b8Sjruoho     /* Create and init a Root Node */
23428c506b8Sjruoho 
235c72da027Schristos     ParseRoot = AcpiPsCreateScopeOp (AmlStart);
23628c506b8Sjruoho     if (!ParseRoot)
23728c506b8Sjruoho     {
23828c506b8Sjruoho         return_ACPI_STATUS (AE_NO_MEMORY);
23928c506b8Sjruoho     }
24028c506b8Sjruoho 
24128c506b8Sjruoho     /* Create and initialize a new walk state */
24228c506b8Sjruoho 
24328c506b8Sjruoho     WalkState = AcpiDsCreateWalkState (OwnerId, NULL, NULL, NULL);
24428c506b8Sjruoho     if (!WalkState)
24528c506b8Sjruoho     {
24628c506b8Sjruoho         AcpiPsFreeOp (ParseRoot);
24728c506b8Sjruoho         return_ACPI_STATUS (AE_NO_MEMORY);
24828c506b8Sjruoho     }
24928c506b8Sjruoho 
25028c506b8Sjruoho     Status = AcpiDsInitAmlWalk (WalkState, ParseRoot, NULL,
25128c506b8Sjruoho         AmlStart, AmlLength, NULL, (UINT8) PassNumber);
25228c506b8Sjruoho     if (ACPI_FAILURE (Status))
25328c506b8Sjruoho     {
25428c506b8Sjruoho         AcpiDsDeleteWalkState (WalkState);
25528c506b8Sjruoho         goto Cleanup;
25628c506b8Sjruoho     }
25728c506b8Sjruoho 
258c72da027Schristos     /* Found OSDT table, enable the namespace override feature */
259c72da027Schristos 
26094783addSchristos     if (ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_OSDT) &&
261c72da027Schristos         PassNumber == ACPI_IMODE_LOAD_PASS1)
262c72da027Schristos     {
263c72da027Schristos         WalkState->NamespaceOverride = TRUE;
264c72da027Schristos     }
265c72da027Schristos 
26628c506b8Sjruoho     /* StartNode is the default location to load the table  */
26728c506b8Sjruoho 
26828c506b8Sjruoho     if (StartNode && StartNode != AcpiGbl_RootNode)
26928c506b8Sjruoho     {
27071e38f1dSchristos         Status = AcpiDsScopeStackPush (
27171e38f1dSchristos             StartNode, ACPI_TYPE_METHOD, WalkState);
27228c506b8Sjruoho         if (ACPI_FAILURE (Status))
27328c506b8Sjruoho         {
27428c506b8Sjruoho             AcpiDsDeleteWalkState (WalkState);
27528c506b8Sjruoho             goto Cleanup;
27628c506b8Sjruoho         }
27728c506b8Sjruoho     }
27828c506b8Sjruoho 
27928c506b8Sjruoho     /* Parse the AML */
28028c506b8Sjruoho 
28171e38f1dSchristos     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
28271e38f1dSchristos         "*PARSE* pass %u parse\n", PassNumber));
283d0e1da26Schristos     AcpiExEnterInterpreter ();
28428c506b8Sjruoho     Status = AcpiPsParseAml (WalkState);
285d0e1da26Schristos     AcpiExExitInterpreter ();
28628c506b8Sjruoho 
28728c506b8Sjruoho Cleanup:
28828c506b8Sjruoho     AcpiPsDeleteParseTree (ParseRoot);
28928c506b8Sjruoho     return_ACPI_STATUS (Status);
29028c506b8Sjruoho }
29128c506b8Sjruoho 
29228c506b8Sjruoho 
29328c506b8Sjruoho /*******************************************************************************
29428c506b8Sjruoho  *
29528c506b8Sjruoho  * FUNCTION:    AcpiNsParseTable
29628c506b8Sjruoho  *
29728c506b8Sjruoho  * PARAMETERS:  TableDesc       - An ACPI table descriptor for table to parse
29828c506b8Sjruoho  *              StartNode       - Where to enter the table into the namespace
29928c506b8Sjruoho  *
30028c506b8Sjruoho  * RETURN:      Status
30128c506b8Sjruoho  *
30228c506b8Sjruoho  * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
30328c506b8Sjruoho  *
30428c506b8Sjruoho  ******************************************************************************/
30528c506b8Sjruoho 
30628c506b8Sjruoho ACPI_STATUS
AcpiNsParseTable(UINT32 TableIndex,ACPI_NAMESPACE_NODE * StartNode)30728c506b8Sjruoho AcpiNsParseTable (
30828c506b8Sjruoho     UINT32                  TableIndex,
30928c506b8Sjruoho     ACPI_NAMESPACE_NODE     *StartNode)
31028c506b8Sjruoho {
31128c506b8Sjruoho     ACPI_STATUS             Status;
31228c506b8Sjruoho 
31328c506b8Sjruoho 
31428c506b8Sjruoho     ACPI_FUNCTION_TRACE (NsParseTable);
31528c506b8Sjruoho 
31628c506b8Sjruoho 
317062782b3Schristos     /*
31894783addSchristos      * Executes the AML table as one large control method.
319062782b3Schristos      * The point of this is to execute any module-level code in-place
320062782b3Schristos      * as the table is parsed. Some AML code depends on this behavior.
321062782b3Schristos      *
322062782b3Schristos      * Note: This causes the table to only have a single-pass parse.
323062782b3Schristos      * However, this is compatible with other ACPI implementations.
324062782b3Schristos      */
325062782b3Schristos     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
326062782b3Schristos         "%s: **** Start table execution pass\n", ACPI_GET_FUNCTION_NAME));
327d0e1da26Schristos 
328d0e1da26Schristos     Status = AcpiNsExecuteTable (TableIndex, StartNode);
32928c506b8Sjruoho 
33028c506b8Sjruoho     return_ACPI_STATUS (Status);
33128c506b8Sjruoho }
332