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