]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/psloop.c
This commit was generated by cvs2svn to compensate for changes in r154180,
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / psloop.c
1 /******************************************************************************
2  *
3  * Module Name: psloop - Main AML parse loop
4  *              $Revision: 1.5 $
5  *
6  *****************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2005, 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,
120  * like Perl, do.  Parsing is done by hand rather than with a YACC
121  * generated parser to tightly constrain stack and dynamic memory
122  * usage.  At the same time, parsing is kept flexible and the code
123  * fairly compact by parsing based on a list of AML opcode
124  * templates in AmlOpInfo[]
125  */
126
127 #include <contrib/dev/acpica/acpi.h>
128 #include <contrib/dev/acpica/acparser.h>
129 #include <contrib/dev/acpica/acdispat.h>
130 #include <contrib/dev/acpica/amlcode.h>
131
132 #define _COMPONENT          ACPI_PARSER
133         ACPI_MODULE_NAME    ("psloop")
134
135 static UINT32               AcpiGbl_Depth = 0;
136
137
138 /*******************************************************************************
139  *
140  * FUNCTION:    AcpiPsParseLoop
141  *
142  * PARAMETERS:  WalkState           - Current state
143  *
144  * RETURN:      Status
145  *
146  * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
147  *              a tree of ops.
148  *
149  ******************************************************************************/
150
151 ACPI_STATUS
152 AcpiPsParseLoop (
153     ACPI_WALK_STATE         *WalkState)
154 {
155     ACPI_STATUS             Status = AE_OK;
156     ACPI_STATUS             Status2;
157     ACPI_PARSE_OBJECT       *Op = NULL;     /* current op */
158     ACPI_PARSE_OBJECT       *Arg = NULL;
159     ACPI_PARSE_OBJECT       *PreOp = NULL;
160     ACPI_PARSE_STATE        *ParserState;
161     UINT8                   *AmlOpStart = NULL;
162
163
164     ACPI_FUNCTION_TRACE_PTR ("PsParseLoop", WalkState);
165
166     if (WalkState->DescendingCallback == NULL)
167     {
168         return_ACPI_STATUS (AE_BAD_PARAMETER);
169     }
170
171     ParserState = &WalkState->ParserState;
172     WalkState->ArgTypes = 0;
173
174 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
175
176     if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART)
177     {
178         /* We are restarting a preempted control method */
179
180         if (AcpiPsHasCompletedScope (ParserState))
181         {
182             /*
183              * We must check if a predicate to an IF or WHILE statement
184              * was just completed
185              */
186             if ((ParserState->Scope->ParseScope.Op) &&
187                ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) ||
188                 (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) &&
189                 (WalkState->ControlState) &&
190                 (WalkState->ControlState->Common.State ==
191                     ACPI_CONTROL_PREDICATE_EXECUTING))
192             {
193                 /*
194                  * A predicate was just completed, get the value of the
195                  * predicate and branch based on that value
196                  */
197                 WalkState->Op = NULL;
198                 Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE));
199                 if (ACPI_FAILURE (Status) &&
200                     ((Status & AE_CODE_MASK) != AE_CODE_CONTROL))
201                 {
202                     if (Status == AE_AML_NO_RETURN_VALUE)
203                     {
204                         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
205                             "Invoked method did not return a value, %s\n",
206                             AcpiFormatException (Status)));
207
208                     }
209                     ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
210                         "GetPredicate Failed, %s\n",
211                         AcpiFormatException (Status)));
212                     return_ACPI_STATUS (Status);
213                 }
214
215                 Status = AcpiPsNextParseState (WalkState, Op, Status);
216             }
217
218             AcpiPsPopScope (ParserState, &Op,
219                 &WalkState->ArgTypes, &WalkState->ArgCount);
220             ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
221         }
222         else if (WalkState->PrevOp)
223         {
224             /* We were in the middle of an op */
225
226             Op = WalkState->PrevOp;
227             WalkState->ArgTypes = WalkState->PrevArgTypes;
228         }
229     }
230 #endif
231
232     /* Iterative parsing loop, while there is more AML to process: */
233
234     while ((ParserState->Aml < ParserState->AmlEnd) || (Op))
235     {
236         AmlOpStart = ParserState->Aml;
237         if (!Op)
238         {
239             /* Get the next opcode from the AML stream */
240
241             WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (ParserState->Aml,
242                                                     ParserState->AmlStart);
243             WalkState->Opcode    = AcpiPsPeekOpcode (ParserState);
244
245             /*
246              * First cut to determine what we have found:
247              * 1) A valid AML opcode
248              * 2) A name string
249              * 3) An unknown/invalid opcode
250              */
251             WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
252             switch (WalkState->OpInfo->Class)
253             {
254             case AML_CLASS_ASCII:
255             case AML_CLASS_PREFIX:
256                 /*
257                  * Starts with a valid prefix or ASCII char, this is a name
258                  * string.  Convert the bare name string to a namepath.
259                  */
260                 WalkState->Opcode = AML_INT_NAMEPATH_OP;
261                 WalkState->ArgTypes = ARGP_NAMESTRING;
262                 break;
263
264             case AML_CLASS_UNKNOWN:
265
266                 /* The opcode is unrecognized.  Just skip unknown opcodes */
267
268                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
269                     "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
270                     WalkState->Opcode, ParserState->Aml, WalkState->AmlOffset));
271
272                 ACPI_DUMP_BUFFER (ParserState->Aml, 128);
273
274                 /* Assume one-byte bad opcode */
275
276                 ParserState->Aml++;
277                 continue;
278
279             default:
280
281                 /* Found opcode info, this is a normal opcode */
282
283                 ParserState->Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
284                 WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
285                 break;
286             }
287
288             /* Create Op structure and append to parent's argument list */
289
290             if (WalkState->OpInfo->Flags & AML_NAMED)
291             {
292                 /* Allocate a new PreOp if necessary */
293
294                 if (!PreOp)
295                 {
296                     PreOp = AcpiPsAllocOp (WalkState->Opcode);
297                     if (!PreOp)
298                     {
299                         Status = AE_NO_MEMORY;
300                         goto CloseThisOp;
301                     }
302                 }
303
304                 PreOp->Common.Value.Arg = NULL;
305                 PreOp->Common.AmlOpcode = WalkState->Opcode;
306
307                 /*
308                  * Get and append arguments until we find the node that contains
309                  * the name (the type ARGP_NAME).
310                  */
311                 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
312                       (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
313                 {
314                     Status = AcpiPsGetNextArg (WalkState, ParserState,
315                                 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
316                     if (ACPI_FAILURE (Status))
317                     {
318                         goto CloseThisOp;
319                     }
320
321                     AcpiPsAppendArg (PreOp, Arg);
322                     INCREMENT_ARG_LIST (WalkState->ArgTypes);
323                 }
324
325                 /*
326                  * Make sure that we found a NAME and didn't run out of
327                  * arguments
328                  */
329                 if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
330                 {
331                     Status = AE_AML_NO_OPERAND;
332                     goto CloseThisOp;
333                 }
334
335                 /* We know that this arg is a name, move to next arg */
336
337                 INCREMENT_ARG_LIST (WalkState->ArgTypes);
338
339                 /*
340                  * Find the object.  This will either insert the object into
341                  * the namespace or simply look it up
342                  */
343                 WalkState->Op = NULL;
344
345                 Status = WalkState->DescendingCallback (WalkState, &Op);
346                 if (ACPI_FAILURE (Status))
347                 {
348                     ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
349                         "During name lookup/catalog, %s\n",
350                         AcpiFormatException (Status)));
351                     goto CloseThisOp;
352                 }
353
354                 if (!Op)
355                 {
356                     continue;
357                 }
358
359                 Status = AcpiPsNextParseState (WalkState, Op, Status);
360                 if (Status == AE_CTRL_PENDING)
361                 {
362                     Status = AE_OK;
363                     goto CloseThisOp;
364                 }
365
366                 if (ACPI_FAILURE (Status))
367                 {
368                     goto CloseThisOp;
369                 }
370
371                 AcpiPsAppendArg (Op, PreOp->Common.Value.Arg);
372                 AcpiGbl_Depth++;
373
374                 if (Op->Common.AmlOpcode == AML_REGION_OP)
375                 {
376                     /*
377                      * Defer final parsing of an OperationRegion body,
378                      * because we don't have enough info in the first pass
379                      * to parse it correctly (i.e., there may be method
380                      * calls within the TermArg elements of the body.)
381                      *
382                      * However, we must continue parsing because
383                      * the opregion is not a standalone package --
384                      * we don't know where the end is at this point.
385                      *
386                      * (Length is unknown until parse of the body complete)
387                      */
388                     Op->Named.Data    = AmlOpStart;
389                     Op->Named.Length  = 0;
390                 }
391             }
392             else
393             {
394                 /* Not a named opcode, just allocate Op and append to parent */
395
396                 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
397                 Op = AcpiPsAllocOp (WalkState->Opcode);
398                 if (!Op)
399                 {
400                     Status = AE_NO_MEMORY;
401                     goto CloseThisOp;
402                 }
403
404                 if (WalkState->OpInfo->Flags & AML_CREATE)
405                 {
406                     /*
407                      * Backup to beginning of CreateXXXfield declaration
408                      * BodyLength is unknown until we parse the body
409                      */
410                     Op->Named.Data    = AmlOpStart;
411                     Op->Named.Length  = 0;
412                 }
413
414                 AcpiPsAppendArg (AcpiPsGetParentScope (ParserState), Op);
415
416                 if ((WalkState->DescendingCallback != NULL))
417                 {
418                     /*
419                      * Find the object. This will either insert the object into
420                      * the namespace or simply look it up
421                      */
422                     WalkState->Op = Op;
423
424                     Status = WalkState->DescendingCallback (WalkState, &Op);
425                     Status = AcpiPsNextParseState (WalkState, Op, Status);
426                     if (Status == AE_CTRL_PENDING)
427                     {
428                         Status = AE_OK;
429                         goto CloseThisOp;
430                     }
431
432                     if (ACPI_FAILURE (Status))
433                     {
434                         goto CloseThisOp;
435                     }
436                 }
437             }
438
439             Op->Common.AmlOffset = WalkState->AmlOffset;
440
441             if (WalkState->OpInfo)
442             {
443                 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
444                     "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
445                      (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name,
446                      Op, ParserState->Aml, Op->Common.AmlOffset));
447             }
448         }
449
450
451         /*
452          * Start ArgCount at zero because we don't know if there are
453          * any args yet
454          */
455         WalkState->ArgCount  = 0;
456
457         /* Are there any arguments that must be processed? */
458
459         if (WalkState->ArgTypes)
460         {
461             /* Get arguments */
462
463             switch (Op->Common.AmlOpcode)
464             {
465             case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
466             case AML_WORD_OP:       /* AML_WORDDATA_ARG */
467             case AML_DWORD_OP:      /* AML_DWORDATA_ARG */
468             case AML_QWORD_OP:      /* AML_QWORDATA_ARG */
469             case AML_STRING_OP:     /* AML_ASCIICHARLIST_ARG */
470
471                 /* Fill in constant or string argument directly */
472
473                 AcpiPsGetNextSimpleArg (ParserState,
474                     GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op);
475                 break;
476
477             case AML_INT_NAMEPATH_OP:   /* AML_NAMESTRING_ARG */
478
479                 Status = AcpiPsGetNextNamepath (WalkState, ParserState, Op, 1);
480                 if (ACPI_FAILURE (Status))
481                 {
482                     goto CloseThisOp;
483                 }
484
485                 WalkState->ArgTypes = 0;
486                 break;
487
488             default:
489                 /*
490                  * Op is not a constant or string, append each argument
491                  * to the Op
492                  */
493                 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
494                         !WalkState->ArgCount)
495                 {
496                     WalkState->AmlOffset = (UINT32)
497                         ACPI_PTR_DIFF (ParserState->Aml, ParserState->AmlStart);
498
499                     Status = AcpiPsGetNextArg (WalkState, ParserState,
500                                 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes),
501                                 &Arg);
502                     if (ACPI_FAILURE (Status))
503                     {
504                         goto CloseThisOp;
505                     }
506
507                     if (Arg)
508                     {
509                         Arg->Common.AmlOffset = WalkState->AmlOffset;
510                         AcpiPsAppendArg (Op, Arg);
511                     }
512                     INCREMENT_ARG_LIST (WalkState->ArgTypes);
513                 }
514
515
516                 /* Special processing for certain opcodes */
517
518     /* TBD (remove): Temporary mechanism to disable this code if needed */
519
520 #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
521
522                 if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS1) &&
523                    ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0))
524                 {
525                     /*
526                      * We want to skip If/Else/While constructs during Pass1
527                      * because we want to actually conditionally execute the
528                      * code during Pass2.
529                      *
530                      * Except for disassembly, where we always want to
531                      * walk the If/Else/While packages
532                      */
533                     switch (Op->Common.AmlOpcode)
534                     {
535                     case AML_IF_OP:
536                     case AML_ELSE_OP:
537                     case AML_WHILE_OP:
538
539                         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
540                             "Pass1: Skipping an If/Else/While body\n"));
541
542                         /* Skip body of if/else/while in pass 1 */
543
544                         ParserState->Aml    = ParserState->PkgEnd;
545                         WalkState->ArgCount = 0;
546                         break;
547
548                     default:
549                         break;
550                     }
551                 }
552 #endif
553                 switch (Op->Common.AmlOpcode)
554                 {
555                 case AML_METHOD_OP:
556
557                     /*
558                      * Skip parsing of control method
559                      * because we don't have enough info in the first pass
560                      * to parse it correctly.
561                      *
562                      * Save the length and address of the body
563                      */
564                     Op->Named.Data   = ParserState->Aml;
565                     Op->Named.Length = (UINT32) (ParserState->PkgEnd -
566                                                  ParserState->Aml);
567
568                     /* Skip body of method */
569
570                     ParserState->Aml    = ParserState->PkgEnd;
571                     WalkState->ArgCount = 0;
572                     break;
573
574                 case AML_BUFFER_OP:
575                 case AML_PACKAGE_OP:
576                 case AML_VAR_PACKAGE_OP:
577
578                     if ((Op->Common.Parent) &&
579                         (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
580                         (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))
581                     {
582                         /*
583                          * Skip parsing of Buffers and Packages
584                          * because we don't have enough info in the first pass
585                          * to parse them correctly.
586                          */
587                         Op->Named.Data   = AmlOpStart;
588                         Op->Named.Length = (UINT32) (ParserState->PkgEnd -
589                                                      AmlOpStart);
590
591                         /* Skip body */
592
593                         ParserState->Aml    = ParserState->PkgEnd;
594                         WalkState->ArgCount = 0;
595                     }
596                     break;
597
598                 case AML_WHILE_OP:
599
600                     if (WalkState->ControlState)
601                     {
602                         WalkState->ControlState->Control.PackageEnd =
603                             ParserState->PkgEnd;
604                     }
605                     break;
606
607                 default:
608
609                     /* No action for all other opcodes */
610                     break;
611                 }
612                 break;
613             }
614         }
615
616         /* Check for arguments that need to be processed */
617
618         if (WalkState->ArgCount)
619         {
620             /*
621              * There are arguments (complex ones), push Op and
622              * prepare for argument
623              */
624             Status = AcpiPsPushScope (ParserState, Op,
625                         WalkState->ArgTypes, WalkState->ArgCount);
626             if (ACPI_FAILURE (Status))
627             {
628                 goto CloseThisOp;
629             }
630             Op = NULL;
631             continue;
632         }
633
634         /*
635          * All arguments have been processed -- Op is complete,
636          * prepare for next
637          */
638         WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
639         if (WalkState->OpInfo->Flags & AML_NAMED)
640         {
641             if (AcpiGbl_Depth)
642             {
643                 AcpiGbl_Depth--;
644             }
645
646             if (Op->Common.AmlOpcode == AML_REGION_OP)
647             {
648                 /*
649                  * Skip parsing of control method or opregion body,
650                  * because we don't have enough info in the first pass
651                  * to parse them correctly.
652                  *
653                  * Completed parsing an OpRegion declaration, we now
654                  * know the length.
655                  */
656                 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
657             }
658         }
659
660         if (WalkState->OpInfo->Flags & AML_CREATE)
661         {
662             /*
663              * Backup to beginning of CreateXXXfield declaration (1 for
664              * Opcode)
665              *
666              * BodyLength is unknown until we parse the body
667              */
668             Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
669         }
670
671         /* This op complete, notify the dispatcher */
672
673         if (WalkState->AscendingCallback != NULL)
674         {
675             WalkState->Op     = Op;
676             WalkState->Opcode = Op->Common.AmlOpcode;
677
678             Status = WalkState->AscendingCallback (WalkState);
679             Status = AcpiPsNextParseState (WalkState, Op, Status);
680             if (Status == AE_CTRL_PENDING)
681             {
682                 Status = AE_OK;
683                 goto CloseThisOp;
684             }
685         }
686
687
688 CloseThisOp:
689         /*
690          * Finished one argument of the containing scope
691          */
692         ParserState->Scope->ParseScope.ArgCount--;
693
694         /* Finished with PreOp */
695
696         if (PreOp)
697         {
698             AcpiPsFreeOp (PreOp);
699             PreOp = NULL;
700         }
701
702         /* Close this Op (will result in parse subtree deletion) */
703
704         Status2 = AcpiPsCompleteThisOp (WalkState, Op);
705         if (ACPI_FAILURE (Status2))
706         {
707             return_ACPI_STATUS (Status2);
708         }
709         Op = NULL;
710
711         switch (Status)
712         {
713         case AE_OK:
714             break;
715
716
717         case AE_CTRL_TRANSFER:
718
719             /* We are about to transfer to a called method. */
720
721             WalkState->PrevOp = Op;
722             WalkState->PrevArgTypes = WalkState->ArgTypes;
723             return_ACPI_STATUS (Status);
724
725
726         case AE_CTRL_END:
727
728             AcpiPsPopScope (ParserState, &Op,
729                 &WalkState->ArgTypes, &WalkState->ArgCount);
730
731             if (Op)
732             {
733                 WalkState->Op     = Op;
734                 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
735                 WalkState->Opcode = Op->Common.AmlOpcode;
736
737                 Status = WalkState->AscendingCallback (WalkState);
738                 Status = AcpiPsNextParseState (WalkState, Op, Status);
739
740                 Status2 = AcpiPsCompleteThisOp (WalkState, Op);
741                 if (ACPI_FAILURE (Status2))
742                 {
743                     return_ACPI_STATUS (Status2);
744                 }
745                 Op = NULL;
746             }
747             Status = AE_OK;
748             break;
749
750
751         case AE_CTRL_BREAK:
752         case AE_CTRL_CONTINUE:
753
754             /* Pop off scopes until we find the While */
755
756             while (!Op || (Op->Common.AmlOpcode != AML_WHILE_OP))
757             {
758                 AcpiPsPopScope (ParserState, &Op,
759                     &WalkState->ArgTypes, &WalkState->ArgCount);
760             }
761
762             /* Close this iteration of the While loop */
763
764             WalkState->Op     = Op;
765             WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
766             WalkState->Opcode = Op->Common.AmlOpcode;
767
768             Status = WalkState->AscendingCallback (WalkState);
769             Status = AcpiPsNextParseState (WalkState, Op, Status);
770
771             Status2 = AcpiPsCompleteThisOp (WalkState, Op);
772             if (ACPI_FAILURE (Status2))
773             {
774                 return_ACPI_STATUS (Status2);
775             }
776             Op = NULL;
777
778             Status = AE_OK;
779             break;
780
781
782         case AE_CTRL_TERMINATE:
783
784             Status = AE_OK;
785
786             /* Clean up */
787             do
788             {
789                 if (Op)
790                 {
791                     Status2 = AcpiPsCompleteThisOp (WalkState, Op);
792                     if (ACPI_FAILURE (Status2))
793                     {
794                         return_ACPI_STATUS (Status2);
795                     }
796                 }
797                 AcpiPsPopScope (ParserState, &Op,
798                     &WalkState->ArgTypes, &WalkState->ArgCount);
799
800             } while (Op);
801
802             return_ACPI_STATUS (Status);
803
804
805         default:  /* All other non-AE_OK status */
806
807             do
808             {
809                 if (Op)
810                 {
811                     Status2 = AcpiPsCompleteThisOp (WalkState, Op);
812                     if (ACPI_FAILURE (Status2))
813                     {
814                         return_ACPI_STATUS (Status2);
815                     }
816                 }
817                 AcpiPsPopScope (ParserState, &Op,
818                     &WalkState->ArgTypes, &WalkState->ArgCount);
819
820             } while (Op);
821
822
823             /*
824              * TBD: Cleanup parse ops on error
825              */
826 #if 0
827             if (Op == NULL)
828             {
829                 AcpiPsPopScope (ParserState, &Op,
830                     &WalkState->ArgTypes, &WalkState->ArgCount);
831             }
832 #endif
833             WalkState->PrevOp = Op;
834             WalkState->PrevArgTypes = WalkState->ArgTypes;
835             return_ACPI_STATUS (Status);
836         }
837
838         /* This scope complete? */
839
840         if (AcpiPsHasCompletedScope (ParserState))
841         {
842             AcpiPsPopScope (ParserState, &Op,
843                 &WalkState->ArgTypes, &WalkState->ArgCount);
844             ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
845         }
846         else
847         {
848             Op = NULL;
849         }
850
851     } /* while ParserState->Aml */
852
853
854     /*
855      * Complete the last Op (if not completed), and clear the scope stack.
856      * It is easily possible to end an AML "package" with an unbounded number
857      * of open scopes (such as when several ASL blocks are closed with
858      * sequential closing braces).  We want to terminate each one cleanly.
859      */
860     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
861     do
862     {
863         if (Op)
864         {
865             if (WalkState->AscendingCallback != NULL)
866             {
867                 WalkState->Op     = Op;
868                 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
869                 WalkState->Opcode = Op->Common.AmlOpcode;
870
871                 Status = WalkState->AscendingCallback (WalkState);
872                 Status = AcpiPsNextParseState (WalkState, Op, Status);
873                 if (Status == AE_CTRL_PENDING)
874                 {
875                     Status = AE_OK;
876                     goto CloseThisOp;
877                 }
878
879                 if (Status == AE_CTRL_TERMINATE)
880                 {
881                     Status = AE_OK;
882
883                     /* Clean up */
884                     do
885                     {
886                         if (Op)
887                         {
888                             Status2 = AcpiPsCompleteThisOp (WalkState, Op);
889                             if (ACPI_FAILURE (Status2))
890                             {
891                                 return_ACPI_STATUS (Status2);
892                             }
893                         }
894
895                         AcpiPsPopScope (ParserState, &Op,
896                             &WalkState->ArgTypes, &WalkState->ArgCount);
897
898                     } while (Op);
899
900                     return_ACPI_STATUS (Status);
901                 }
902
903                 else if (ACPI_FAILURE (Status))
904                 {
905                     /* First error is most important */
906
907                     (void) AcpiPsCompleteThisOp (WalkState, Op);
908                     return_ACPI_STATUS (Status);
909                 }
910             }
911
912             Status2 = AcpiPsCompleteThisOp (WalkState, Op);
913             if (ACPI_FAILURE (Status2))
914             {
915                 return_ACPI_STATUS (Status2);
916             }
917         }
918
919         AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes,
920             &WalkState->ArgCount);
921
922     } while (Op);
923
924     return_ACPI_STATUS (Status);
925 }
926
927