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