1 /******************************************************************************
3 * Module Name: psloop - Main AML parse loop
5 *****************************************************************************/
7 /******************************************************************************
11 * Some or all of this work - Copyright (c) 1999 - 2015, Intel Corp.
12 * All rights reserved.
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
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
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;
37 * The above copyright and patent license is granted only if the following
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.
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
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
72 * 3.4. Intel retains all right, title, and interest in and to the Original
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.
80 * 4. Disclaimer and Export Compliance
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
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
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.
114 *****************************************************************************/
117 * Parse the AML and build an operation tree as most interpreters, (such as
118 * Perl) do. Parsing is done by hand rather than with a YACC generated parser
119 * to tightly constrain stack and dynamic memory usage. Parsing is kept
120 * flexible and the code fairly compact by parsing based on a list of AML
121 * opcode templates in AmlOpInfo[].
125 #include "accommon.h"
126 #include "acinterp.h"
127 #include "acparser.h"
128 #include "acdispat.h"
131 #define _COMPONENT ACPI_PARSER
132 ACPI_MODULE_NAME ("psloop")
135 /* Local prototypes */
139 ACPI_WALK_STATE
*WalkState
,
141 ACPI_PARSE_OBJECT
*Op
);
144 AcpiPsLinkModuleCode (
145 ACPI_PARSE_OBJECT
*ParentOp
,
148 ACPI_OWNER_ID OwnerId
);
151 /*******************************************************************************
153 * FUNCTION: AcpiPsGetArguments
155 * PARAMETERS: WalkState - Current state
156 * AmlOpStart - Op start in AML
161 * DESCRIPTION: Get arguments for passed Op.
163 ******************************************************************************/
167 ACPI_WALK_STATE
*WalkState
,
169 ACPI_PARSE_OBJECT
*Op
)
171 ACPI_STATUS Status
= AE_OK
;
172 ACPI_PARSE_OBJECT
*Arg
= NULL
;
173 const ACPI_OPCODE_INFO
*OpInfo
;
176 ACPI_FUNCTION_TRACE_PTR (PsGetArguments
, WalkState
);
179 switch (Op
->Common
.AmlOpcode
)
181 case AML_BYTE_OP
: /* AML_BYTEDATA_ARG */
182 case AML_WORD_OP
: /* AML_WORDDATA_ARG */
183 case AML_DWORD_OP
: /* AML_DWORDATA_ARG */
184 case AML_QWORD_OP
: /* AML_QWORDATA_ARG */
185 case AML_STRING_OP
: /* AML_ASCIICHARLIST_ARG */
187 /* Fill in constant or string argument directly */
189 AcpiPsGetNextSimpleArg (&(WalkState
->ParserState
),
190 GET_CURRENT_ARG_TYPE (WalkState
->ArgTypes
), Op
);
193 case AML_INT_NAMEPATH_OP
: /* AML_NAMESTRING_ARG */
195 Status
= AcpiPsGetNextNamepath (WalkState
, &(WalkState
->ParserState
), Op
, 1);
196 if (ACPI_FAILURE (Status
))
198 return_ACPI_STATUS (Status
);
201 WalkState
->ArgTypes
= 0;
206 * Op is not a constant or string, append each argument to the Op
208 while (GET_CURRENT_ARG_TYPE (WalkState
->ArgTypes
) && !WalkState
->ArgCount
)
210 WalkState
->Aml
= WalkState
->ParserState
.Aml
;
212 Status
= AcpiPsGetNextArg (WalkState
, &(WalkState
->ParserState
),
213 GET_CURRENT_ARG_TYPE (WalkState
->ArgTypes
), &Arg
);
214 if (ACPI_FAILURE (Status
))
216 return_ACPI_STATUS (Status
);
221 AcpiPsAppendArg (Op
, Arg
);
224 INCREMENT_ARG_LIST (WalkState
->ArgTypes
);
229 * Handle executable code at "module-level". This refers to
230 * executable opcodes that appear outside of any control method.
232 if ((WalkState
->PassNumber
<= ACPI_IMODE_LOAD_PASS2
) &&
233 ((WalkState
->ParseFlags
& ACPI_PARSE_DISASSEMBLE
) == 0))
236 * We want to skip If/Else/While constructs during Pass1 because we
237 * want to actually conditionally execute the code during Pass2.
239 * Except for disassembly, where we always want to walk the
240 * If/Else/While packages
242 switch (Op
->Common
.AmlOpcode
)
248 * Currently supported module-level opcodes are:
249 * IF/ELSE/WHILE. These appear to be the most common,
250 * and easiest to support since they open an AML
253 if (WalkState
->PassNumber
== ACPI_IMODE_LOAD_PASS1
)
255 AcpiPsLinkModuleCode (Op
->Common
.Parent
, AmlOpStart
,
256 (UINT32
) (WalkState
->ParserState
.PkgEnd
- AmlOpStart
),
260 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE
,
261 "Pass1: Skipping an If/Else/While body\n"));
263 /* Skip body of if/else/while in pass 1 */
265 WalkState
->ParserState
.Aml
= WalkState
->ParserState
.PkgEnd
;
266 WalkState
->ArgCount
= 0;
271 * Check for an unsupported executable opcode at module
272 * level. We must be in PASS1, the parent must be a SCOPE,
273 * The opcode class must be EXECUTE, and the opcode must
274 * not be an argument to another opcode.
276 if ((WalkState
->PassNumber
== ACPI_IMODE_LOAD_PASS1
) &&
277 (Op
->Common
.Parent
->Common
.AmlOpcode
== AML_SCOPE_OP
))
279 OpInfo
= AcpiPsGetOpcodeInfo (Op
->Common
.AmlOpcode
);
280 if ((OpInfo
->Class
== AML_CLASS_EXECUTE
) &&
283 ACPI_WARNING ((AE_INFO
,
284 "Unsupported module-level executable opcode "
285 "0x%.2X at table offset 0x%.4X",
286 Op
->Common
.AmlOpcode
,
287 (UINT32
) (ACPI_PTR_DIFF (AmlOpStart
,
288 WalkState
->ParserState
.AmlStart
) +
289 sizeof (ACPI_TABLE_HEADER
))));
296 /* Special processing for certain opcodes */
298 switch (Op
->Common
.AmlOpcode
)
302 * Skip parsing of control method because we don't have enough
303 * info in the first pass to parse it correctly.
305 * Save the length and address of the body
307 Op
->Named
.Data
= WalkState
->ParserState
.Aml
;
308 Op
->Named
.Length
= (UINT32
)
309 (WalkState
->ParserState
.PkgEnd
- WalkState
->ParserState
.Aml
);
311 /* Skip body of method */
313 WalkState
->ParserState
.Aml
= WalkState
->ParserState
.PkgEnd
;
314 WalkState
->ArgCount
= 0;
319 case AML_VAR_PACKAGE_OP
:
321 if ((Op
->Common
.Parent
) &&
322 (Op
->Common
.Parent
->Common
.AmlOpcode
== AML_NAME_OP
) &&
323 (WalkState
->PassNumber
<= ACPI_IMODE_LOAD_PASS2
))
326 * Skip parsing of Buffers and Packages because we don't have
327 * enough info in the first pass to parse them correctly.
329 Op
->Named
.Data
= AmlOpStart
;
330 Op
->Named
.Length
= (UINT32
)
331 (WalkState
->ParserState
.PkgEnd
- AmlOpStart
);
335 WalkState
->ParserState
.Aml
= WalkState
->ParserState
.PkgEnd
;
336 WalkState
->ArgCount
= 0;
342 if (WalkState
->ControlState
)
344 WalkState
->ControlState
->Control
.PackageEnd
=
345 WalkState
->ParserState
.PkgEnd
;
351 /* No action for all other opcodes */
359 return_ACPI_STATUS (AE_OK
);
363 /*******************************************************************************
365 * FUNCTION: AcpiPsLinkModuleCode
367 * PARAMETERS: ParentOp - Parent parser op
368 * AmlStart - Pointer to the AML
369 * AmlLength - Length of executable AML
370 * OwnerId - OwnerId of module level code
374 * DESCRIPTION: Wrap the module-level code with a method object and link the
375 * object to the global list. Note, the mutex field of the method
376 * object is used to link multiple module-level code objects.
378 ******************************************************************************/
381 AcpiPsLinkModuleCode (
382 ACPI_PARSE_OBJECT
*ParentOp
,
385 ACPI_OWNER_ID OwnerId
)
387 ACPI_OPERAND_OBJECT
*Prev
;
388 ACPI_OPERAND_OBJECT
*Next
;
389 ACPI_OPERAND_OBJECT
*MethodObj
;
390 ACPI_NAMESPACE_NODE
*ParentNode
;
393 ACPI_FUNCTION_TRACE (PsLinkModuleCode
);
396 /* Get the tail of the list */
398 Prev
= Next
= AcpiGbl_ModuleCodeList
;
402 Next
= Next
->Method
.Mutex
;
406 * Insert the module level code into the list. Merge it if it is
407 * adjacent to the previous element.
410 ((Prev
->Method
.AmlStart
+ Prev
->Method
.AmlLength
) != AmlStart
))
412 /* Create, initialize, and link a new temporary method object */
414 MethodObj
= AcpiUtCreateInternalObject (ACPI_TYPE_METHOD
);
420 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE
,
421 "Create/Link new code block: %p\n", MethodObj
));
423 if (ParentOp
->Common
.Node
)
425 ParentNode
= ParentOp
->Common
.Node
;
429 ParentNode
= AcpiGbl_RootNode
;
432 MethodObj
->Method
.AmlStart
= AmlStart
;
433 MethodObj
->Method
.AmlLength
= AmlLength
;
434 MethodObj
->Method
.OwnerId
= OwnerId
;
435 MethodObj
->Method
.InfoFlags
|= ACPI_METHOD_MODULE_LEVEL
;
438 * Save the parent node in NextObject. This is cheating, but we
439 * don't want to expand the method object.
441 MethodObj
->Method
.NextObject
=
442 ACPI_CAST_PTR (ACPI_OPERAND_OBJECT
, ParentNode
);
446 AcpiGbl_ModuleCodeList
= MethodObj
;
450 Prev
->Method
.Mutex
= MethodObj
;
455 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE
,
456 "Appending to existing code block: %p\n", Prev
));
458 Prev
->Method
.AmlLength
+= AmlLength
;
464 /*******************************************************************************
466 * FUNCTION: AcpiPsParseLoop
468 * PARAMETERS: WalkState - Current state
472 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
475 ******************************************************************************/
479 ACPI_WALK_STATE
*WalkState
)
481 ACPI_STATUS Status
= AE_OK
;
482 ACPI_PARSE_OBJECT
*Op
= NULL
; /* current op */
483 ACPI_PARSE_STATE
*ParserState
;
484 UINT8
*AmlOpStart
= NULL
;
487 ACPI_FUNCTION_TRACE_PTR (PsParseLoop
, WalkState
);
490 if (WalkState
->DescendingCallback
== NULL
)
492 return_ACPI_STATUS (AE_BAD_PARAMETER
);
495 ParserState
= &WalkState
->ParserState
;
496 WalkState
->ArgTypes
= 0;
498 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
500 if (WalkState
->WalkType
& ACPI_WALK_METHOD_RESTART
)
502 /* We are restarting a preempted control method */
504 if (AcpiPsHasCompletedScope (ParserState
))
507 * We must check if a predicate to an IF or WHILE statement
510 if ((ParserState
->Scope
->ParseScope
.Op
) &&
511 ((ParserState
->Scope
->ParseScope
.Op
->Common
.AmlOpcode
== AML_IF_OP
) ||
512 (ParserState
->Scope
->ParseScope
.Op
->Common
.AmlOpcode
== AML_WHILE_OP
)) &&
513 (WalkState
->ControlState
) &&
514 (WalkState
->ControlState
->Common
.State
==
515 ACPI_CONTROL_PREDICATE_EXECUTING
))
518 * A predicate was just completed, get the value of the
519 * predicate and branch based on that value
521 WalkState
->Op
= NULL
;
522 Status
= AcpiDsGetPredicateValue (WalkState
, ACPI_TO_POINTER (TRUE
));
523 if (ACPI_FAILURE (Status
) &&
524 ((Status
& AE_CODE_MASK
) != AE_CODE_CONTROL
))
526 if (Status
== AE_AML_NO_RETURN_VALUE
)
528 ACPI_EXCEPTION ((AE_INFO
, Status
,
529 "Invoked method did not return a value"));
532 ACPI_EXCEPTION ((AE_INFO
, Status
, "GetPredicate Failed"));
533 return_ACPI_STATUS (Status
);
536 Status
= AcpiPsNextParseState (WalkState
, Op
, Status
);
539 AcpiPsPopScope (ParserState
, &Op
,
540 &WalkState
->ArgTypes
, &WalkState
->ArgCount
);
541 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE
, "Popped scope, Op=%p\n", Op
));
543 else if (WalkState
->PrevOp
)
545 /* We were in the middle of an op */
547 Op
= WalkState
->PrevOp
;
548 WalkState
->ArgTypes
= WalkState
->PrevArgTypes
;
553 /* Iterative parsing loop, while there is more AML to process: */
555 while ((ParserState
->Aml
< ParserState
->AmlEnd
) || (Op
))
557 AmlOpStart
= ParserState
->Aml
;
560 Status
= AcpiPsCreateOp (WalkState
, AmlOpStart
, &Op
);
561 if (ACPI_FAILURE (Status
))
563 if (Status
== AE_CTRL_PARSE_CONTINUE
)
568 if (Status
== AE_CTRL_PARSE_PENDING
)
573 if (Status
== AE_CTRL_TERMINATE
)
575 return_ACPI_STATUS (Status
);
578 Status
= AcpiPsCompleteOp (WalkState
, &Op
, Status
);
579 if (ACPI_FAILURE (Status
))
581 return_ACPI_STATUS (Status
);
587 AcpiExStartTraceOpcode (Op
, WalkState
);
592 * Start ArgCount at zero because we don't know if there are
595 WalkState
->ArgCount
= 0;
597 /* Are there any arguments that must be processed? */
599 if (WalkState
->ArgTypes
)
603 Status
= AcpiPsGetArguments (WalkState
, AmlOpStart
, Op
);
604 if (ACPI_FAILURE (Status
))
606 Status
= AcpiPsCompleteOp (WalkState
, &Op
, Status
);
607 if (ACPI_FAILURE (Status
))
609 return_ACPI_STATUS (Status
);
616 /* Check for arguments that need to be processed */
618 if (WalkState
->ArgCount
)
621 * There are arguments (complex ones), push Op and
622 * prepare for argument
624 Status
= AcpiPsPushScope (ParserState
, Op
,
625 WalkState
->ArgTypes
, WalkState
->ArgCount
);
626 if (ACPI_FAILURE (Status
))
628 Status
= AcpiPsCompleteOp (WalkState
, &Op
, Status
);
629 if (ACPI_FAILURE (Status
))
631 return_ACPI_STATUS (Status
);
642 * All arguments have been processed -- Op is complete,
645 WalkState
->OpInfo
= AcpiPsGetOpcodeInfo (Op
->Common
.AmlOpcode
);
646 if (WalkState
->OpInfo
->Flags
& AML_NAMED
)
648 if (Op
->Common
.AmlOpcode
== AML_REGION_OP
||
649 Op
->Common
.AmlOpcode
== AML_DATA_REGION_OP
)
652 * Skip parsing of control method or opregion body,
653 * because we don't have enough info in the first pass
654 * to parse them correctly.
656 * Completed parsing an OpRegion declaration, we now
659 Op
->Named
.Length
= (UINT32
) (ParserState
->Aml
- Op
->Named
.Data
);
663 if (WalkState
->OpInfo
->Flags
& AML_CREATE
)
666 * Backup to beginning of CreateXXXfield declaration (1 for
669 * BodyLength is unknown until we parse the body
671 Op
->Named
.Length
= (UINT32
) (ParserState
->Aml
- Op
->Named
.Data
);
674 if (Op
->Common
.AmlOpcode
== AML_BANK_FIELD_OP
)
677 * Backup to beginning of BankField declaration
679 * BodyLength is unknown until we parse the body
681 Op
->Named
.Length
= (UINT32
) (ParserState
->Aml
- Op
->Named
.Data
);
684 /* This op complete, notify the dispatcher */
686 if (WalkState
->AscendingCallback
!= NULL
)
689 WalkState
->Opcode
= Op
->Common
.AmlOpcode
;
691 Status
= WalkState
->AscendingCallback (WalkState
);
692 Status
= AcpiPsNextParseState (WalkState
, Op
, Status
);
693 if (Status
== AE_CTRL_PENDING
)
699 Status
= AcpiPsCompleteOp (WalkState
, &Op
, Status
);
700 if (ACPI_FAILURE (Status
))
702 return_ACPI_STATUS (Status
);
705 } /* while ParserState->Aml */
707 Status
= AcpiPsCompleteFinalOp (WalkState
, Op
, Status
);
708 return_ACPI_STATUS (Status
);