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