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