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