1 /******************************************************************************
2  *
3  * Module Name: nsparse - namespace interface to AML parser
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2018, 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 "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     Status = AcpiPsExecuteTable (Info);
157 
158 Cleanup:
159     if (Info)
160     {
161         ACPI_FREE (Info->FullPathname);
162         Info->FullPathname = NULL;
163     }
164     ACPI_FREE (Info);
165     AcpiUtRemoveReference (MethodObj);
166     return_ACPI_STATUS (Status);
167 }
168 
169 
170 /*******************************************************************************
171  *
172  * FUNCTION:    NsOneCompleteParse
173  *
174  * PARAMETERS:  PassNumber              - 1 or 2
175  *              TableDesc               - The table to be parsed.
176  *
177  * RETURN:      Status
178  *
179  * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
180  *
181  ******************************************************************************/
182 
183 ACPI_STATUS
184 AcpiNsOneCompleteParse (
185     UINT32                  PassNumber,
186     UINT32                  TableIndex,
187     ACPI_NAMESPACE_NODE     *StartNode)
188 {
189     ACPI_PARSE_OBJECT       *ParseRoot;
190     ACPI_STATUS             Status;
191     UINT32                  AmlLength;
192     UINT8                   *AmlStart;
193     ACPI_WALK_STATE         *WalkState;
194     ACPI_TABLE_HEADER       *Table;
195     ACPI_OWNER_ID           OwnerId;
196 
197 
198     ACPI_FUNCTION_TRACE (NsOneCompleteParse);
199 
200 
201     Status = AcpiGetTableByIndex (TableIndex, &Table);
202     if (ACPI_FAILURE (Status))
203     {
204         return_ACPI_STATUS (Status);
205     }
206 
207     /* Table must consist of at least a complete header */
208 
209     if (Table->Length < sizeof (ACPI_TABLE_HEADER))
210     {
211         return_ACPI_STATUS (AE_BAD_HEADER);
212     }
213 
214     AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER);
215     AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
216 
217     Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
218     if (ACPI_FAILURE (Status))
219     {
220         return_ACPI_STATUS (Status);
221     }
222 
223     /* Create and init a Root Node */
224 
225     ParseRoot = AcpiPsCreateScopeOp (AmlStart);
226     if (!ParseRoot)
227     {
228         return_ACPI_STATUS (AE_NO_MEMORY);
229     }
230 
231     /* Create and initialize a new walk state */
232 
233     WalkState = AcpiDsCreateWalkState (OwnerId, NULL, NULL, NULL);
234     if (!WalkState)
235     {
236         AcpiPsFreeOp (ParseRoot);
237         return_ACPI_STATUS (AE_NO_MEMORY);
238     }
239 
240     Status = AcpiDsInitAmlWalk (WalkState, ParseRoot, NULL,
241         AmlStart, AmlLength, NULL, (UINT8) PassNumber);
242     if (ACPI_FAILURE (Status))
243     {
244         AcpiDsDeleteWalkState (WalkState);
245         goto Cleanup;
246     }
247 
248     /* Found OSDT table, enable the namespace override feature */
249 
250     if (ACPI_COMPARE_NAME(Table->Signature, ACPI_SIG_OSDT) &&
251         PassNumber == ACPI_IMODE_LOAD_PASS1)
252     {
253         WalkState->NamespaceOverride = TRUE;
254     }
255 
256     /* StartNode is the default location to load the table  */
257 
258     if (StartNode && StartNode != AcpiGbl_RootNode)
259     {
260         Status = AcpiDsScopeStackPush (
261             StartNode, ACPI_TYPE_METHOD, WalkState);
262         if (ACPI_FAILURE (Status))
263         {
264             AcpiDsDeleteWalkState (WalkState);
265             goto Cleanup;
266         }
267     }
268 
269     /* Parse the AML */
270 
271     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
272         "*PARSE* pass %u parse\n", PassNumber));
273     AcpiExEnterInterpreter ();
274     Status = AcpiPsParseAml (WalkState);
275     AcpiExExitInterpreter ();
276 
277 Cleanup:
278     AcpiPsDeleteParseTree (ParseRoot);
279     return_ACPI_STATUS (Status);
280 }
281 
282 
283 /*******************************************************************************
284  *
285  * FUNCTION:    AcpiNsParseTable
286  *
287  * PARAMETERS:  TableDesc       - An ACPI table descriptor for table to parse
288  *              StartNode       - Where to enter the table into the namespace
289  *
290  * RETURN:      Status
291  *
292  * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
293  *
294  ******************************************************************************/
295 
296 ACPI_STATUS
297 AcpiNsParseTable (
298     UINT32                  TableIndex,
299     ACPI_NAMESPACE_NODE     *StartNode)
300 {
301     ACPI_STATUS             Status;
302 
303 
304     ACPI_FUNCTION_TRACE (NsParseTable);
305 
306 
307     if (AcpiGbl_ExecuteTablesAsMethods)
308     {
309         /*
310          * This case executes the AML table as one large control method.
311          * The point of this is to execute any module-level code in-place
312          * as the table is parsed. Some AML code depends on this behavior.
313          *
314          * It is a run-time option at this time, but will eventually become
315          * the default.
316          *
317          * Note: This causes the table to only have a single-pass parse.
318          * However, this is compatible with other ACPI implementations.
319          */
320         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
321             "%s: **** Start table execution pass\n", ACPI_GET_FUNCTION_NAME));
322 
323         Status = AcpiNsExecuteTable (TableIndex, StartNode);
324         if (ACPI_FAILURE (Status))
325         {
326             return_ACPI_STATUS (Status);
327         }
328     }
329     else
330     {
331         /*
332          * AML Parse, pass 1
333          *
334          * In this pass, we load most of the namespace. Control methods
335          * are not parsed until later. A parse tree is not created.
336          * Instead, each Parser Op subtree is deleted when it is finished.
337          * This saves a great deal of memory, and allows a small cache of
338          * parse objects to service the entire parse. The second pass of
339          * the parse then performs another complete parse of the AML.
340          */
341         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 1\n"));
342 
343         Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS1,
344             TableIndex, StartNode);
345         if (ACPI_FAILURE (Status))
346         {
347             return_ACPI_STATUS (Status);
348         }
349 
350         /*
351          * AML Parse, pass 2
352          *
353          * In this pass, we resolve forward references and other things
354          * that could not be completed during the first pass.
355          * Another complete parse of the AML is performed, but the
356          * overhead of this is compensated for by the fact that the
357          * parse objects are all cached.
358          */
359         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 2\n"));
360         Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2,
361             TableIndex, StartNode);
362         if (ACPI_FAILURE (Status))
363         {
364             return_ACPI_STATUS (Status);
365         }
366     }
367 
368     return_ACPI_STATUS (Status);
369 }
370