1 /******************************************************************************
2  *
3  * Module Name: nsparse - namespace interface to AML parser
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 "acparser.h"
48 #include "acdispat.h"
49 #include "actables.h"
50 #include "acinterp.h"
51 
52 
53 #define _COMPONENT          ACPI_NAMESPACE
54         ACPI_MODULE_NAME    ("nsparse")
55 
56 
57 /*******************************************************************************
58  *
59  * FUNCTION:    NsExecuteTable
60  *
61  * PARAMETERS:  TableDesc       - An ACPI table descriptor for table to parse
62  *              StartNode       - Where to enter the table into the namespace
63  *
64  * RETURN:      Status
65  *
66  * DESCRIPTION: Load ACPI/AML table by executing the entire table as a single
67  *              large control method.
68  *
69  * NOTE: The point of this is to execute any module-level code in-place
70  * as the table is parsed. Some AML code depends on this behavior.
71  *
72  * It is a run-time option at this time, but will eventually become
73  * the default.
74  *
75  * Note: This causes the table to only have a single-pass parse.
76  * However, this is compatible with other ACPI implementations.
77  *
78  ******************************************************************************/
79 
80 ACPI_STATUS
81 AcpiNsExecuteTable (
82     UINT32                  TableIndex,
83     ACPI_NAMESPACE_NODE     *StartNode)
84 {
85     ACPI_STATUS             Status;
86     ACPI_TABLE_HEADER       *Table;
87     ACPI_OWNER_ID           OwnerId;
88     ACPI_EVALUATE_INFO      *Info = NULL;
89     UINT32                  AmlLength;
90     UINT8                   *AmlStart;
91     ACPI_OPERAND_OBJECT     *MethodObj = NULL;
92 
93 
94     ACPI_FUNCTION_TRACE (NsExecuteTable);
95 
96 
97     Status = AcpiGetTableByIndex (TableIndex, &Table);
98     if (ACPI_FAILURE (Status))
99     {
100         return_ACPI_STATUS (Status);
101     }
102 
103     /* Table must consist of at least a complete header */
104 
105     if (Table->Length < sizeof (ACPI_TABLE_HEADER))
106     {
107         return_ACPI_STATUS (AE_BAD_HEADER);
108     }
109 
110     AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER);
111     AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
112 
113     Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
114     if (ACPI_FAILURE (Status))
115     {
116         return_ACPI_STATUS (Status);
117     }
118 
119     /* Create, initialize, and link a new temporary method object */
120 
121     MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
122     if (!MethodObj)
123     {
124         return_ACPI_STATUS (AE_NO_MEMORY);
125     }
126 
127     /* Allocate the evaluation information block */
128 
129     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
130     if (!Info)
131     {
132         Status = AE_NO_MEMORY;
133         goto Cleanup;
134     }
135 
136     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
137         "%s: Create table pseudo-method for [%4.4s] @%p, method %p\n",
138         ACPI_GET_FUNCTION_NAME, Table->Signature, Table, MethodObj));
139 
140     MethodObj->Method.AmlStart = AmlStart;
141     MethodObj->Method.AmlLength = AmlLength;
142     MethodObj->Method.OwnerId = OwnerId;
143     MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL;
144 
145     Info->PassNumber = ACPI_IMODE_EXECUTE;
146     Info->Node = StartNode;
147     Info->ObjDesc = MethodObj;
148     Info->NodeFlags = Info->Node->Flags;
149     Info->FullPathname = AcpiNsGetNormalizedPathname (Info->Node, TRUE);
150     if (!Info->FullPathname)
151     {
152         Status = AE_NO_MEMORY;
153         goto Cleanup;
154     }
155 
156     /* Optional object evaluation log */
157 
158     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION,
159         "%-26s:  (Definition Block level)\n", "Module-level evaluation"));
160 
161     Status = AcpiPsExecuteTable (Info);
162 
163     /* Optional object evaluation log */
164 
165     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION,
166         "%-26s:  (Definition Block level)\n", "Module-level complete"));
167 
168 Cleanup:
169     if (Info)
170     {
171         ACPI_FREE (Info->FullPathname);
172         Info->FullPathname = NULL;
173     }
174     ACPI_FREE (Info);
175     AcpiUtRemoveReference (MethodObj);
176     return_ACPI_STATUS (Status);
177 }
178 
179 
180 /*******************************************************************************
181  *
182  * FUNCTION:    NsOneCompleteParse
183  *
184  * PARAMETERS:  PassNumber              - 1 or 2
185  *              TableDesc               - The table to be parsed.
186  *
187  * RETURN:      Status
188  *
189  * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
190  *
191  ******************************************************************************/
192 
193 ACPI_STATUS
194 AcpiNsOneCompleteParse (
195     UINT32                  PassNumber,
196     UINT32                  TableIndex,
197     ACPI_NAMESPACE_NODE     *StartNode)
198 {
199     ACPI_PARSE_OBJECT       *ParseRoot;
200     ACPI_STATUS             Status;
201     UINT32                  AmlLength;
202     UINT8                   *AmlStart;
203     ACPI_WALK_STATE         *WalkState;
204     ACPI_TABLE_HEADER       *Table;
205     ACPI_OWNER_ID           OwnerId;
206 
207 
208     ACPI_FUNCTION_TRACE (NsOneCompleteParse);
209 
210 
211     Status = AcpiGetTableByIndex (TableIndex, &Table);
212     if (ACPI_FAILURE (Status))
213     {
214         return_ACPI_STATUS (Status);
215     }
216 
217     /* Table must consist of at least a complete header */
218 
219     if (Table->Length < sizeof (ACPI_TABLE_HEADER))
220     {
221         return_ACPI_STATUS (AE_BAD_HEADER);
222     }
223 
224     AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER);
225     AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
226 
227     Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
228     if (ACPI_FAILURE (Status))
229     {
230         return_ACPI_STATUS (Status);
231     }
232 
233     /* Create and init a Root Node */
234 
235     ParseRoot = AcpiPsCreateScopeOp (AmlStart);
236     if (!ParseRoot)
237     {
238         return_ACPI_STATUS (AE_NO_MEMORY);
239     }
240 
241     /* Create and initialize a new walk state */
242 
243     WalkState = AcpiDsCreateWalkState (OwnerId, NULL, NULL, NULL);
244     if (!WalkState)
245     {
246         AcpiPsFreeOp (ParseRoot);
247         return_ACPI_STATUS (AE_NO_MEMORY);
248     }
249 
250     Status = AcpiDsInitAmlWalk (WalkState, ParseRoot, NULL,
251         AmlStart, AmlLength, NULL, (UINT8) PassNumber);
252     if (ACPI_FAILURE (Status))
253     {
254         AcpiDsDeleteWalkState (WalkState);
255         goto Cleanup;
256     }
257 
258     /* Found OSDT table, enable the namespace override feature */
259 
260     if (ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_OSDT) &&
261         PassNumber == ACPI_IMODE_LOAD_PASS1)
262     {
263         WalkState->NamespaceOverride = TRUE;
264     }
265 
266     /* StartNode is the default location to load the table  */
267 
268     if (StartNode && StartNode != AcpiGbl_RootNode)
269     {
270         Status = AcpiDsScopeStackPush (
271             StartNode, ACPI_TYPE_METHOD, WalkState);
272         if (ACPI_FAILURE (Status))
273         {
274             AcpiDsDeleteWalkState (WalkState);
275             goto Cleanup;
276         }
277     }
278 
279     /* Parse the AML */
280 
281     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
282         "*PARSE* pass %u parse\n", PassNumber));
283     AcpiExEnterInterpreter ();
284     Status = AcpiPsParseAml (WalkState);
285     AcpiExExitInterpreter ();
286 
287 Cleanup:
288     AcpiPsDeleteParseTree (ParseRoot);
289     return_ACPI_STATUS (Status);
290 }
291 
292 
293 /*******************************************************************************
294  *
295  * FUNCTION:    AcpiNsParseTable
296  *
297  * PARAMETERS:  TableDesc       - An ACPI table descriptor for table to parse
298  *              StartNode       - Where to enter the table into the namespace
299  *
300  * RETURN:      Status
301  *
302  * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
303  *
304  ******************************************************************************/
305 
306 ACPI_STATUS
307 AcpiNsParseTable (
308     UINT32                  TableIndex,
309     ACPI_NAMESPACE_NODE     *StartNode)
310 {
311     ACPI_STATUS             Status;
312 
313 
314     ACPI_FUNCTION_TRACE (NsParseTable);
315 
316 
317     /*
318      * Executes the AML table as one large control method.
319      * The point of this is to execute any module-level code in-place
320      * as the table is parsed. Some AML code depends on this behavior.
321      *
322      * Note: This causes the table to only have a single-pass parse.
323      * However, this is compatible with other ACPI implementations.
324      */
325     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
326         "%s: **** Start table execution pass\n", ACPI_GET_FUNCTION_NAME));
327 
328     Status = AcpiNsExecuteTable (TableIndex, StartNode);
329 
330     return_ACPI_STATUS (Status);
331 }
332