Rev 1498 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1498 | serge | 1 | /****************************************************************************** |
2 | * |
||
3 | * Module Name: psloop - Main AML parse loop |
||
4 | * |
||
5 | *****************************************************************************/ |
||
6 | |||
7 | /****************************************************************************** |
||
8 | * |
||
9 | * 1. Copyright Notice |
||
10 | * |
||
2216 | Serge | 11 | * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
1498 | serge | 12 | * All rights reserved. |
13 | * |
||
14 | * 2. License |
||
15 | * |
||
16 | * 2.1. This is your license from Intel Corp. under its intellectual property |
||
17 | * rights. You may have additional license terms from the party that provided |
||
18 | * you this software, covering your right to use that party's intellectual |
||
19 | * property rights. |
||
20 | * |
||
21 | * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
||
22 | * copy of the source code appearing in this file ("Covered Code") an |
||
23 | * irrevocable, perpetual, worldwide license under Intel's copyrights in the |
||
24 | * base code distributed originally by Intel ("Original Intel Code") to copy, |
||
25 | * make derivatives, distribute, use and display any portion of the Covered |
||
26 | * Code in any form, with the right to sublicense such rights; and |
||
27 | * |
||
28 | * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
||
29 | * license (with the right to sublicense), under only those claims of Intel |
||
30 | * patents that are infringed by the Original Intel Code, to make, use, sell, |
||
31 | * offer to sell, and import the Covered Code and derivative works thereof |
||
32 | * solely to the minimum extent necessary to exercise the above copyright |
||
33 | * license, and in no event shall the patent license extend to any additions |
||
34 | * to or modifications of the Original Intel Code. No other license or right |
||
35 | * is granted directly or by implication, estoppel or otherwise; |
||
36 | * |
||
37 | * The above copyright and patent license is granted only if the following |
||
38 | * conditions are met: |
||
39 | * |
||
40 | * 3. Conditions |
||
41 | * |
||
42 | * 3.1. Redistribution of Source with Rights to Further Distribute Source. |
||
43 | * Redistribution of source code of any substantial portion of the Covered |
||
44 | * Code or modification with rights to further distribute source must include |
||
45 | * the above Copyright Notice, the above License, this list of Conditions, |
||
46 | * and the following Disclaimer and Export Compliance provision. In addition, |
||
47 | * Licensee must cause all Covered Code to which Licensee contributes to |
||
48 | * contain a file documenting the changes Licensee made to create that Covered |
||
49 | * Code and the date of any change. Licensee must include in that file the |
||
50 | * documentation of any changes made by any predecessor Licensee. Licensee |
||
51 | * must include a prominent statement that the modification is derived, |
||
52 | * directly or indirectly, from Original Intel Code. |
||
53 | * |
||
54 | * 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
||
55 | * Redistribution of source code of any substantial portion of the Covered |
||
56 | * Code or modification without rights to further distribute source must |
||
57 | * include the following Disclaimer and Export Compliance provision in the |
||
58 | * documentation and/or other materials provided with distribution. In |
||
59 | * addition, Licensee may not authorize further sublicense of source of any |
||
60 | * portion of the Covered Code, and must include terms to the effect that the |
||
61 | * license from Licensee to its licensee is limited to the intellectual |
||
62 | * property embodied in the software Licensee provides to its licensee, and |
||
63 | * not to intellectual property embodied in modifications its licensee may |
||
64 | * make. |
||
65 | * |
||
66 | * 3.3. Redistribution of Executable. Redistribution in executable form of any |
||
67 | * substantial portion of the Covered Code or modification must reproduce the |
||
68 | * above Copyright Notice, and the following Disclaimer and Export Compliance |
||
69 | * provision in the documentation and/or other materials provided with the |
||
70 | * distribution. |
||
71 | * |
||
72 | * 3.4. Intel retains all right, title, and interest in and to the Original |
||
73 | * Intel Code. |
||
74 | * |
||
75 | * 3.5. Neither the name Intel nor any other trademark owned or controlled by |
||
76 | * Intel shall be used in advertising or otherwise to promote the sale, use or |
||
77 | * other dealings in products derived from or relating to the Covered Code |
||
78 | * without prior written authorization from Intel. |
||
79 | * |
||
80 | * 4. Disclaimer and Export Compliance |
||
81 | * |
||
82 | * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
||
83 | * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
||
84 | * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
||
85 | * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
||
86 | * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
||
87 | * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
||
88 | * PARTICULAR PURPOSE. |
||
89 | * |
||
90 | * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
||
91 | * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
||
92 | * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
||
93 | * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
||
94 | * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
||
95 | * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
||
96 | * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
||
97 | * LIMITED REMEDY. |
||
98 | * |
||
99 | * 4.3. Licensee shall not export, either directly or indirectly, any of this |
||
100 | * software or system incorporating such software without first obtaining any |
||
101 | * required license or other approval from the U. S. Department of Commerce or |
||
102 | * any other agency or department of the United States Government. In the |
||
103 | * event Licensee exports any such software from the United States or |
||
104 | * re-exports any such software from a foreign destination, Licensee shall |
||
105 | * ensure that the distribution and export/re-export of the software is in |
||
106 | * compliance with all laws, regulations, orders, or other restrictions of the |
||
107 | * U.S. Export Administration Regulations. Licensee agrees that neither it nor |
||
108 | * any of its subsidiaries will export/re-export any technical data, process, |
||
109 | * software, or service, directly or indirectly, to any country for which the |
||
110 | * United States government or any agency thereof requires an export license, |
||
111 | * other governmental approval, or letter of assurance, without first obtaining |
||
112 | * such license, approval or letter. |
||
113 | * |
||
114 | *****************************************************************************/ |
||
115 | |||
116 | |||
117 | /* |
||
118 | * Parse the AML and build an operation tree as most interpreters, (such as |
||
119 | * Perl) do. Parsing is done by hand rather than with a YACC generated parser |
||
120 | * to tightly constrain stack and dynamic memory usage. Parsing is kept |
||
121 | * flexible and the code fairly compact by parsing based on a list of AML |
||
122 | * opcode templates in AmlOpInfo[]. |
||
123 | */ |
||
124 | |||
125 | #include "acpi.h" |
||
126 | #include "accommon.h" |
||
127 | #include "acparser.h" |
||
128 | #include "acdispat.h" |
||
129 | #include "amlcode.h" |
||
130 | |||
131 | #define _COMPONENT ACPI_PARSER |
||
132 | ACPI_MODULE_NAME ("psloop") |
||
133 | |||
134 | static UINT32 AcpiGbl_Depth = 0; |
||
135 | |||
136 | |||
137 | /* Local prototypes */ |
||
138 | |||
139 | static ACPI_STATUS |
||
140 | AcpiPsGetAmlOpcode ( |
||
141 | ACPI_WALK_STATE *WalkState); |
||
142 | |||
143 | static ACPI_STATUS |
||
144 | AcpiPsBuildNamedOp ( |
||
145 | ACPI_WALK_STATE *WalkState, |
||
146 | UINT8 *AmlOpStart, |
||
147 | ACPI_PARSE_OBJECT *UnnamedOp, |
||
148 | ACPI_PARSE_OBJECT **Op); |
||
149 | |||
150 | static ACPI_STATUS |
||
151 | AcpiPsCreateOp ( |
||
152 | ACPI_WALK_STATE *WalkState, |
||
153 | UINT8 *AmlOpStart, |
||
154 | ACPI_PARSE_OBJECT **NewOp); |
||
155 | |||
156 | static ACPI_STATUS |
||
157 | AcpiPsGetArguments ( |
||
158 | ACPI_WALK_STATE *WalkState, |
||
159 | UINT8 *AmlOpStart, |
||
160 | ACPI_PARSE_OBJECT *Op); |
||
161 | |||
162 | static ACPI_STATUS |
||
163 | AcpiPsCompleteOp ( |
||
164 | ACPI_WALK_STATE *WalkState, |
||
165 | ACPI_PARSE_OBJECT **Op, |
||
166 | ACPI_STATUS Status); |
||
167 | |||
168 | static ACPI_STATUS |
||
169 | AcpiPsCompleteFinalOp ( |
||
170 | ACPI_WALK_STATE *WalkState, |
||
171 | ACPI_PARSE_OBJECT *Op, |
||
172 | ACPI_STATUS Status); |
||
173 | |||
174 | static void |
||
175 | AcpiPsLinkModuleCode ( |
||
176 | ACPI_PARSE_OBJECT *ParentOp, |
||
177 | UINT8 *AmlStart, |
||
178 | UINT32 AmlLength, |
||
179 | ACPI_OWNER_ID OwnerId); |
||
180 | |||
181 | |||
182 | /******************************************************************************* |
||
183 | * |
||
184 | * FUNCTION: AcpiPsGetAmlOpcode |
||
185 | * |
||
186 | * PARAMETERS: WalkState - Current state |
||
187 | * |
||
188 | * RETURN: Status |
||
189 | * |
||
190 | * DESCRIPTION: Extract the next AML opcode from the input stream. |
||
191 | * |
||
192 | ******************************************************************************/ |
||
193 | |||
194 | static ACPI_STATUS |
||
195 | AcpiPsGetAmlOpcode ( |
||
196 | ACPI_WALK_STATE *WalkState) |
||
197 | { |
||
198 | |||
199 | ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState); |
||
200 | |||
201 | |||
202 | WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, |
||
203 | WalkState->ParserState.AmlStart); |
||
204 | WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState)); |
||
205 | |||
206 | /* |
||
207 | * First cut to determine what we have found: |
||
208 | * 1) A valid AML opcode |
||
209 | * 2) A name string |
||
210 | * 3) An unknown/invalid opcode |
||
211 | */ |
||
212 | WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); |
||
213 | |||
214 | switch (WalkState->OpInfo->Class) |
||
215 | { |
||
216 | case AML_CLASS_ASCII: |
||
217 | case AML_CLASS_PREFIX: |
||
218 | /* |
||
219 | * Starts with a valid prefix or ASCII char, this is a name |
||
220 | * string. Convert the bare name string to a namepath. |
||
221 | */ |
||
222 | WalkState->Opcode = AML_INT_NAMEPATH_OP; |
||
223 | WalkState->ArgTypes = ARGP_NAMESTRING; |
||
224 | break; |
||
225 | |||
226 | case AML_CLASS_UNKNOWN: |
||
227 | |||
228 | /* The opcode is unrecognized. Just skip unknown opcodes */ |
||
229 | |||
230 | ACPI_ERROR ((AE_INFO, |
||
231 | "Found unknown opcode 0x%X at AML address %p offset 0x%X, ignoring", |
||
232 | WalkState->Opcode, WalkState->ParserState.Aml, WalkState->AmlOffset)); |
||
233 | |||
234 | ACPI_DUMP_BUFFER (WalkState->ParserState.Aml, 128); |
||
235 | |||
236 | /* Assume one-byte bad opcode */ |
||
237 | |||
238 | WalkState->ParserState.Aml++; |
||
239 | return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); |
||
240 | |||
241 | default: |
||
242 | |||
243 | /* Found opcode info, this is a normal opcode */ |
||
244 | |||
245 | WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode); |
||
246 | WalkState->ArgTypes = WalkState->OpInfo->ParseArgs; |
||
247 | break; |
||
248 | } |
||
249 | |||
250 | return_ACPI_STATUS (AE_OK); |
||
251 | } |
||
252 | |||
253 | |||
254 | /******************************************************************************* |
||
255 | * |
||
256 | * FUNCTION: AcpiPsBuildNamedOp |
||
257 | * |
||
258 | * PARAMETERS: WalkState - Current state |
||
259 | * AmlOpStart - Begin of named Op in AML |
||
260 | * UnnamedOp - Early Op (not a named Op) |
||
261 | * Op - Returned Op |
||
262 | * |
||
263 | * RETURN: Status |
||
264 | * |
||
265 | * DESCRIPTION: Parse a named Op |
||
266 | * |
||
267 | ******************************************************************************/ |
||
268 | |||
269 | static ACPI_STATUS |
||
270 | AcpiPsBuildNamedOp ( |
||
271 | ACPI_WALK_STATE *WalkState, |
||
272 | UINT8 *AmlOpStart, |
||
273 | ACPI_PARSE_OBJECT *UnnamedOp, |
||
274 | ACPI_PARSE_OBJECT **Op) |
||
275 | { |
||
276 | ACPI_STATUS Status = AE_OK; |
||
277 | ACPI_PARSE_OBJECT *Arg = NULL; |
||
278 | |||
279 | |||
280 | ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState); |
||
281 | |||
282 | |||
283 | UnnamedOp->Common.Value.Arg = NULL; |
||
284 | UnnamedOp->Common.ArgListLength = 0; |
||
285 | UnnamedOp->Common.AmlOpcode = WalkState->Opcode; |
||
286 | |||
287 | /* |
||
288 | * Get and append arguments until we find the node that contains |
||
289 | * the name (the type ARGP_NAME). |
||
290 | */ |
||
291 | while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && |
||
292 | (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME)) |
||
293 | { |
||
294 | Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), |
||
295 | GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); |
||
296 | if (ACPI_FAILURE (Status)) |
||
297 | { |
||
298 | return_ACPI_STATUS (Status); |
||
299 | } |
||
300 | |||
301 | AcpiPsAppendArg (UnnamedOp, Arg); |
||
302 | INCREMENT_ARG_LIST (WalkState->ArgTypes); |
||
303 | } |
||
304 | |||
305 | /* |
||
306 | * Make sure that we found a NAME and didn't run out of arguments |
||
307 | */ |
||
308 | if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes)) |
||
309 | { |
||
310 | return_ACPI_STATUS (AE_AML_NO_OPERAND); |
||
311 | } |
||
312 | |||
313 | /* We know that this arg is a name, move to next arg */ |
||
314 | |||
315 | INCREMENT_ARG_LIST (WalkState->ArgTypes); |
||
316 | |||
317 | /* |
||
318 | * Find the object. This will either insert the object into |
||
319 | * the namespace or simply look it up |
||
320 | */ |
||
321 | WalkState->Op = NULL; |
||
322 | |||
323 | Status = WalkState->DescendingCallback (WalkState, Op); |
||
324 | if (ACPI_FAILURE (Status)) |
||
325 | { |
||
326 | ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog")); |
||
327 | return_ACPI_STATUS (Status); |
||
328 | } |
||
329 | |||
330 | if (!*Op) |
||
331 | { |
||
332 | return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); |
||
333 | } |
||
334 | |||
335 | Status = AcpiPsNextParseState (WalkState, *Op, Status); |
||
336 | if (ACPI_FAILURE (Status)) |
||
337 | { |
||
338 | if (Status == AE_CTRL_PENDING) |
||
339 | { |
||
340 | return_ACPI_STATUS (AE_CTRL_PARSE_PENDING); |
||
341 | } |
||
342 | return_ACPI_STATUS (Status); |
||
343 | } |
||
344 | |||
345 | AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg); |
||
346 | AcpiGbl_Depth++; |
||
347 | |||
348 | if ((*Op)->Common.AmlOpcode == AML_REGION_OP || |
||
349 | (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP) |
||
350 | { |
||
351 | /* |
||
352 | * Defer final parsing of an OperationRegion body, because we don't |
||
353 | * have enough info in the first pass to parse it correctly (i.e., |
||
354 | * there may be method calls within the TermArg elements of the body.) |
||
355 | * |
||
356 | * However, we must continue parsing because the opregion is not a |
||
357 | * standalone package -- we don't know where the end is at this point. |
||
358 | * |
||
359 | * (Length is unknown until parse of the body complete) |
||
360 | */ |
||
361 | (*Op)->Named.Data = AmlOpStart; |
||
362 | (*Op)->Named.Length = 0; |
||
363 | } |
||
364 | |||
365 | return_ACPI_STATUS (AE_OK); |
||
366 | } |
||
367 | |||
368 | |||
369 | /******************************************************************************* |
||
370 | * |
||
371 | * FUNCTION: AcpiPsCreateOp |
||
372 | * |
||
373 | * PARAMETERS: WalkState - Current state |
||
374 | * AmlOpStart - Op start in AML |
||
375 | * NewOp - Returned Op |
||
376 | * |
||
377 | * RETURN: Status |
||
378 | * |
||
379 | * DESCRIPTION: Get Op from AML |
||
380 | * |
||
381 | ******************************************************************************/ |
||
382 | |||
383 | static ACPI_STATUS |
||
384 | AcpiPsCreateOp ( |
||
385 | ACPI_WALK_STATE *WalkState, |
||
386 | UINT8 *AmlOpStart, |
||
387 | ACPI_PARSE_OBJECT **NewOp) |
||
388 | { |
||
389 | ACPI_STATUS Status = AE_OK; |
||
390 | ACPI_PARSE_OBJECT *Op; |
||
391 | ACPI_PARSE_OBJECT *NamedOp = NULL; |
||
392 | ACPI_PARSE_OBJECT *ParentScope; |
||
393 | UINT8 ArgumentCount; |
||
394 | const ACPI_OPCODE_INFO *OpInfo; |
||
395 | |||
396 | |||
397 | ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState); |
||
398 | |||
399 | |||
400 | Status = AcpiPsGetAmlOpcode (WalkState); |
||
401 | if (Status == AE_CTRL_PARSE_CONTINUE) |
||
402 | { |
||
403 | return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); |
||
404 | } |
||
405 | |||
406 | /* Create Op structure and append to parent's argument list */ |
||
407 | |||
408 | WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); |
||
409 | Op = AcpiPsAllocOp (WalkState->Opcode); |
||
410 | if (!Op) |
||
411 | { |
||
412 | return_ACPI_STATUS (AE_NO_MEMORY); |
||
413 | } |
||
414 | |||
415 | if (WalkState->OpInfo->Flags & AML_NAMED) |
||
416 | { |
||
417 | Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp); |
||
418 | AcpiPsFreeOp (Op); |
||
419 | if (ACPI_FAILURE (Status)) |
||
420 | { |
||
421 | return_ACPI_STATUS (Status); |
||
422 | } |
||
423 | |||
424 | *NewOp = NamedOp; |
||
425 | return_ACPI_STATUS (AE_OK); |
||
426 | } |
||
427 | |||
428 | /* Not a named opcode, just allocate Op and append to parent */ |
||
429 | |||
430 | if (WalkState->OpInfo->Flags & AML_CREATE) |
||
431 | { |
||
432 | /* |
||
433 | * Backup to beginning of CreateXXXfield declaration |
||
434 | * BodyLength is unknown until we parse the body |
||
435 | */ |
||
436 | Op->Named.Data = AmlOpStart; |
||
437 | Op->Named.Length = 0; |
||
438 | } |
||
439 | |||
440 | if (WalkState->Opcode == AML_BANK_FIELD_OP) |
||
441 | { |
||
442 | /* |
||
443 | * Backup to beginning of BankField declaration |
||
444 | * BodyLength is unknown until we parse the body |
||
445 | */ |
||
446 | Op->Named.Data = AmlOpStart; |
||
447 | Op->Named.Length = 0; |
||
448 | } |
||
449 | |||
450 | ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState)); |
||
451 | AcpiPsAppendArg (ParentScope, Op); |
||
452 | |||
453 | if (ParentScope) |
||
454 | { |
||
455 | OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode); |
||
456 | if (OpInfo->Flags & AML_HAS_TARGET) |
||
457 | { |
||
458 | ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type); |
||
459 | if (ParentScope->Common.ArgListLength > ArgumentCount) |
||
460 | { |
||
461 | Op->Common.Flags |= ACPI_PARSEOP_TARGET; |
||
462 | } |
||
463 | } |
||
464 | else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP) |
||
465 | { |
||
466 | Op->Common.Flags |= ACPI_PARSEOP_TARGET; |
||
467 | } |
||
468 | } |
||
469 | |||
470 | if (WalkState->DescendingCallback != NULL) |
||
471 | { |
||
472 | /* |
||
473 | * Find the object. This will either insert the object into |
||
474 | * the namespace or simply look it up |
||
475 | */ |
||
476 | WalkState->Op = *NewOp = Op; |
||
477 | |||
478 | Status = WalkState->DescendingCallback (WalkState, &Op); |
||
479 | Status = AcpiPsNextParseState (WalkState, Op, Status); |
||
480 | if (Status == AE_CTRL_PENDING) |
||
481 | { |
||
482 | Status = AE_CTRL_PARSE_PENDING; |
||
483 | } |
||
484 | } |
||
485 | |||
486 | return_ACPI_STATUS (Status); |
||
487 | } |
||
488 | |||
489 | |||
490 | /******************************************************************************* |
||
491 | * |
||
492 | * FUNCTION: AcpiPsGetArguments |
||
493 | * |
||
494 | * PARAMETERS: WalkState - Current state |
||
495 | * AmlOpStart - Op start in AML |
||
496 | * Op - Current Op |
||
497 | * |
||
498 | * RETURN: Status |
||
499 | * |
||
500 | * DESCRIPTION: Get arguments for passed Op. |
||
501 | * |
||
502 | ******************************************************************************/ |
||
503 | |||
504 | static ACPI_STATUS |
||
505 | AcpiPsGetArguments ( |
||
506 | ACPI_WALK_STATE *WalkState, |
||
507 | UINT8 *AmlOpStart, |
||
508 | ACPI_PARSE_OBJECT *Op) |
||
509 | { |
||
510 | ACPI_STATUS Status = AE_OK; |
||
511 | ACPI_PARSE_OBJECT *Arg = NULL; |
||
512 | const ACPI_OPCODE_INFO *OpInfo; |
||
513 | |||
514 | |||
515 | ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState); |
||
516 | |||
517 | |||
518 | switch (Op->Common.AmlOpcode) |
||
519 | { |
||
520 | case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ |
||
521 | case AML_WORD_OP: /* AML_WORDDATA_ARG */ |
||
522 | case AML_DWORD_OP: /* AML_DWORDATA_ARG */ |
||
523 | case AML_QWORD_OP: /* AML_QWORDATA_ARG */ |
||
524 | case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ |
||
525 | |||
526 | /* Fill in constant or string argument directly */ |
||
527 | |||
528 | AcpiPsGetNextSimpleArg (&(WalkState->ParserState), |
||
529 | GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op); |
||
530 | break; |
||
531 | |||
532 | case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ |
||
533 | |||
534 | Status = AcpiPsGetNextNamepath (WalkState, &(WalkState->ParserState), Op, 1); |
||
535 | if (ACPI_FAILURE (Status)) |
||
536 | { |
||
537 | return_ACPI_STATUS (Status); |
||
538 | } |
||
539 | |||
540 | WalkState->ArgTypes = 0; |
||
541 | break; |
||
542 | |||
543 | default: |
||
544 | /* |
||
545 | * Op is not a constant or string, append each argument to the Op |
||
546 | */ |
||
547 | while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount) |
||
548 | { |
||
549 | WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, |
||
550 | WalkState->ParserState.AmlStart); |
||
551 | |||
552 | Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), |
||
553 | GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); |
||
554 | if (ACPI_FAILURE (Status)) |
||
555 | { |
||
556 | return_ACPI_STATUS (Status); |
||
557 | } |
||
558 | |||
559 | if (Arg) |
||
560 | { |
||
561 | Arg->Common.AmlOffset = WalkState->AmlOffset; |
||
562 | AcpiPsAppendArg (Op, Arg); |
||
563 | } |
||
564 | |||
565 | INCREMENT_ARG_LIST (WalkState->ArgTypes); |
||
566 | } |
||
567 | |||
568 | |||
569 | /* |
||
570 | * Handle executable code at "module-level". This refers to |
||
571 | * executable opcodes that appear outside of any control method. |
||
572 | */ |
||
573 | if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2) && |
||
574 | ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0)) |
||
575 | { |
||
576 | /* |
||
577 | * We want to skip If/Else/While constructs during Pass1 because we |
||
578 | * want to actually conditionally execute the code during Pass2. |
||
579 | * |
||
580 | * Except for disassembly, where we always want to walk the |
||
581 | * If/Else/While packages |
||
582 | */ |
||
583 | switch (Op->Common.AmlOpcode) |
||
584 | { |
||
585 | case AML_IF_OP: |
||
586 | case AML_ELSE_OP: |
||
587 | case AML_WHILE_OP: |
||
588 | |||
589 | /* |
||
590 | * Currently supported module-level opcodes are: |
||
591 | * IF/ELSE/WHILE. These appear to be the most common, |
||
592 | * and easiest to support since they open an AML |
||
593 | * package. |
||
594 | */ |
||
595 | if (WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) |
||
596 | { |
||
597 | AcpiPsLinkModuleCode (Op->Common.Parent, AmlOpStart, |
||
598 | (UINT32) (WalkState->ParserState.PkgEnd - AmlOpStart), |
||
599 | WalkState->OwnerId); |
||
600 | } |
||
601 | |||
602 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, |
||
603 | "Pass1: Skipping an If/Else/While body\n")); |
||
604 | |||
605 | /* Skip body of if/else/while in pass 1 */ |
||
606 | |||
607 | WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; |
||
608 | WalkState->ArgCount = 0; |
||
609 | break; |
||
610 | |||
611 | default: |
||
612 | /* |
||
613 | * Check for an unsupported executable opcode at module |
||
614 | * level. We must be in PASS1, the parent must be a SCOPE, |
||
615 | * The opcode class must be EXECUTE, and the opcode must |
||
616 | * not be an argument to another opcode. |
||
617 | */ |
||
618 | if ((WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) && |
||
619 | (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP)) |
||
620 | { |
||
621 | OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); |
||
622 | if ((OpInfo->Class == AML_CLASS_EXECUTE) && |
||
623 | (!Arg)) |
||
624 | { |
||
625 | ACPI_WARNING ((AE_INFO, |
||
626 | "Detected an unsupported executable opcode " |
||
627 | "at module-level: [0x%.4X] at table offset 0x%.4X", |
||
628 | Op->Common.AmlOpcode, |
||
629 | (UINT32) (ACPI_PTR_DIFF (AmlOpStart, |
||
630 | WalkState->ParserState.AmlStart) + |
||
631 | sizeof (ACPI_TABLE_HEADER)))); |
||
632 | } |
||
633 | } |
||
634 | break; |
||
635 | } |
||
636 | } |
||
637 | |||
638 | /* Special processing for certain opcodes */ |
||
639 | |||
640 | switch (Op->Common.AmlOpcode) |
||
641 | { |
||
642 | case AML_METHOD_OP: |
||
643 | /* |
||
644 | * Skip parsing of control method because we don't have enough |
||
645 | * info in the first pass to parse it correctly. |
||
646 | * |
||
647 | * Save the length and address of the body |
||
648 | */ |
||
649 | Op->Named.Data = WalkState->ParserState.Aml; |
||
650 | Op->Named.Length = (UINT32) |
||
651 | (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml); |
||
652 | |||
653 | /* Skip body of method */ |
||
654 | |||
655 | WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; |
||
656 | WalkState->ArgCount = 0; |
||
657 | break; |
||
658 | |||
659 | case AML_BUFFER_OP: |
||
660 | case AML_PACKAGE_OP: |
||
661 | case AML_VAR_PACKAGE_OP: |
||
662 | |||
663 | if ((Op->Common.Parent) && |
||
664 | (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) && |
||
665 | (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2)) |
||
666 | { |
||
667 | /* |
||
668 | * Skip parsing of Buffers and Packages because we don't have |
||
669 | * enough info in the first pass to parse them correctly. |
||
670 | */ |
||
671 | Op->Named.Data = AmlOpStart; |
||
672 | Op->Named.Length = (UINT32) |
||
673 | (WalkState->ParserState.PkgEnd - AmlOpStart); |
||
674 | |||
675 | /* Skip body */ |
||
676 | |||
677 | WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; |
||
678 | WalkState->ArgCount = 0; |
||
679 | } |
||
680 | break; |
||
681 | |||
682 | case AML_WHILE_OP: |
||
683 | |||
684 | if (WalkState->ControlState) |
||
685 | { |
||
686 | WalkState->ControlState->Control.PackageEnd = |
||
687 | WalkState->ParserState.PkgEnd; |
||
688 | } |
||
689 | break; |
||
690 | |||
691 | default: |
||
692 | |||
693 | /* No action for all other opcodes */ |
||
694 | break; |
||
695 | } |
||
696 | |||
697 | break; |
||
698 | } |
||
699 | |||
700 | return_ACPI_STATUS (AE_OK); |
||
701 | } |
||
702 | |||
703 | |||
704 | /******************************************************************************* |
||
705 | * |
||
706 | * FUNCTION: AcpiPsLinkModuleCode |
||
707 | * |
||
708 | * PARAMETERS: ParentOp - Parent parser op |
||
709 | * AmlStart - Pointer to the AML |
||
710 | * AmlLength - Length of executable AML |
||
711 | * OwnerId - OwnerId of module level code |
||
712 | * |
||
713 | * RETURN: None. |
||
714 | * |
||
715 | * DESCRIPTION: Wrap the module-level code with a method object and link the |
||
716 | * object to the global list. Note, the mutex field of the method |
||
717 | * object is used to link multiple module-level code objects. |
||
718 | * |
||
719 | ******************************************************************************/ |
||
720 | |||
721 | static void |
||
722 | AcpiPsLinkModuleCode ( |
||
723 | ACPI_PARSE_OBJECT *ParentOp, |
||
724 | UINT8 *AmlStart, |
||
725 | UINT32 AmlLength, |
||
726 | ACPI_OWNER_ID OwnerId) |
||
727 | { |
||
728 | ACPI_OPERAND_OBJECT *Prev; |
||
729 | ACPI_OPERAND_OBJECT *Next; |
||
730 | ACPI_OPERAND_OBJECT *MethodObj; |
||
731 | ACPI_NAMESPACE_NODE *ParentNode; |
||
732 | |||
733 | |||
734 | /* Get the tail of the list */ |
||
735 | |||
736 | Prev = Next = AcpiGbl_ModuleCodeList; |
||
737 | while (Next) |
||
738 | { |
||
739 | Prev = Next; |
||
740 | Next = Next->Method.Mutex; |
||
741 | } |
||
742 | |||
743 | /* |
||
744 | * Insert the module level code into the list. Merge it if it is |
||
745 | * adjacent to the previous element. |
||
746 | */ |
||
747 | if (!Prev || |
||
748 | ((Prev->Method.AmlStart + Prev->Method.AmlLength) != AmlStart)) |
||
749 | { |
||
750 | /* Create, initialize, and link a new temporary method object */ |
||
751 | |||
752 | MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); |
||
753 | if (!MethodObj) |
||
754 | { |
||
755 | return; |
||
756 | } |
||
757 | |||
758 | if (ParentOp->Common.Node) |
||
759 | { |
||
760 | ParentNode = ParentOp->Common.Node; |
||
761 | } |
||
762 | else |
||
763 | { |
||
764 | ParentNode = AcpiGbl_RootNode; |
||
765 | } |
||
766 | |||
767 | MethodObj->Method.AmlStart = AmlStart; |
||
768 | MethodObj->Method.AmlLength = AmlLength; |
||
769 | MethodObj->Method.OwnerId = OwnerId; |
||
2216 | Serge | 770 | MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL; |
1498 | serge | 771 | |
772 | /* |
||
773 | * Save the parent node in NextObject. This is cheating, but we |
||
774 | * don't want to expand the method object. |
||
775 | */ |
||
776 | MethodObj->Method.NextObject = |
||
777 | ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParentNode); |
||
778 | |||
779 | if (!Prev) |
||
780 | { |
||
781 | AcpiGbl_ModuleCodeList = MethodObj; |
||
782 | } |
||
783 | else |
||
784 | { |
||
785 | Prev->Method.Mutex = MethodObj; |
||
786 | } |
||
787 | } |
||
788 | else |
||
789 | { |
||
790 | Prev->Method.AmlLength += AmlLength; |
||
791 | } |
||
792 | } |
||
793 | |||
794 | |||
795 | /******************************************************************************* |
||
796 | * |
||
797 | * FUNCTION: AcpiPsCompleteOp |
||
798 | * |
||
799 | * PARAMETERS: WalkState - Current state |
||
800 | * Op - Returned Op |
||
801 | * Status - Parse status before complete Op |
||
802 | * |
||
803 | * RETURN: Status |
||
804 | * |
||
805 | * DESCRIPTION: Complete Op |
||
806 | * |
||
807 | ******************************************************************************/ |
||
808 | |||
809 | static ACPI_STATUS |
||
810 | AcpiPsCompleteOp ( |
||
811 | ACPI_WALK_STATE *WalkState, |
||
812 | ACPI_PARSE_OBJECT **Op, |
||
813 | ACPI_STATUS Status) |
||
814 | { |
||
815 | ACPI_STATUS Status2; |
||
816 | |||
817 | |||
818 | ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState); |
||
819 | |||
820 | |||
821 | /* |
||
822 | * Finished one argument of the containing scope |
||
823 | */ |
||
824 | WalkState->ParserState.Scope->ParseScope.ArgCount--; |
||
825 | |||
826 | /* Close this Op (will result in parse subtree deletion) */ |
||
827 | |||
828 | Status2 = AcpiPsCompleteThisOp (WalkState, *Op); |
||
829 | if (ACPI_FAILURE (Status2)) |
||
830 | { |
||
831 | return_ACPI_STATUS (Status2); |
||
832 | } |
||
833 | |||
834 | *Op = NULL; |
||
835 | |||
836 | switch (Status) |
||
837 | { |
||
838 | case AE_OK: |
||
839 | break; |
||
840 | |||
841 | |||
842 | case AE_CTRL_TRANSFER: |
||
843 | |||
844 | /* We are about to transfer to a called method */ |
||
845 | |||
846 | WalkState->PrevOp = NULL; |
||
847 | WalkState->PrevArgTypes = WalkState->ArgTypes; |
||
848 | return_ACPI_STATUS (Status); |
||
849 | |||
850 | |||
851 | case AE_CTRL_END: |
||
852 | |||
853 | AcpiPsPopScope (&(WalkState->ParserState), Op, |
||
854 | &WalkState->ArgTypes, &WalkState->ArgCount); |
||
855 | |||
856 | if (*Op) |
||
857 | { |
||
858 | WalkState->Op = *Op; |
||
859 | WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); |
||
860 | WalkState->Opcode = (*Op)->Common.AmlOpcode; |
||
861 | |||
862 | Status = WalkState->AscendingCallback (WalkState); |
||
863 | Status = AcpiPsNextParseState (WalkState, *Op, Status); |
||
864 | |||
865 | Status2 = AcpiPsCompleteThisOp (WalkState, *Op); |
||
866 | if (ACPI_FAILURE (Status2)) |
||
867 | { |
||
868 | return_ACPI_STATUS (Status2); |
||
869 | } |
||
870 | } |
||
871 | |||
872 | Status = AE_OK; |
||
873 | break; |
||
874 | |||
875 | |||
876 | case AE_CTRL_BREAK: |
||
877 | case AE_CTRL_CONTINUE: |
||
878 | |||
879 | /* Pop off scopes until we find the While */ |
||
880 | |||
881 | while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP)) |
||
882 | { |
||
883 | AcpiPsPopScope (&(WalkState->ParserState), Op, |
||
884 | &WalkState->ArgTypes, &WalkState->ArgCount); |
||
885 | } |
||
886 | |||
887 | /* Close this iteration of the While loop */ |
||
888 | |||
889 | WalkState->Op = *Op; |
||
890 | WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); |
||
891 | WalkState->Opcode = (*Op)->Common.AmlOpcode; |
||
892 | |||
893 | Status = WalkState->AscendingCallback (WalkState); |
||
894 | Status = AcpiPsNextParseState (WalkState, *Op, Status); |
||
895 | |||
896 | Status2 = AcpiPsCompleteThisOp (WalkState, *Op); |
||
897 | if (ACPI_FAILURE (Status2)) |
||
898 | { |
||
899 | return_ACPI_STATUS (Status2); |
||
900 | } |
||
901 | |||
902 | Status = AE_OK; |
||
903 | break; |
||
904 | |||
905 | |||
906 | case AE_CTRL_TERMINATE: |
||
907 | |||
908 | /* Clean up */ |
||
909 | do |
||
910 | { |
||
911 | if (*Op) |
||
912 | { |
||
913 | Status2 = AcpiPsCompleteThisOp (WalkState, *Op); |
||
914 | if (ACPI_FAILURE (Status2)) |
||
915 | { |
||
916 | return_ACPI_STATUS (Status2); |
||
917 | } |
||
918 | |||
919 | AcpiUtDeleteGenericState ( |
||
920 | AcpiUtPopGenericState (&WalkState->ControlState)); |
||
921 | } |
||
922 | |||
923 | AcpiPsPopScope (&(WalkState->ParserState), Op, |
||
924 | &WalkState->ArgTypes, &WalkState->ArgCount); |
||
925 | |||
926 | } while (*Op); |
||
927 | |||
928 | return_ACPI_STATUS (AE_OK); |
||
929 | |||
930 | |||
931 | default: /* All other non-AE_OK status */ |
||
932 | |||
933 | do |
||
934 | { |
||
935 | if (*Op) |
||
936 | { |
||
937 | Status2 = AcpiPsCompleteThisOp (WalkState, *Op); |
||
938 | if (ACPI_FAILURE (Status2)) |
||
939 | { |
||
940 | return_ACPI_STATUS (Status2); |
||
941 | } |
||
942 | } |
||
943 | |||
944 | AcpiPsPopScope (&(WalkState->ParserState), Op, |
||
945 | &WalkState->ArgTypes, &WalkState->ArgCount); |
||
946 | |||
947 | } while (*Op); |
||
948 | |||
949 | |||
950 | #if 0 |
||
951 | /* |
||
952 | * TBD: Cleanup parse ops on error |
||
953 | */ |
||
954 | if (*Op == NULL) |
||
955 | { |
||
956 | AcpiPsPopScope (ParserState, Op, |
||
957 | &WalkState->ArgTypes, &WalkState->ArgCount); |
||
958 | } |
||
959 | #endif |
||
960 | WalkState->PrevOp = NULL; |
||
961 | WalkState->PrevArgTypes = WalkState->ArgTypes; |
||
962 | return_ACPI_STATUS (Status); |
||
963 | } |
||
964 | |||
965 | /* This scope complete? */ |
||
966 | |||
967 | if (AcpiPsHasCompletedScope (&(WalkState->ParserState))) |
||
968 | { |
||
969 | AcpiPsPopScope (&(WalkState->ParserState), Op, |
||
970 | &WalkState->ArgTypes, &WalkState->ArgCount); |
||
971 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op)); |
||
972 | } |
||
973 | else |
||
974 | { |
||
975 | *Op = NULL; |
||
976 | } |
||
977 | |||
978 | return_ACPI_STATUS (AE_OK); |
||
979 | } |
||
980 | |||
981 | |||
982 | /******************************************************************************* |
||
983 | * |
||
984 | * FUNCTION: AcpiPsCompleteFinalOp |
||
985 | * |
||
986 | * PARAMETERS: WalkState - Current state |
||
987 | * Op - Current Op |
||
988 | * Status - Current parse status before complete last |
||
989 | * Op |
||
990 | * |
||
991 | * RETURN: Status |
||
992 | * |
||
993 | * DESCRIPTION: Complete last Op. |
||
994 | * |
||
995 | ******************************************************************************/ |
||
996 | |||
997 | static ACPI_STATUS |
||
998 | AcpiPsCompleteFinalOp ( |
||
999 | ACPI_WALK_STATE *WalkState, |
||
1000 | ACPI_PARSE_OBJECT *Op, |
||
1001 | ACPI_STATUS Status) |
||
1002 | { |
||
1003 | ACPI_STATUS Status2; |
||
1004 | |||
1005 | |||
1006 | ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState); |
||
1007 | |||
1008 | |||
1009 | /* |
||
1010 | * Complete the last Op (if not completed), and clear the scope stack. |
||
1011 | * It is easily possible to end an AML "package" with an unbounded number |
||
1012 | * of open scopes (such as when several ASL blocks are closed with |
||
1013 | * sequential closing braces). We want to terminate each one cleanly. |
||
1014 | */ |
||
1015 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op)); |
||
1016 | do |
||
1017 | { |
||
1018 | if (Op) |
||
1019 | { |
||
1020 | if (WalkState->AscendingCallback != NULL) |
||
1021 | { |
||
1022 | WalkState->Op = Op; |
||
1023 | WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); |
||
1024 | WalkState->Opcode = Op->Common.AmlOpcode; |
||
1025 | |||
1026 | Status = WalkState->AscendingCallback (WalkState); |
||
1027 | Status = AcpiPsNextParseState (WalkState, Op, Status); |
||
1028 | if (Status == AE_CTRL_PENDING) |
||
1029 | { |
||
1030 | Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK); |
||
1031 | if (ACPI_FAILURE (Status)) |
||
1032 | { |
||
1033 | return_ACPI_STATUS (Status); |
||
1034 | } |
||
1035 | } |
||
1036 | |||
1037 | if (Status == AE_CTRL_TERMINATE) |
||
1038 | { |
||
1039 | Status = AE_OK; |
||
1040 | |||
1041 | /* Clean up */ |
||
1042 | do |
||
1043 | { |
||
1044 | if (Op) |
||
1045 | { |
||
1046 | Status2 = AcpiPsCompleteThisOp (WalkState, Op); |
||
1047 | if (ACPI_FAILURE (Status2)) |
||
1048 | { |
||
1049 | return_ACPI_STATUS (Status2); |
||
1050 | } |
||
1051 | } |
||
1052 | |||
1053 | AcpiPsPopScope (&(WalkState->ParserState), &Op, |
||
1054 | &WalkState->ArgTypes, &WalkState->ArgCount); |
||
1055 | |||
1056 | } while (Op); |
||
1057 | |||
1058 | return_ACPI_STATUS (Status); |
||
1059 | } |
||
1060 | |||
1061 | else if (ACPI_FAILURE (Status)) |
||
1062 | { |
||
1063 | /* First error is most important */ |
||
1064 | |||
1065 | (void) AcpiPsCompleteThisOp (WalkState, Op); |
||
1066 | return_ACPI_STATUS (Status); |
||
1067 | } |
||
1068 | } |
||
1069 | |||
1070 | Status2 = AcpiPsCompleteThisOp (WalkState, Op); |
||
1071 | if (ACPI_FAILURE (Status2)) |
||
1072 | { |
||
1073 | return_ACPI_STATUS (Status2); |
||
1074 | } |
||
1075 | } |
||
1076 | |||
1077 | AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes, |
||
1078 | &WalkState->ArgCount); |
||
1079 | |||
1080 | } while (Op); |
||
1081 | |||
1082 | return_ACPI_STATUS (Status); |
||
1083 | } |
||
1084 | |||
1085 | |||
1086 | /******************************************************************************* |
||
1087 | * |
||
1088 | * FUNCTION: AcpiPsParseLoop |
||
1089 | * |
||
1090 | * PARAMETERS: WalkState - Current state |
||
1091 | * |
||
1092 | * RETURN: Status |
||
1093 | * |
||
1094 | * DESCRIPTION: Parse AML (pointed to by the current parser state) and return |
||
1095 | * a tree of ops. |
||
1096 | * |
||
1097 | ******************************************************************************/ |
||
1098 | |||
1099 | ACPI_STATUS |
||
1100 | AcpiPsParseLoop ( |
||
1101 | ACPI_WALK_STATE *WalkState) |
||
1102 | { |
||
1103 | ACPI_STATUS Status = AE_OK; |
||
1104 | ACPI_PARSE_OBJECT *Op = NULL; /* current op */ |
||
1105 | ACPI_PARSE_STATE *ParserState; |
||
1106 | UINT8 *AmlOpStart = NULL; |
||
1107 | |||
1108 | |||
1109 | ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState); |
||
1110 | |||
1111 | |||
1112 | if (WalkState->DescendingCallback == NULL) |
||
1113 | { |
||
1114 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
||
1115 | } |
||
1116 | |||
1117 | ParserState = &WalkState->ParserState; |
||
1118 | WalkState->ArgTypes = 0; |
||
1119 | |||
1120 | #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) |
||
1121 | |||
1122 | if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART) |
||
1123 | { |
||
1124 | /* We are restarting a preempted control method */ |
||
1125 | |||
1126 | if (AcpiPsHasCompletedScope (ParserState)) |
||
1127 | { |
||
1128 | /* |
||
1129 | * We must check if a predicate to an IF or WHILE statement |
||
1130 | * was just completed |
||
1131 | */ |
||
1132 | if ((ParserState->Scope->ParseScope.Op) && |
||
1133 | ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) || |
||
1134 | (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) && |
||
1135 | (WalkState->ControlState) && |
||
1136 | (WalkState->ControlState->Common.State == |
||
1137 | ACPI_CONTROL_PREDICATE_EXECUTING)) |
||
1138 | { |
||
1139 | /* |
||
1140 | * A predicate was just completed, get the value of the |
||
1141 | * predicate and branch based on that value |
||
1142 | */ |
||
1143 | WalkState->Op = NULL; |
||
1144 | Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE)); |
||
1145 | if (ACPI_FAILURE (Status) && |
||
1146 | ((Status & AE_CODE_MASK) != AE_CODE_CONTROL)) |
||
1147 | { |
||
1148 | if (Status == AE_AML_NO_RETURN_VALUE) |
||
1149 | { |
||
1150 | ACPI_EXCEPTION ((AE_INFO, Status, |
||
1151 | "Invoked method did not return a value")); |
||
1152 | } |
||
1153 | |||
1154 | ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed")); |
||
1155 | return_ACPI_STATUS (Status); |
||
1156 | } |
||
1157 | |||
1158 | Status = AcpiPsNextParseState (WalkState, Op, Status); |
||
1159 | } |
||
1160 | |||
1161 | AcpiPsPopScope (ParserState, &Op, |
||
1162 | &WalkState->ArgTypes, &WalkState->ArgCount); |
||
1163 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op)); |
||
1164 | } |
||
1165 | else if (WalkState->PrevOp) |
||
1166 | { |
||
1167 | /* We were in the middle of an op */ |
||
1168 | |||
1169 | Op = WalkState->PrevOp; |
||
1170 | WalkState->ArgTypes = WalkState->PrevArgTypes; |
||
1171 | } |
||
1172 | } |
||
1173 | #endif |
||
1174 | |||
1175 | /* Iterative parsing loop, while there is more AML to process: */ |
||
1176 | |||
1177 | while ((ParserState->Aml < ParserState->AmlEnd) || (Op)) |
||
1178 | { |
||
1179 | AmlOpStart = ParserState->Aml; |
||
1180 | if (!Op) |
||
1181 | { |
||
1182 | Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op); |
||
1183 | if (ACPI_FAILURE (Status)) |
||
1184 | { |
||
1185 | if (Status == AE_CTRL_PARSE_CONTINUE) |
||
1186 | { |
||
1187 | continue; |
||
1188 | } |
||
1189 | |||
1190 | if (Status == AE_CTRL_PARSE_PENDING) |
||
1191 | { |
||
1192 | Status = AE_OK; |
||
1193 | } |
||
1194 | |||
1195 | Status = AcpiPsCompleteOp (WalkState, &Op, Status); |
||
1196 | if (ACPI_FAILURE (Status)) |
||
1197 | { |
||
1198 | return_ACPI_STATUS (Status); |
||
1199 | } |
||
1200 | |||
1201 | continue; |
||
1202 | } |
||
1203 | |||
1204 | Op->Common.AmlOffset = WalkState->AmlOffset; |
||
1205 | |||
1206 | if (WalkState->OpInfo) |
||
1207 | { |
||
1208 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, |
||
1209 | "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", |
||
1210 | (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name, |
||
1211 | Op, ParserState->Aml, Op->Common.AmlOffset)); |
||
1212 | } |
||
1213 | } |
||
1214 | |||
1215 | |||
1216 | /* |
||
1217 | * Start ArgCount at zero because we don't know if there are |
||
1218 | * any args yet |
||
1219 | */ |
||
1220 | WalkState->ArgCount = 0; |
||
1221 | |||
1222 | /* Are there any arguments that must be processed? */ |
||
1223 | |||
1224 | if (WalkState->ArgTypes) |
||
1225 | { |
||
1226 | /* Get arguments */ |
||
1227 | |||
1228 | Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op); |
||
1229 | if (ACPI_FAILURE (Status)) |
||
1230 | { |
||
1231 | Status = AcpiPsCompleteOp (WalkState, &Op, Status); |
||
1232 | if (ACPI_FAILURE (Status)) |
||
1233 | { |
||
1234 | return_ACPI_STATUS (Status); |
||
1235 | } |
||
1236 | |||
1237 | continue; |
||
1238 | } |
||
1239 | } |
||
1240 | |||
1241 | /* Check for arguments that need to be processed */ |
||
1242 | |||
1243 | if (WalkState->ArgCount) |
||
1244 | { |
||
1245 | /* |
||
1246 | * There are arguments (complex ones), push Op and |
||
1247 | * prepare for argument |
||
1248 | */ |
||
1249 | Status = AcpiPsPushScope (ParserState, Op, |
||
1250 | WalkState->ArgTypes, WalkState->ArgCount); |
||
1251 | if (ACPI_FAILURE (Status)) |
||
1252 | { |
||
1253 | Status = AcpiPsCompleteOp (WalkState, &Op, Status); |
||
1254 | if (ACPI_FAILURE (Status)) |
||
1255 | { |
||
1256 | return_ACPI_STATUS (Status); |
||
1257 | } |
||
1258 | |||
1259 | continue; |
||
1260 | } |
||
1261 | |||
1262 | Op = NULL; |
||
1263 | continue; |
||
1264 | } |
||
1265 | |||
1266 | /* |
||
1267 | * All arguments have been processed -- Op is complete, |
||
1268 | * prepare for next |
||
1269 | */ |
||
1270 | WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); |
||
1271 | if (WalkState->OpInfo->Flags & AML_NAMED) |
||
1272 | { |
||
1273 | if (AcpiGbl_Depth) |
||
1274 | { |
||
1275 | AcpiGbl_Depth--; |
||
1276 | } |
||
1277 | |||
1278 | if (Op->Common.AmlOpcode == AML_REGION_OP || |
||
1279 | Op->Common.AmlOpcode == AML_DATA_REGION_OP) |
||
1280 | { |
||
1281 | /* |
||
1282 | * Skip parsing of control method or opregion body, |
||
1283 | * because we don't have enough info in the first pass |
||
1284 | * to parse them correctly. |
||
1285 | * |
||
1286 | * Completed parsing an OpRegion declaration, we now |
||
1287 | * know the length. |
||
1288 | */ |
||
1289 | Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); |
||
1290 | } |
||
1291 | } |
||
1292 | |||
1293 | if (WalkState->OpInfo->Flags & AML_CREATE) |
||
1294 | { |
||
1295 | /* |
||
1296 | * Backup to beginning of CreateXXXfield declaration (1 for |
||
1297 | * Opcode) |
||
1298 | * |
||
1299 | * BodyLength is unknown until we parse the body |
||
1300 | */ |
||
1301 | Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); |
||
1302 | } |
||
1303 | |||
1304 | if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP) |
||
1305 | { |
||
1306 | /* |
||
1307 | * Backup to beginning of BankField declaration |
||
1308 | * |
||
1309 | * BodyLength is unknown until we parse the body |
||
1310 | */ |
||
1311 | Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); |
||
1312 | } |
||
1313 | |||
1314 | /* This op complete, notify the dispatcher */ |
||
1315 | |||
1316 | if (WalkState->AscendingCallback != NULL) |
||
1317 | { |
||
1318 | WalkState->Op = Op; |
||
1319 | WalkState->Opcode = Op->Common.AmlOpcode; |
||
1320 | |||
1321 | Status = WalkState->AscendingCallback (WalkState); |
||
1322 | Status = AcpiPsNextParseState (WalkState, Op, Status); |
||
1323 | if (Status == AE_CTRL_PENDING) |
||
1324 | { |
||
1325 | Status = AE_OK; |
||
1326 | } |
||
1327 | } |
||
1328 | |||
1329 | Status = AcpiPsCompleteOp (WalkState, &Op, Status); |
||
1330 | if (ACPI_FAILURE (Status)) |
||
1331 | { |
||
1332 | return_ACPI_STATUS (Status); |
||
1333 | } |
||
1334 | |||
1335 | } /* while ParserState->Aml */ |
||
1336 | |||
1337 | Status = AcpiPsCompleteFinalOp (WalkState, Op, Status); |
||
1338 | return_ACPI_STATUS (Status); |
||
1339 | }>=>=> |
||
1340 |