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