1 /******************************************************************************
2 *
3 * Module Name: psloop - Main AML parse loop
4 *
5 *****************************************************************************/
6
7 /******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
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
AcpiPsGetAmlOpcode(ACPI_WALK_STATE * WalkState)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 %X at AML address %p offset %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
AcpiPsBuildNamedOp(ACPI_WALK_STATE * WalkState,UINT8 * AmlOpStart,ACPI_PARSE_OBJECT * UnnamedOp,ACPI_PARSE_OBJECT ** Op)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
AcpiPsCreateOp(ACPI_WALK_STATE * WalkState,UINT8 * AmlOpStart,ACPI_PARSE_OBJECT ** NewOp)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
AcpiPsGetArguments(ACPI_WALK_STATE * WalkState,UINT8 * AmlOpStart,ACPI_PARSE_OBJECT * Op)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
AcpiPsLinkModuleCode(ACPI_PARSE_OBJECT * ParentOp,UINT8 * AmlStart,UINT32 AmlLength,ACPI_OWNER_ID OwnerId)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;
770 MethodObj->Method.Flags |= AOPOBJ_MODULE_LEVEL;
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
AcpiPsCompleteOp(ACPI_WALK_STATE * WalkState,ACPI_PARSE_OBJECT ** Op,ACPI_STATUS 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
AcpiPsCompleteFinalOp(ACPI_WALK_STATE * WalkState,ACPI_PARSE_OBJECT * Op,ACPI_STATUS 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
AcpiPsParseLoop(ACPI_WALK_STATE * WalkState)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
1155 ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed"));
1156 return_ACPI_STATUS (Status);
1157 }
1158
1159 Status = AcpiPsNextParseState (WalkState, Op, Status);
1160 }
1161
1162 AcpiPsPopScope (ParserState, &Op,
1163 &WalkState->ArgTypes, &WalkState->ArgCount);
1164 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
1165 }
1166 else if (WalkState->PrevOp)
1167 {
1168 /* We were in the middle of an op */
1169
1170 Op = WalkState->PrevOp;
1171 WalkState->ArgTypes = WalkState->PrevArgTypes;
1172 }
1173 }
1174 #endif
1175
1176 /* Iterative parsing loop, while there is more AML to process: */
1177
1178 while ((ParserState->Aml < ParserState->AmlEnd) || (Op))
1179 {
1180 AmlOpStart = ParserState->Aml;
1181 if (!Op)
1182 {
1183 Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op);
1184 if (ACPI_FAILURE (Status))
1185 {
1186 if (Status == AE_CTRL_PARSE_CONTINUE)
1187 {
1188 continue;
1189 }
1190
1191 if (Status == AE_CTRL_PARSE_PENDING)
1192 {
1193 Status = AE_OK;
1194 }
1195
1196 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1197 if (ACPI_FAILURE (Status))
1198 {
1199 return_ACPI_STATUS (Status);
1200 }
1201
1202 continue;
1203 }
1204
1205 Op->Common.AmlOffset = WalkState->AmlOffset;
1206
1207 if (WalkState->OpInfo)
1208 {
1209 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
1210 "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
1211 (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name,
1212 Op, ParserState->Aml, Op->Common.AmlOffset));
1213 }
1214 }
1215
1216
1217 /*
1218 * Start ArgCount at zero because we don't know if there are
1219 * any args yet
1220 */
1221 WalkState->ArgCount = 0;
1222
1223 /* Are there any arguments that must be processed? */
1224
1225 if (WalkState->ArgTypes)
1226 {
1227 /* Get arguments */
1228
1229 Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op);
1230 if (ACPI_FAILURE (Status))
1231 {
1232 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1233 if (ACPI_FAILURE (Status))
1234 {
1235 return_ACPI_STATUS (Status);
1236 }
1237
1238 continue;
1239 }
1240 }
1241
1242 /* Check for arguments that need to be processed */
1243
1244 if (WalkState->ArgCount)
1245 {
1246 /*
1247 * There are arguments (complex ones), push Op and
1248 * prepare for argument
1249 */
1250 Status = AcpiPsPushScope (ParserState, Op,
1251 WalkState->ArgTypes, WalkState->ArgCount);
1252 if (ACPI_FAILURE (Status))
1253 {
1254 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1255 if (ACPI_FAILURE (Status))
1256 {
1257 return_ACPI_STATUS (Status);
1258 }
1259
1260 continue;
1261 }
1262
1263 Op = NULL;
1264 continue;
1265 }
1266
1267 /*
1268 * All arguments have been processed -- Op is complete,
1269 * prepare for next
1270 */
1271 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1272 if (WalkState->OpInfo->Flags & AML_NAMED)
1273 {
1274 if (AcpiGbl_Depth)
1275 {
1276 AcpiGbl_Depth--;
1277 }
1278
1279 if (Op->Common.AmlOpcode == AML_REGION_OP ||
1280 Op->Common.AmlOpcode == AML_DATA_REGION_OP)
1281 {
1282 /*
1283 * Skip parsing of control method or opregion body,
1284 * because we don't have enough info in the first pass
1285 * to parse them correctly.
1286 *
1287 * Completed parsing an OpRegion declaration, we now
1288 * know the length.
1289 */
1290 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1291 }
1292 }
1293
1294 if (WalkState->OpInfo->Flags & AML_CREATE)
1295 {
1296 /*
1297 * Backup to beginning of CreateXXXfield declaration (1 for
1298 * Opcode)
1299 *
1300 * BodyLength is unknown until we parse the body
1301 */
1302 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1303 }
1304
1305 if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP)
1306 {
1307 /*
1308 * Backup to beginning of BankField declaration
1309 *
1310 * BodyLength is unknown until we parse the body
1311 */
1312 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1313 }
1314
1315 /* This op complete, notify the dispatcher */
1316
1317 if (WalkState->AscendingCallback != NULL)
1318 {
1319 WalkState->Op = Op;
1320 WalkState->Opcode = Op->Common.AmlOpcode;
1321
1322 Status = WalkState->AscendingCallback (WalkState);
1323 Status = AcpiPsNextParseState (WalkState, Op, Status);
1324 if (Status == AE_CTRL_PENDING)
1325 {
1326 Status = AE_OK;
1327 }
1328 }
1329
1330 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1331 if (ACPI_FAILURE (Status))
1332 {
1333 return_ACPI_STATUS (Status);
1334 }
1335
1336 } /* while ParserState->Aml */
1337
1338 Status = AcpiPsCompleteFinalOp (WalkState, Op, Status);
1339 return_ACPI_STATUS (Status);
1340 }
1341
1342