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