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