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