psparse.c revision 114237
191094Sdes/******************************************************************************
291094Sdes *
391094Sdes * Module Name: psparse - Parser top level AML parse routines
491094Sdes *              $Revision: 139 $
591094Sdes *
691094Sdes *****************************************************************************/
791094Sdes
891094Sdes/******************************************************************************
991094Sdes *
1091094Sdes * 1. Copyright Notice
1191094Sdes *
1291094Sdes * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp.
1391094Sdes * All rights reserved.
1491094Sdes *
1591094Sdes * 2. License
1691094Sdes *
1791094Sdes * 2.1. This is your license from Intel Corp. under its intellectual property
1891094Sdes * rights.  You may have additional license terms from the party that provided
1991094Sdes * you this software, covering your right to use that party's intellectual
2091094Sdes * property rights.
2191094Sdes *
2291094Sdes * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2391094Sdes * copy of the source code appearing in this file ("Covered Code") an
2491094Sdes * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2591094Sdes * base code distributed originally by Intel ("Original Intel Code") to copy,
2691094Sdes * make derivatives, distribute, use and display any portion of the Covered
2791094Sdes * Code in any form, with the right to sublicense such rights; and
2891094Sdes *
2991094Sdes * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3091094Sdes * license (with the right to sublicense), under only those claims of Intel
3191094Sdes * patents that are infringed by the Original Intel Code, to make, use, sell,
3291094Sdes * offer to sell, and import the Covered Code and derivative works thereof
3391094Sdes * solely to the minimum extent necessary to exercise the above copyright
3491094Sdes * license, and in no event shall the patent license extend to any additions
3591094Sdes * to or modifications of the Original Intel Code.  No other license or right
3691094Sdes * is granted directly or by implication, estoppel or otherwise;
3791094Sdes *
3891094Sdes * The above copyright and patent license is granted only if the following
3991094Sdes * conditions are met:
4091094Sdes *
4191094Sdes * 3. Conditions
4291094Sdes *
4391094Sdes * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4491094Sdes * Redistribution of source code of any substantial portion of the Covered
4591094Sdes * Code or modification with rights to further distribute source must include
4691094Sdes * the above Copyright Notice, the above License, this list of Conditions,
4791094Sdes * and the following Disclaimer and Export Compliance provision.  In addition,
4891094Sdes * Licensee must cause all Covered Code to which Licensee contributes to
4991094Sdes * contain a file documenting the changes Licensee made to create that Covered
5091094Sdes * Code and the date of any change.  Licensee must include in that file the
5191094Sdes * documentation of any changes made by any predecessor Licensee.  Licensee
5291094Sdes * must include a prominent statement that the modification is derived,
5391094Sdes * directly or indirectly, from Original Intel Code.
5491094Sdes *
5591094Sdes * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5691094Sdes * 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 "acinterp.h"
133
134#define _COMPONENT          ACPI_PARSER
135        ACPI_MODULE_NAME    ("psparse")
136
137
138static UINT32               AcpiGbl_Depth = 0;
139
140
141/*******************************************************************************
142 *
143 * FUNCTION:    AcpiPsGetOpcodeSize
144 *
145 * PARAMETERS:  Opcode          - An AML opcode
146 *
147 * RETURN:      Size of the opcode, in bytes (1 or 2)
148 *
149 * DESCRIPTION: Get the size of the current opcode.
150 *
151 ******************************************************************************/
152
153UINT32
154AcpiPsGetOpcodeSize (
155    UINT32                  Opcode)
156{
157
158    /* Extended (2-byte) opcode if > 255 */
159
160    if (Opcode > 0x00FF)
161    {
162        return (2);
163    }
164
165    /* Otherwise, just a single byte opcode */
166
167    return (1);
168}
169
170
171/*******************************************************************************
172 *
173 * FUNCTION:    AcpiPsPeekOpcode
174 *
175 * PARAMETERS:  ParserState         - A parser state object
176 *
177 * RETURN:      Status
178 *
179 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer)
180 *
181 ******************************************************************************/
182
183UINT16
184AcpiPsPeekOpcode (
185    ACPI_PARSE_STATE        *ParserState)
186{
187    UINT8                   *Aml;
188    UINT16                  Opcode;
189
190
191    Aml = ParserState->Aml;
192    Opcode = (UINT16) ACPI_GET8 (Aml);
193
194
195    if (Opcode == AML_EXTOP)
196    {
197        /* Extended opcode */
198
199        Aml++;
200        Opcode = (UINT16) ((Opcode << 8) | ACPI_GET8 (Aml));
201    }
202
203    return (Opcode);
204}
205
206
207/*******************************************************************************
208 *
209 * FUNCTION:    AcpiPsCompleteThisOp
210 *
211 * PARAMETERS:  WalkState       - Current State
212 *              Op              - Op to complete
213 *
214 * RETURN:      None.
215 *
216 * DESCRIPTION: Perform any cleanup at the completion of an Op.
217 *
218 ******************************************************************************/
219
220void
221AcpiPsCompleteThisOp (
222    ACPI_WALK_STATE         *WalkState,
223    ACPI_PARSE_OBJECT       *Op)
224{
225    ACPI_PARSE_OBJECT       *Prev;
226    ACPI_PARSE_OBJECT       *Next;
227    const ACPI_OPCODE_INFO  *ParentInfo;
228    ACPI_PARSE_OBJECT       *ReplacementOp = NULL;
229
230
231    ACPI_FUNCTION_TRACE_PTR ("PsCompleteThisOp", Op);
232
233
234    /* Check for null Op, can happen if AML code is corrupt */
235
236    if (!Op)
237    {
238        return_VOID;
239    }
240
241    /* Delete this op and the subtree below it if asked to */
242
243    if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) == ACPI_PARSE_DELETE_TREE) &&
244        (WalkState->OpInfo->Class != AML_CLASS_ARGUMENT))
245    {
246        /* Make sure that we only delete this subtree */
247
248        if (Op->Common.Parent)
249        {
250            /*
251             * Check if we need to replace the operator and its subtree
252             * with a return value op (placeholder op)
253             */
254            ParentInfo  = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
255
256            switch (ParentInfo->Class)
257            {
258            case AML_CLASS_CONTROL:
259                break;
260
261            case AML_CLASS_CREATE:
262
263                /*
264                 * These opcodes contain TermArg operands.  The current
265                 * op must be replaced by a placeholder return op
266                 */
267                ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
268                if (!ReplacementOp)
269                {
270                    return_VOID;
271                }
272                break;
273
274            case AML_CLASS_NAMED_OBJECT:
275
276                /*
277                 * These opcodes contain TermArg operands.  The current
278                 * op must be replaced by a placeholder return op
279                 */
280                if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
281                    (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
282                    (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
283                    (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
284                    (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
285                {
286                    ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
287                    if (!ReplacementOp)
288                    {
289                        return_VOID;
290                    }
291                }
292
293                if ((Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
294                    (WalkState->DescendingCallback != AcpiDsExecBeginOp))
295
296                {
297                    if ((Op->Common.AmlOpcode == AML_BUFFER_OP) ||
298                        (Op->Common.AmlOpcode == AML_PACKAGE_OP) ||
299                        (Op->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
300                    {
301                        ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode);
302                        if (!ReplacementOp)
303                        {
304                            return_VOID;
305                        }
306
307                        ReplacementOp->Named.Data = Op->Named.Data;
308                        ReplacementOp->Named.Length = Op->Named.Length;
309                    }
310                }
311                break;
312
313            default:
314                ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
315                if (!ReplacementOp)
316                {
317                    return_VOID;
318                }
319            }
320
321            /* We must unlink this op from the parent tree */
322
323            Prev = Op->Common.Parent->Common.Value.Arg;
324            if (Prev == Op)
325            {
326                /* This op is the first in the list */
327
328                if (ReplacementOp)
329                {
330                    ReplacementOp->Common.Parent        = Op->Common.Parent;
331                    ReplacementOp->Common.Value.Arg     = NULL;
332                    ReplacementOp->Common.Node          = Op->Common.Node;
333                    Op->Common.Parent->Common.Value.Arg = ReplacementOp;
334                    ReplacementOp->Common.Next          = Op->Common.Next;
335                }
336                else
337                {
338                    Op->Common.Parent->Common.Value.Arg    = Op->Common.Next;
339                }
340            }
341
342            /* Search the parent list */
343
344            else while (Prev)
345            {
346                /* Traverse all siblings in the parent's argument list */
347
348                Next = Prev->Common.Next;
349                if (Next == Op)
350                {
351                    if (ReplacementOp)
352                    {
353                        ReplacementOp->Common.Parent    = Op->Common.Parent;
354                        ReplacementOp->Common.Value.Arg = NULL;
355                        ReplacementOp->Common.Node      = Op->Common.Node;
356                        Prev->Common.Next               = ReplacementOp;
357                        ReplacementOp->Common.Next      = Op->Common.Next;
358                        Next = NULL;
359                    }
360                    else
361                    {
362                        Prev->Common.Next = Op->Common.Next;
363                        Next = NULL;
364                    }
365                }
366
367                Prev = Next;
368            }
369        }
370
371        /* Now we can actually delete the subtree rooted at op */
372
373        AcpiPsDeleteParseTree (Op);
374
375        return_VOID;
376    }
377
378    return_VOID;
379}
380
381
382/*******************************************************************************
383 *
384 * FUNCTION:    AcpiPsNextParseState
385 *
386 * PARAMETERS:  ParserState         - Current parser state object
387 *
388 * RETURN:      Status
389 *
390 * DESCRIPTION: Update the parser state based upon the return exception from
391 *              the parser callback.
392 *
393 ******************************************************************************/
394
395ACPI_STATUS
396AcpiPsNextParseState (
397    ACPI_WALK_STATE         *WalkState,
398    ACPI_PARSE_OBJECT       *Op,
399    ACPI_STATUS             CallbackStatus)
400{
401    ACPI_PARSE_STATE        *ParserState = &WalkState->ParserState;
402    ACPI_STATUS             Status = AE_CTRL_PENDING;
403
404
405    ACPI_FUNCTION_TRACE_PTR ("PsNextParseState", Op);
406
407
408    switch (CallbackStatus)
409    {
410    case AE_CTRL_TERMINATE:
411
412        /*
413         * A control method was terminated via a RETURN statement.
414         * The walk of this method is complete.
415         */
416        ParserState->Aml = ParserState->AmlEnd;
417        Status = AE_CTRL_TERMINATE;
418        break;
419
420
421    case AE_CTRL_BREAK:
422
423        ParserState->Aml = WalkState->AmlLastWhile;
424        WalkState->ControlState->Common.Value = FALSE;
425        Status = AE_CTRL_BREAK;
426        break;
427
428    case AE_CTRL_CONTINUE:
429
430
431        ParserState->Aml = WalkState->AmlLastWhile;
432        Status = AE_CTRL_CONTINUE;
433        break;
434
435    case AE_CTRL_PENDING:
436
437        ParserState->Aml = WalkState->AmlLastWhile;
438        break;
439
440#if 0
441    case AE_CTRL_SKIP:
442
443        ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd;
444        Status = AE_OK;
445        break;
446#endif
447
448    case AE_CTRL_TRUE:
449
450        /*
451         * Predicate of an IF was true, and we are at the matching ELSE.
452         * Just close out this package
453         */
454        ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState);
455        break;
456
457
458    case AE_CTRL_FALSE:
459
460        /*
461         * Either an IF/WHILE Predicate was false or we encountered a BREAK
462         * opcode.  In both cases, we do not execute the rest of the
463         * package;  We simply close out the parent (finishing the walk of
464         * this branch of the tree) and continue execution at the parent
465         * level.
466         */
467        ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd;
468
469        /* In the case of a BREAK, just force a predicate (if any) to FALSE */
470
471        WalkState->ControlState->Common.Value = FALSE;
472        Status = AE_CTRL_END;
473        break;
474
475
476    case AE_CTRL_TRANSFER:
477
478        /*
479         * A method call (invocation) -- transfer control
480         */
481        Status = AE_CTRL_TRANSFER;
482        WalkState->PrevOp = Op;
483        WalkState->MethodCallOp = Op;
484        WalkState->MethodCallNode = (Op->Common.Value.Arg)->Common.Node;
485
486        /* Will return value (if any) be used by the caller? */
487
488        WalkState->ReturnUsed = AcpiDsIsResultUsed (Op, WalkState);
489        break;
490
491
492    default:
493        Status = CallbackStatus;
494        if ((CallbackStatus & AE_CODE_MASK) == AE_CODE_CONTROL)
495        {
496            Status = AE_OK;
497        }
498        break;
499    }
500
501    return_ACPI_STATUS (Status);
502}
503
504
505/*******************************************************************************
506 *
507 * FUNCTION:    AcpiPsParseLoop
508 *
509 * PARAMETERS:  ParserState         - Current parser state object
510 *
511 * RETURN:      Status
512 *
513 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
514 *              a tree of ops.
515 *
516 ******************************************************************************/
517
518ACPI_STATUS
519AcpiPsParseLoop (
520    ACPI_WALK_STATE         *WalkState)
521{
522    ACPI_STATUS             Status = AE_OK;
523    ACPI_PARSE_OBJECT       *Op = NULL;     /* current op */
524    ACPI_PARSE_OBJECT       *Arg = NULL;
525    ACPI_PARSE_OBJECT       PreOp;
526    ACPI_PARSE_STATE        *ParserState;
527    UINT8                   *AmlOpStart = NULL;
528
529
530    ACPI_FUNCTION_TRACE_PTR ("PsParseLoop", WalkState);
531
532    if (WalkState->DescendingCallback == NULL)
533    {
534        return_ACPI_STATUS (AE_BAD_PARAMETER);
535    }
536
537
538    ParserState = &WalkState->ParserState;
539    WalkState->ArgTypes = 0;
540
541#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
542    if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART)
543    {
544        /* We are restarting a preempted control method */
545
546        if (AcpiPsHasCompletedScope (ParserState))
547        {
548            /*
549             * We must check if a predicate to an IF or WHILE statement
550             * was just completed
551             */
552            if ((ParserState->Scope->ParseScope.Op) &&
553               ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) ||
554                (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) &&
555                (WalkState->ControlState) &&
556                (WalkState->ControlState->Common.State ==
557                    ACPI_CONTROL_PREDICATE_EXECUTING))
558            {
559                /*
560                 * A predicate was just completed, get the value of the
561                 * predicate and branch based on that value
562                 */
563                WalkState->Op = NULL;
564                Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE));
565                if (ACPI_FAILURE (Status) &&
566                    ((Status & AE_CODE_MASK) != AE_CODE_CONTROL))
567                {
568                    if (Status == AE_AML_NO_RETURN_VALUE)
569                    {
570                        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
571                            "Invoked method did not return a value, %s\n",
572                            AcpiFormatException (Status)));
573
574                    }
575                    ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "GetPredicate Failed, %s\n",
576                        AcpiFormatException (Status)));
577                    return_ACPI_STATUS (Status);
578                }
579
580                Status = AcpiPsNextParseState (WalkState, Op, Status);
581            }
582
583            AcpiPsPopScope (ParserState, &Op,
584                &WalkState->ArgTypes, &WalkState->ArgCount);
585            ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
586        }
587        else if (WalkState->PrevOp)
588        {
589            /* We were in the middle of an op */
590
591            Op = WalkState->PrevOp;
592            WalkState->ArgTypes = WalkState->PrevArgTypes;
593        }
594    }
595#endif
596
597    /*
598     * Iterative parsing loop, while there is more aml to process:
599     */
600    while ((ParserState->Aml < ParserState->AmlEnd) || (Op))
601    {
602        AmlOpStart = ParserState->Aml;
603        if (!Op)
604        {
605            /* Get the next opcode from the AML stream */
606
607            WalkState->AmlOffset = ACPI_PTR_DIFF (ParserState->Aml,
608                                                  ParserState->AmlStart);
609            WalkState->Opcode    = AcpiPsPeekOpcode (ParserState);
610
611            /*
612             * First cut to determine what we have found:
613             * 1) A valid AML opcode
614             * 2) A name string
615             * 3) An unknown/invalid opcode
616             */
617            WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
618            switch (WalkState->OpInfo->Class)
619            {
620            case AML_CLASS_ASCII:
621            case AML_CLASS_PREFIX:
622                /*
623                 * Starts with a valid prefix or ASCII char, this is a name
624                 * string.  Convert the bare name string to a namepath.
625                 */
626                WalkState->Opcode = AML_INT_NAMEPATH_OP;
627                WalkState->ArgTypes = ARGP_NAMESTRING;
628                break;
629
630            case AML_CLASS_UNKNOWN:
631
632                /* The opcode is unrecognized.  Just skip unknown opcodes */
633
634                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
635                    "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
636                    WalkState->Opcode, ParserState->Aml, WalkState->AmlOffset));
637
638                ACPI_DUMP_BUFFER (ParserState->Aml, 128);
639
640                /* Assume one-byte bad opcode */
641
642                ParserState->Aml++;
643                continue;
644
645            default:
646
647                /* Found opcode info, this is a normal opcode */
648
649                ParserState->Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
650                WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
651                break;
652            }
653
654            /* Create Op structure and append to parent's argument list */
655
656            if (WalkState->OpInfo->Flags & AML_NAMED)
657            {
658                PreOp.Common.Value.Arg = NULL;
659                PreOp.Common.AmlOpcode = WalkState->Opcode;
660
661                /*
662                 * Get and append arguments until we find the node that contains
663                 * the name (the type ARGP_NAME).
664                 */
665                while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
666                      (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
667                {
668                    Status = AcpiPsGetNextArg (WalkState, ParserState,
669                                GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
670                    if (ACPI_FAILURE (Status))
671                    {
672                        goto CloseThisOp;
673                    }
674
675                    AcpiPsAppendArg (&PreOp, Arg);
676                    INCREMENT_ARG_LIST (WalkState->ArgTypes);
677                }
678
679                /* Make sure that we found a NAME and didn't run out of arguments */
680
681                if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
682                {
683                    return_ACPI_STATUS (AE_AML_NO_OPERAND);
684                }
685
686                /* We know that this arg is a name, move to next arg */
687
688                INCREMENT_ARG_LIST (WalkState->ArgTypes);
689
690                /*
691                 * Find the object.  This will either insert the object into
692                 * the namespace or simply look it up
693                 */
694                WalkState->Op = NULL;
695
696                Status = WalkState->DescendingCallback (WalkState, &Op);
697                if (ACPI_FAILURE (Status))
698                {
699                    ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "During name lookup/catalog, %s\n",
700                            AcpiFormatException (Status)));
701                    goto CloseThisOp;
702                }
703
704                if (Op == NULL)
705                {
706                    continue;
707                }
708
709                Status = AcpiPsNextParseState (WalkState, Op, Status);
710                if (Status == AE_CTRL_PENDING)
711                {
712                    Status = AE_OK;
713                    goto CloseThisOp;
714                }
715
716                if (ACPI_FAILURE (Status))
717                {
718                    goto CloseThisOp;
719                }
720
721                AcpiPsAppendArg (Op, PreOp.Common.Value.Arg);
722                AcpiGbl_Depth++;
723
724                if (Op->Common.AmlOpcode == AML_REGION_OP)
725                {
726                    /*
727                     * Defer final parsing of an OperationRegion body,
728                     * because we don't have enough info in the first pass
729                     * to parse it correctly (i.e., there may be method
730                     * calls within the TermArg elements of the body.)
731                     *
732                     * However, we must continue parsing because
733                     * the opregion is not a standalone package --
734                     * we don't know where the end is at this point.
735                     *
736                     * (Length is unknown until parse of the body complete)
737                     */
738                    Op->Named.Data    = AmlOpStart;
739                    Op->Named.Length  = 0;
740                }
741            }
742            else
743            {
744                /* Not a named opcode, just allocate Op and append to parent */
745
746                WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
747                Op = AcpiPsAllocOp (WalkState->Opcode);
748                if (!Op)
749                {
750                    return_ACPI_STATUS (AE_NO_MEMORY);
751                }
752
753                if (WalkState->OpInfo->Flags & AML_CREATE)
754                {
755                    /*
756                     * Backup to beginning of CreateXXXfield declaration
757                     * BodyLength is unknown until we parse the body
758                     */
759                    Op->Named.Data    = AmlOpStart;
760                    Op->Named.Length  = 0;
761                }
762
763                AcpiPsAppendArg (AcpiPsGetParentScope (ParserState), Op);
764
765                if ((WalkState->DescendingCallback != NULL))
766                {
767                    /*
768                     * Find the object.  This will either insert the object into
769                     * the namespace or simply look it up
770                     */
771                    WalkState->Op = Op;
772
773                    Status = WalkState->DescendingCallback (WalkState, &Op);
774                    Status = AcpiPsNextParseState (WalkState, Op, Status);
775                    if (Status == AE_CTRL_PENDING)
776                    {
777                        Status = AE_OK;
778                        goto CloseThisOp;
779                    }
780
781                    if (ACPI_FAILURE (Status))
782                    {
783                        goto CloseThisOp;
784                    }
785                }
786            }
787
788            Op->Common.AmlOffset = WalkState->AmlOffset;
789
790            if (WalkState->OpInfo)
791            {
792                ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
793                    "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
794                     (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name,
795                     Op, ParserState->Aml, Op->Common.AmlOffset));
796            }
797        }
798
799
800        /* Start ArgCount at zero because we don't know if there are any args yet */
801
802        WalkState->ArgCount  = 0;
803
804        if (WalkState->ArgTypes)   /* Are there any arguments that must be processed? */
805        {
806            /* Get arguments */
807
808            switch (Op->Common.AmlOpcode)
809            {
810            case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
811            case AML_WORD_OP:       /* AML_WORDDATA_ARG */
812            case AML_DWORD_OP:      /* AML_DWORDATA_ARG */
813            case AML_QWORD_OP:      /* AML_QWORDATA_ARG */
814            case AML_STRING_OP:     /* AML_ASCIICHARLIST_ARG */
815
816                /* Fill in constant or string argument directly */
817
818                AcpiPsGetNextSimpleArg (ParserState,
819                    GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op);
820                break;
821
822            case AML_INT_NAMEPATH_OP:   /* AML_NAMESTRING_ARG */
823
824                Status = AcpiPsGetNextNamepath (WalkState, ParserState, Op, 1);
825                if (ACPI_FAILURE (Status))
826                {
827                    goto CloseThisOp;
828                }
829
830                WalkState->ArgTypes = 0;
831                break;
832
833
834            default:
835
836                /* Op is not a constant or string, append each argument */
837
838                while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
839                        !WalkState->ArgCount)
840                {
841                    WalkState->AmlOffset = ACPI_PTR_DIFF (ParserState->Aml,
842                                                          ParserState->AmlStart);
843                    Status = AcpiPsGetNextArg (WalkState, ParserState,
844                                GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
845                    if (ACPI_FAILURE (Status))
846                    {
847                        goto CloseThisOp;
848                    }
849
850                    if (Arg)
851                    {
852                        Arg->Common.AmlOffset = WalkState->AmlOffset;
853                        AcpiPsAppendArg (Op, Arg);
854                    }
855                    INCREMENT_ARG_LIST (WalkState->ArgTypes);
856                }
857
858                switch (Op->Common.AmlOpcode)
859                {
860                case AML_METHOD_OP:
861
862                    /* For a method, save the length and address of the body */
863
864                    /*
865                     * Skip parsing of control method or opregion body,
866                     * because we don't have enough info in the first pass
867                     * to parse them correctly.
868                     */
869                    Op->Named.Data   = ParserState->Aml;
870                    Op->Named.Length = (UINT32) (ParserState->PkgEnd - ParserState->Aml);
871                    /*
872                     * Skip body of method.  For OpRegions, we must continue
873                     * parsing because the opregion is not a standalone
874                     * package (We don't know where the end is).
875                     */
876                    ParserState->Aml    = ParserState->PkgEnd;
877                    WalkState->ArgCount = 0;
878                    break;
879
880                case AML_BUFFER_OP:
881                case AML_PACKAGE_OP:
882                case AML_VAR_PACKAGE_OP:
883
884                    if ((Op->Common.Parent) &&
885                        (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
886                        (WalkState->DescendingCallback != AcpiDsExecBeginOp))
887                    {
888                        /*
889                         * Skip parsing of
890                         * because we don't have enough info in the first pass
891                         * to parse them correctly.
892                         */
893                        Op->Named.Data   = AmlOpStart;
894                        Op->Named.Length = (UINT32) (ParserState->PkgEnd - AmlOpStart);
895                        /*
896                         * Skip body
897                         */
898                        ParserState->Aml    = ParserState->PkgEnd;
899                        WalkState->ArgCount = 0;
900                    }
901                    break;
902
903                case AML_WHILE_OP:
904
905                    if (WalkState->ControlState)
906                    {
907                        WalkState->ControlState->Control.PackageEnd = ParserState->PkgEnd;
908                    }
909                    break;
910
911                default:
912                    /* No action for all other opcodes */
913                    break;
914                }
915                break;
916            }
917        }
918
919        /* Check for arguments that need to be processed */
920
921        if (WalkState->ArgCount)
922        {
923            /* There are arguments (complex ones), push Op and prepare for argument */
924
925            Status = AcpiPsPushScope (ParserState, Op,
926                        WalkState->ArgTypes, WalkState->ArgCount);
927            if (ACPI_FAILURE (Status))
928            {
929                return_ACPI_STATUS (Status);
930            }
931            Op = NULL;
932            continue;
933        }
934
935        /* All arguments have been processed -- Op is complete, prepare for next */
936
937        WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
938        if (WalkState->OpInfo->Flags & AML_NAMED)
939        {
940            if (AcpiGbl_Depth)
941            {
942                AcpiGbl_Depth--;
943            }
944
945            if (Op->Common.AmlOpcode == AML_REGION_OP)
946            {
947                /*
948                 * Skip parsing of control method or opregion body,
949                 * because we don't have enough info in the first pass
950                 * to parse them correctly.
951                 *
952                 * Completed parsing an OpRegion declaration, we now
953                 * know the length.
954                 */
955                Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
956            }
957        }
958
959        if (WalkState->OpInfo->Flags & AML_CREATE)
960        {
961            /*
962             * Backup to beginning of CreateXXXfield declaration (1 for
963             * Opcode)
964             *
965             * BodyLength is unknown until we parse the body
966             */
967            Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
968        }
969
970        /* This op complete, notify the dispatcher */
971
972        if (WalkState->AscendingCallback != NULL)
973        {
974            WalkState->Op     = Op;
975            WalkState->Opcode = Op->Common.AmlOpcode;
976
977            Status = WalkState->AscendingCallback (WalkState);
978            Status = AcpiPsNextParseState (WalkState, Op, Status);
979            if (Status == AE_CTRL_PENDING)
980            {
981                Status = AE_OK;
982                goto CloseThisOp;
983            }
984        }
985
986
987CloseThisOp:
988        /*
989         * Finished one argument of the containing scope
990         */
991        ParserState->Scope->ParseScope.ArgCount--;
992
993        /* Close this Op (will result in parse subtree deletion) */
994
995        AcpiPsCompleteThisOp (WalkState, Op);
996        Op = NULL;
997
998        switch (Status)
999        {
1000        case AE_OK:
1001            break;
1002
1003
1004        case AE_CTRL_TRANSFER:
1005
1006            /*
1007             * We are about to transfer to a called method.
1008             */
1009            WalkState->PrevOp = Op;
1010            WalkState->PrevArgTypes = WalkState->ArgTypes;
1011            return_ACPI_STATUS (Status);
1012
1013
1014        case AE_CTRL_END:
1015
1016            AcpiPsPopScope (ParserState, &Op,
1017                &WalkState->ArgTypes, &WalkState->ArgCount);
1018
1019            if (Op)
1020            {
1021                WalkState->Op     = Op;
1022                WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1023                WalkState->Opcode = Op->Common.AmlOpcode;
1024
1025                Status = WalkState->AscendingCallback (WalkState);
1026                Status = AcpiPsNextParseState (WalkState, Op, Status);
1027
1028                AcpiPsCompleteThisOp (WalkState, Op);
1029                Op = NULL;
1030            }
1031            Status = AE_OK;
1032            break;
1033
1034
1035        case AE_CTRL_BREAK:
1036        case AE_CTRL_CONTINUE:
1037
1038            /* Pop off scopes until we find the While */
1039
1040            while (!Op || (Op->Common.AmlOpcode != AML_WHILE_OP))
1041            {
1042                AcpiPsPopScope (ParserState, &Op,
1043                    &WalkState->ArgTypes, &WalkState->ArgCount);
1044            }
1045
1046            /* Close this iteration of the While loop */
1047
1048            WalkState->Op     = Op;
1049            WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1050            WalkState->Opcode = Op->Common.AmlOpcode;
1051
1052            Status = WalkState->AscendingCallback (WalkState);
1053            Status = AcpiPsNextParseState (WalkState, Op, Status);
1054
1055            AcpiPsCompleteThisOp (WalkState, Op);
1056            Op = NULL;
1057
1058            Status = AE_OK;
1059            break;
1060
1061
1062        case AE_CTRL_TERMINATE:
1063
1064            Status = AE_OK;
1065
1066            /* Clean up */
1067            do
1068            {
1069                if (Op)
1070                {
1071                    AcpiPsCompleteThisOp (WalkState, Op);
1072                }
1073                AcpiPsPopScope (ParserState, &Op,
1074                    &WalkState->ArgTypes, &WalkState->ArgCount);
1075
1076            } while (Op);
1077
1078            return_ACPI_STATUS (Status);
1079
1080
1081        default:  /* All other non-AE_OK status */
1082
1083            do
1084            {
1085                if (Op)
1086                {
1087                    AcpiPsCompleteThisOp (WalkState, Op);
1088                }
1089                AcpiPsPopScope (ParserState, &Op,
1090                    &WalkState->ArgTypes, &WalkState->ArgCount);
1091
1092            } while (Op);
1093
1094
1095            /*
1096             * TBD: Cleanup parse ops on error
1097             */
1098#if 0
1099            if (Op == NULL)
1100            {
1101                AcpiPsPopScope (ParserState, &Op,
1102                    &WalkState->ArgTypes, &WalkState->ArgCount);
1103            }
1104#endif
1105            WalkState->PrevOp = Op;
1106            WalkState->PrevArgTypes = WalkState->ArgTypes;
1107            return_ACPI_STATUS (Status);
1108        }
1109
1110        /* This scope complete? */
1111
1112        if (AcpiPsHasCompletedScope (ParserState))
1113        {
1114            AcpiPsPopScope (ParserState, &Op,
1115                &WalkState->ArgTypes, &WalkState->ArgCount);
1116            ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
1117        }
1118        else
1119        {
1120            Op = NULL;
1121        }
1122
1123    } /* while ParserState->Aml */
1124
1125
1126    /*
1127     * Complete the last Op (if not completed), and clear the scope stack.
1128     * It is easily possible to end an AML "package" with an unbounded number
1129     * of open scopes (such as when several ASL blocks are closed with
1130     * sequential closing braces).  We want to terminate each one cleanly.
1131     */
1132    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
1133    do
1134    {
1135        if (Op)
1136        {
1137            if (WalkState->AscendingCallback != NULL)
1138            {
1139                WalkState->Op     = Op;
1140                WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1141                WalkState->Opcode = Op->Common.AmlOpcode;
1142
1143                Status = WalkState->AscendingCallback (WalkState);
1144                Status = AcpiPsNextParseState (WalkState, Op, Status);
1145                if (Status == AE_CTRL_PENDING)
1146                {
1147                    Status = AE_OK;
1148                    goto CloseThisOp;
1149                }
1150
1151                if (Status == AE_CTRL_TERMINATE)
1152                {
1153                    Status = AE_OK;
1154
1155                    /* Clean up */
1156                    do
1157                    {
1158                        if (Op)
1159                        {
1160                            AcpiPsCompleteThisOp (WalkState, Op);
1161                        }
1162
1163                        AcpiPsPopScope (ParserState, &Op,
1164                            &WalkState->ArgTypes, &WalkState->ArgCount);
1165
1166                    } while (Op);
1167
1168                    return_ACPI_STATUS (Status);
1169                }
1170
1171                else if (ACPI_FAILURE (Status))
1172                {
1173                    AcpiPsCompleteThisOp (WalkState, Op);
1174                    return_ACPI_STATUS (Status);
1175                }
1176            }
1177
1178            AcpiPsCompleteThisOp (WalkState, Op);
1179        }
1180
1181        AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes,
1182            &WalkState->ArgCount);
1183
1184    } while (Op);
1185
1186    return_ACPI_STATUS (Status);
1187}
1188
1189
1190/*******************************************************************************
1191 *
1192 * FUNCTION:    AcpiPsParseAml
1193 *
1194 * PARAMETERS:  StartScope      - The starting point of the parse.  Becomes the
1195 *                                root of the parsed op tree.
1196 *              Aml             - Pointer to the raw AML code to parse
1197 *              AmlSize         - Length of the AML to parse
1198 *
1199 *
1200 * RETURN:      Status
1201 *
1202 * DESCRIPTION: Parse raw AML and return a tree of ops
1203 *
1204 ******************************************************************************/
1205
1206ACPI_STATUS
1207AcpiPsParseAml (
1208    ACPI_WALK_STATE         *WalkState)
1209{
1210    ACPI_STATUS             Status;
1211    ACPI_STATUS             TerminateStatus;
1212    ACPI_THREAD_STATE       *Thread;
1213    ACPI_THREAD_STATE       *PrevWalkList = AcpiGbl_CurrentWalkList;
1214    ACPI_WALK_STATE         *PreviousWalkState;
1215
1216
1217    ACPI_FUNCTION_TRACE ("PsParseAml");
1218
1219    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Entered with WalkState=%p Aml=%p size=%X\n",
1220        WalkState, WalkState->ParserState.Aml, WalkState->ParserState.AmlSize));
1221
1222
1223    /* Create and initialize a new thread state */
1224
1225    Thread = AcpiUtCreateThreadState ();
1226    if (!Thread)
1227    {
1228        return_ACPI_STATUS (AE_NO_MEMORY);
1229    }
1230
1231    WalkState->Thread = Thread;
1232    AcpiDsPushWalkState (WalkState, Thread);
1233
1234    /*
1235     * This global allows the AML debugger to get a handle to the currently
1236     * executing control method.
1237     */
1238    AcpiGbl_CurrentWalkList = Thread;
1239
1240    /*
1241     * Execute the walk loop as long as there is a valid Walk State.  This
1242     * handles nested control method invocations without recursion.
1243     */
1244    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState));
1245
1246    Status = AE_OK;
1247    while (WalkState)
1248    {
1249        if (ACPI_SUCCESS (Status))
1250        {
1251            /*
1252             * The ParseLoop executes AML until the method terminates
1253             * or calls another method.
1254             */
1255            Status = AcpiPsParseLoop (WalkState);
1256        }
1257
1258        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
1259            "Completed one call to walk loop, %s State=%p\n",
1260            AcpiFormatException (Status), WalkState));
1261
1262        if (Status == AE_CTRL_TRANSFER)
1263        {
1264            /*
1265             * A method call was detected.
1266             * Transfer control to the called control method
1267             */
1268            Status = AcpiDsCallControlMethod (Thread, WalkState, NULL);
1269
1270            /*
1271             * If the transfer to the new method method call worked, a new walk
1272             * state was created -- get it
1273             */
1274            WalkState = AcpiDsGetCurrentWalkState (Thread);
1275            continue;
1276        }
1277        else if (Status == AE_CTRL_TERMINATE)
1278        {
1279            Status = AE_OK;
1280        }
1281        else if (Status != AE_OK)
1282        {
1283            ACPI_REPORT_METHOD_ERROR ("Method execution failed",
1284                WalkState->MethodNode, NULL, Status);
1285        }
1286
1287        /* We are done with this walk, move on to the parent if any */
1288
1289        WalkState = AcpiDsPopWalkState (Thread);
1290
1291        /* Reset the current scope to the beginning of scope stack */
1292
1293        AcpiDsScopeStackClear (WalkState);
1294
1295        /*
1296         * If we just returned from the execution of a control method,
1297         * there's lots of cleanup to do
1298         */
1299        if ((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE)
1300        {
1301            TerminateStatus = AcpiDsTerminateControlMethod (WalkState);
1302            if (ACPI_FAILURE (TerminateStatus))
1303            {
1304                ACPI_REPORT_ERROR ((
1305                    "Could not terminate control method properly\n"));
1306
1307                /* Ignore error and continue */
1308            }
1309        }
1310
1311        /* Delete this walk state and all linked control states */
1312
1313        AcpiPsCleanupScope (&WalkState->ParserState);
1314
1315        PreviousWalkState = WalkState;
1316
1317        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "ReturnValue=%p, State=%p\n",
1318            WalkState->ReturnDesc, WalkState));
1319
1320        /* Check if we have restarted a preempted walk */
1321
1322        WalkState = AcpiDsGetCurrentWalkState (Thread);
1323        if (WalkState)
1324        {
1325            if (ACPI_SUCCESS (Status))
1326            {
1327                /*
1328                 * There is another walk state, restart it.
1329                 * If the method return value is not used by the parent,
1330                 * The object is deleted
1331                 */
1332                Status = AcpiDsRestartControlMethod (WalkState,
1333                            PreviousWalkState->ReturnDesc);
1334                if (ACPI_SUCCESS (Status))
1335                {
1336                    WalkState->WalkType |= ACPI_WALK_METHOD_RESTART;
1337                }
1338            }
1339            else
1340            {
1341                /* On error, delete any return object */
1342
1343                AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);
1344            }
1345        }
1346
1347        /*
1348         * Just completed a 1st-level method, save the final internal return
1349         * value (if any)
1350         */
1351        else if (PreviousWalkState->CallerReturnDesc)
1352        {
1353            *(PreviousWalkState->CallerReturnDesc) = PreviousWalkState->ReturnDesc; /* NULL if no return value */
1354        }
1355        else if (PreviousWalkState->ReturnDesc)
1356        {
1357            /* Caller doesn't want it, must delete it */
1358
1359            AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);
1360        }
1361
1362        AcpiDsDeleteWalkState (PreviousWalkState);
1363    }
1364
1365    /* Normal exit */
1366
1367    AcpiExReleaseAllMutexes (Thread);
1368    AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread));
1369    AcpiGbl_CurrentWalkList = PrevWalkList;
1370    return_ACPI_STATUS (Status);
1371}
1372
1373
1374