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