542c9c9345216320e74e8c4533bf53752ab1d94c
[reactos.git] / drivers / bus / acpi / acpica / namespace / nsparse.c
1 /******************************************************************************
2 *
3 * Module Name: nsparse - namespace interface to AML parser
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2019, 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 /* 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_NAME(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 if (AcpiGbl_ExecuteTablesAsMethods)
318 {
319 /*
320 * This case executes the AML table as one large control method.
321 * The point of this is to execute any module-level code in-place
322 * as the table is parsed. Some AML code depends on this behavior.
323 *
324 * It is a run-time option at this time, but will eventually become
325 * the default.
326 *
327 * Note: This causes the table to only have a single-pass parse.
328 * However, this is compatible with other ACPI implementations.
329 */
330 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
331 "%s: **** Start table execution pass\n", ACPI_GET_FUNCTION_NAME));
332
333 Status = AcpiNsExecuteTable (TableIndex, StartNode);
334 if (ACPI_FAILURE (Status))
335 {
336 return_ACPI_STATUS (Status);
337 }
338 }
339 else
340 {
341 /*
342 * AML Parse, pass 1
343 *
344 * In this pass, we load most of the namespace. Control methods
345 * are not parsed until later. A parse tree is not created.
346 * Instead, each Parser Op subtree is deleted when it is finished.
347 * This saves a great deal of memory, and allows a small cache of
348 * parse objects to service the entire parse. The second pass of
349 * the parse then performs another complete parse of the AML.
350 */
351 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 1\n"));
352
353 Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS1,
354 TableIndex, StartNode);
355 if (ACPI_FAILURE (Status))
356 {
357 return_ACPI_STATUS (Status);
358 }
359
360 /*
361 * AML Parse, pass 2
362 *
363 * In this pass, we resolve forward references and other things
364 * that could not be completed during the first pass.
365 * Another complete parse of the AML is performed, but the
366 * overhead of this is compensated for by the fact that the
367 * parse objects are all cached.
368 */
369 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 2\n"));
370 Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2,
371 TableIndex, StartNode);
372 if (ACPI_FAILURE (Status))
373 {
374 return_ACPI_STATUS (Status);
375 }
376 }
377
378 return_ACPI_STATUS (Status);
379 }