checkdirs() was being passed the wrong mount point, resulting in a panic
[dragonfly.git] / sys / contrib / dev / acpica-unix-20050309 / interpreter / parser / psparse.c
blobf3b97576973b28a9ca428d005d6d95b5e6cdeadd
1 /******************************************************************************
3 * Module Name: psparse - Parser top level AML parse routines
4 * $Revision: 148 $
6 *****************************************************************************/
8 /******************************************************************************
10 * 1. Copyright Notice
12 * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13 * All rights reserved.
15 * 2. License
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.
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
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;
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
41 * 3. Conditions
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.
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.
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.
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
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.
81 * 4. Disclaimer and Export Compliance
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.
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.
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.
115 *****************************************************************************/
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[]
127 #include "acpi.h"
128 #include "acparser.h"
129 #include "acdispat.h"
130 #include "amlcode.h"
131 #include "acnamesp.h"
132 #include "acinterp.h"
134 #define _COMPONENT ACPI_PARSER
135 ACPI_MODULE_NAME ("psparse")
138 static UINT32 AcpiGbl_Depth = 0;
141 /*******************************************************************************
143 * FUNCTION: AcpiPsGetOpcodeSize
145 * PARAMETERS: Opcode - An AML opcode
147 * RETURN: Size of the opcode, in bytes (1 or 2)
149 * DESCRIPTION: Get the size of the current opcode.
151 ******************************************************************************/
153 UINT32
154 AcpiPsGetOpcodeSize (
155 UINT32 Opcode)
158 /* Extended (2-byte) opcode if > 255 */
160 if (Opcode > 0x00FF)
162 return (2);
165 /* Otherwise, just a single byte opcode */
167 return (1);
171 /*******************************************************************************
173 * FUNCTION: AcpiPsPeekOpcode
175 * PARAMETERS: ParserState - A parser state object
177 * RETURN: Status
179 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer)
181 ******************************************************************************/
183 UINT16
184 AcpiPsPeekOpcode (
185 ACPI_PARSE_STATE *ParserState)
187 UINT8 *Aml;
188 UINT16 Opcode;
191 Aml = ParserState->Aml;
192 Opcode = (UINT16) ACPI_GET8 (Aml);
195 if (Opcode == AML_EXTOP)
197 /* Extended opcode */
199 Aml++;
200 Opcode = (UINT16) ((Opcode << 8) | ACPI_GET8 (Aml));
203 return (Opcode);
207 /*******************************************************************************
209 * FUNCTION: AcpiPsCompleteThisOp
211 * PARAMETERS: WalkState - Current State
212 * Op - Op to complete
214 * RETURN: None.
216 * DESCRIPTION: Perform any cleanup at the completion of an Op.
218 ******************************************************************************/
220 void
221 AcpiPsCompleteThisOp (
222 ACPI_WALK_STATE *WalkState,
223 ACPI_PARSE_OBJECT *Op)
225 ACPI_PARSE_OBJECT *Prev;
226 ACPI_PARSE_OBJECT *Next;
227 const ACPI_OPCODE_INFO *ParentInfo;
228 ACPI_PARSE_OBJECT *ReplacementOp = NULL;
231 ACPI_FUNCTION_TRACE_PTR ("PsCompleteThisOp", Op);
234 /* Check for null Op, can happen if AML code is corrupt */
236 if (!Op)
238 return_VOID;
241 /* Delete this op and the subtree below it if asked to */
243 if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
244 (WalkState->OpInfo->Class == AML_CLASS_ARGUMENT))
246 return_VOID;
249 /* Make sure that we only delete this subtree */
251 if (Op->Common.Parent)
254 * Check if we need to replace the operator and its subtree
255 * with a return value op (placeholder op)
257 ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
259 switch (ParentInfo->Class)
261 case AML_CLASS_CONTROL:
262 break;
264 case AML_CLASS_CREATE:
267 * These opcodes contain TermArg operands. The current
268 * op must be replaced by a placeholder return op
270 ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
271 if (!ReplacementOp)
273 goto Cleanup;
275 break;
277 case AML_CLASS_NAMED_OBJECT:
280 * These opcodes contain TermArg operands. The current
281 * op must be replaced by a placeholder return op
283 if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) ||
284 (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) ||
285 (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) ||
286 (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
287 (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
289 ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
290 if (!ReplacementOp)
292 goto Cleanup;
296 if ((Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
297 (WalkState->DescendingCallback != AcpiDsExecBeginOp))
300 if ((Op->Common.AmlOpcode == AML_BUFFER_OP) ||
301 (Op->Common.AmlOpcode == AML_PACKAGE_OP) ||
302 (Op->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
304 ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode);
305 if (!ReplacementOp)
307 goto Cleanup;
310 ReplacementOp->Named.Data = Op->Named.Data;
311 ReplacementOp->Named.Length = Op->Named.Length;
314 break;
316 default:
317 ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
318 if (!ReplacementOp)
320 goto Cleanup;
324 /* We must unlink this op from the parent tree */
326 Prev = Op->Common.Parent->Common.Value.Arg;
327 if (Prev == Op)
329 /* This op is the first in the list */
331 if (ReplacementOp)
333 ReplacementOp->Common.Parent = Op->Common.Parent;
334 ReplacementOp->Common.Value.Arg = NULL;
335 ReplacementOp->Common.Node = Op->Common.Node;
336 Op->Common.Parent->Common.Value.Arg = ReplacementOp;
337 ReplacementOp->Common.Next = Op->Common.Next;
339 else
341 Op->Common.Parent->Common.Value.Arg = Op->Common.Next;
345 /* Search the parent list */
347 else while (Prev)
349 /* Traverse all siblings in the parent's argument list */
351 Next = Prev->Common.Next;
352 if (Next == Op)
354 if (ReplacementOp)
356 ReplacementOp->Common.Parent = Op->Common.Parent;
357 ReplacementOp->Common.Value.Arg = NULL;
358 ReplacementOp->Common.Node = Op->Common.Node;
359 Prev->Common.Next = ReplacementOp;
360 ReplacementOp->Common.Next = Op->Common.Next;
361 Next = NULL;
363 else
365 Prev->Common.Next = Op->Common.Next;
366 Next = NULL;
370 Prev = Next;
375 Cleanup:
377 /* Now we can actually delete the subtree rooted at op */
379 AcpiPsDeleteParseTree (Op);
380 return_VOID;
384 /*******************************************************************************
386 * FUNCTION: AcpiPsNextParseState
388 * PARAMETERS: ParserState - Current parser state object
390 * RETURN: Status
392 * DESCRIPTION: Update the parser state based upon the return exception from
393 * the parser callback.
395 ******************************************************************************/
397 ACPI_STATUS
398 AcpiPsNextParseState (
399 ACPI_WALK_STATE *WalkState,
400 ACPI_PARSE_OBJECT *Op,
401 ACPI_STATUS CallbackStatus)
403 ACPI_PARSE_STATE *ParserState = &WalkState->ParserState;
404 ACPI_STATUS Status = AE_CTRL_PENDING;
407 ACPI_FUNCTION_TRACE_PTR ("PsNextParseState", Op);
410 switch (CallbackStatus)
412 case AE_CTRL_TERMINATE:
415 * A control method was terminated via a RETURN statement.
416 * The walk of this method is complete.
418 ParserState->Aml = ParserState->AmlEnd;
419 Status = AE_CTRL_TERMINATE;
420 break;
423 case AE_CTRL_BREAK:
425 ParserState->Aml = WalkState->AmlLastWhile;
426 WalkState->ControlState->Common.Value = FALSE;
427 Status = AE_CTRL_BREAK;
428 break;
430 case AE_CTRL_CONTINUE:
433 ParserState->Aml = WalkState->AmlLastWhile;
434 Status = AE_CTRL_CONTINUE;
435 break;
437 case AE_CTRL_PENDING:
439 ParserState->Aml = WalkState->AmlLastWhile;
440 break;
442 #if 0
443 case AE_CTRL_SKIP:
445 ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd;
446 Status = AE_OK;
447 break;
448 #endif
450 case AE_CTRL_TRUE:
453 * Predicate of an IF was true, and we are at the matching ELSE.
454 * Just close out this package
456 ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState);
457 break;
460 case AE_CTRL_FALSE:
463 * Either an IF/WHILE Predicate was false or we encountered a BREAK
464 * opcode. In both cases, we do not execute the rest of the
465 * package; We simply close out the parent (finishing the walk of
466 * this branch of the tree) and continue execution at the parent
467 * level.
469 ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd;
471 /* In the case of a BREAK, just force a predicate (if any) to FALSE */
473 WalkState->ControlState->Common.Value = FALSE;
474 Status = AE_CTRL_END;
475 break;
478 case AE_CTRL_TRANSFER:
481 * A method call (invocation) -- transfer control
483 Status = AE_CTRL_TRANSFER;
484 WalkState->PrevOp = Op;
485 WalkState->MethodCallOp = Op;
486 WalkState->MethodCallNode = (Op->Common.Value.Arg)->Common.Node;
488 /* Will return value (if any) be used by the caller? */
490 WalkState->ReturnUsed = AcpiDsIsResultUsed (Op, WalkState);
491 break;
494 default:
495 Status = CallbackStatus;
496 if ((CallbackStatus & AE_CODE_MASK) == AE_CODE_CONTROL)
498 Status = AE_OK;
500 break;
503 return_ACPI_STATUS (Status);
507 /*******************************************************************************
509 * FUNCTION: AcpiPsParseLoop
511 * PARAMETERS: ParserState - Current parser state object
513 * RETURN: Status
515 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
516 * a tree of ops.
518 ******************************************************************************/
520 ACPI_STATUS
521 AcpiPsParseLoop (
522 ACPI_WALK_STATE *WalkState)
524 ACPI_STATUS Status = AE_OK;
525 ACPI_PARSE_OBJECT *Op = NULL; /* current op */
526 ACPI_PARSE_OBJECT *Arg = NULL;
527 ACPI_PARSE_OBJECT *PreOp = NULL;
528 ACPI_PARSE_STATE *ParserState;
529 UINT8 *AmlOpStart = NULL;
532 ACPI_FUNCTION_TRACE_PTR ("PsParseLoop", WalkState);
534 if (WalkState->DescendingCallback == NULL)
536 return_ACPI_STATUS (AE_BAD_PARAMETER);
539 ParserState = &WalkState->ParserState;
540 WalkState->ArgTypes = 0;
542 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
543 if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART)
545 /* We are restarting a preempted control method */
547 if (AcpiPsHasCompletedScope (ParserState))
550 * We must check if a predicate to an IF or WHILE statement
551 * was just completed
553 if ((ParserState->Scope->ParseScope.Op) &&
554 ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) ||
555 (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) &&
556 (WalkState->ControlState) &&
557 (WalkState->ControlState->Common.State ==
558 ACPI_CONTROL_PREDICATE_EXECUTING))
561 * A predicate was just completed, get the value of the
562 * predicate and branch based on that value
564 WalkState->Op = NULL;
565 Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE));
566 if (ACPI_FAILURE (Status) &&
567 ((Status & AE_CODE_MASK) != AE_CODE_CONTROL))
569 if (Status == AE_AML_NO_RETURN_VALUE)
571 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
572 "Invoked method did not return a value, %s\n",
573 AcpiFormatException (Status)));
576 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "GetPredicate Failed, %s\n",
577 AcpiFormatException (Status)));
578 return_ACPI_STATUS (Status);
581 Status = AcpiPsNextParseState (WalkState, Op, Status);
584 AcpiPsPopScope (ParserState, &Op,
585 &WalkState->ArgTypes, &WalkState->ArgCount);
586 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
588 else if (WalkState->PrevOp)
590 /* We were in the middle of an op */
592 Op = WalkState->PrevOp;
593 WalkState->ArgTypes = WalkState->PrevArgTypes;
596 #endif
599 * Iterative parsing loop, while there is more aml to process:
601 while ((ParserState->Aml < ParserState->AmlEnd) || (Op))
603 AmlOpStart = ParserState->Aml;
604 if (!Op)
606 /* Get the next opcode from the AML stream */
608 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (ParserState->Aml,
609 ParserState->AmlStart);
610 WalkState->Opcode = AcpiPsPeekOpcode (ParserState);
613 * First cut to determine what we have found:
614 * 1) A valid AML opcode
615 * 2) A name string
616 * 3) An unknown/invalid opcode
618 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
619 switch (WalkState->OpInfo->Class)
621 case AML_CLASS_ASCII:
622 case AML_CLASS_PREFIX:
624 * Starts with a valid prefix or ASCII char, this is a name
625 * string. Convert the bare name string to a namepath.
627 WalkState->Opcode = AML_INT_NAMEPATH_OP;
628 WalkState->ArgTypes = ARGP_NAMESTRING;
629 break;
631 case AML_CLASS_UNKNOWN:
633 /* The opcode is unrecognized. Just skip unknown opcodes */
635 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
636 "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
637 WalkState->Opcode, ParserState->Aml, WalkState->AmlOffset));
639 ACPI_DUMP_BUFFER (ParserState->Aml, 128);
641 /* Assume one-byte bad opcode */
643 ParserState->Aml++;
644 continue;
646 default:
648 /* Found opcode info, this is a normal opcode */
650 ParserState->Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
651 WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
652 break;
655 /* Create Op structure and append to parent's argument list */
657 if (WalkState->OpInfo->Flags & AML_NAMED)
659 /* Allocate a new PreOp if necessary */
661 if (!PreOp)
663 PreOp = AcpiPsAllocOp (WalkState->Opcode);
664 if (!PreOp)
666 Status = AE_NO_MEMORY;
667 goto CloseThisOp;
671 PreOp->Common.Value.Arg = NULL;
672 PreOp->Common.AmlOpcode = WalkState->Opcode;
675 * Get and append arguments until we find the node that contains
676 * the name (the type ARGP_NAME).
678 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
679 (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
681 Status = AcpiPsGetNextArg (WalkState, ParserState,
682 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
683 if (ACPI_FAILURE (Status))
685 goto CloseThisOp;
688 AcpiPsAppendArg (PreOp, Arg);
689 INCREMENT_ARG_LIST (WalkState->ArgTypes);
692 /* Make sure that we found a NAME and didn't run out of arguments */
694 if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
696 Status = AE_AML_NO_OPERAND;
697 goto CloseThisOp;
700 /* We know that this arg is a name, move to next arg */
702 INCREMENT_ARG_LIST (WalkState->ArgTypes);
705 * Find the object. This will either insert the object into
706 * the namespace or simply look it up
708 WalkState->Op = NULL;
710 Status = WalkState->DescendingCallback (WalkState, &Op);
711 if (ACPI_FAILURE (Status))
713 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "During name lookup/catalog, %s\n",
714 AcpiFormatException (Status)));
715 goto CloseThisOp;
718 if (Op == NULL)
720 continue;
723 Status = AcpiPsNextParseState (WalkState, Op, Status);
724 if (Status == AE_CTRL_PENDING)
726 Status = AE_OK;
727 goto CloseThisOp;
730 if (ACPI_FAILURE (Status))
732 goto CloseThisOp;
735 AcpiPsAppendArg (Op, PreOp->Common.Value.Arg);
736 AcpiGbl_Depth++;
738 if (Op->Common.AmlOpcode == AML_REGION_OP)
741 * Defer final parsing of an OperationRegion body,
742 * because we don't have enough info in the first pass
743 * to parse it correctly (i.e., there may be method
744 * calls within the TermArg elements of the body.)
746 * However, we must continue parsing because
747 * the opregion is not a standalone package --
748 * we don't know where the end is at this point.
750 * (Length is unknown until parse of the body complete)
752 Op->Named.Data = AmlOpStart;
753 Op->Named.Length = 0;
756 else
758 /* Not a named opcode, just allocate Op and append to parent */
760 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
761 Op = AcpiPsAllocOp (WalkState->Opcode);
762 if (!Op)
764 Status = AE_NO_MEMORY;
765 goto CloseThisOp;
768 if (WalkState->OpInfo->Flags & AML_CREATE)
771 * Backup to beginning of CreateXXXfield declaration
772 * BodyLength is unknown until we parse the body
774 Op->Named.Data = AmlOpStart;
775 Op->Named.Length = 0;
778 AcpiPsAppendArg (AcpiPsGetParentScope (ParserState), Op);
780 if ((WalkState->DescendingCallback != NULL))
783 * Find the object. This will either insert the object into
784 * the namespace or simply look it up
786 WalkState->Op = Op;
788 Status = WalkState->DescendingCallback (WalkState, &Op);
789 Status = AcpiPsNextParseState (WalkState, Op, Status);
790 if (Status == AE_CTRL_PENDING)
792 Status = AE_OK;
793 goto CloseThisOp;
796 if (ACPI_FAILURE (Status))
798 goto CloseThisOp;
803 Op->Common.AmlOffset = WalkState->AmlOffset;
805 if (WalkState->OpInfo)
807 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
808 "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
809 (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name,
810 Op, ParserState->Aml, Op->Common.AmlOffset));
815 /* Start ArgCount at zero because we don't know if there are any args yet */
817 WalkState->ArgCount = 0;
819 if (WalkState->ArgTypes) /* Are there any arguments that must be processed? */
821 /* Get arguments */
823 switch (Op->Common.AmlOpcode)
825 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
826 case AML_WORD_OP: /* AML_WORDDATA_ARG */
827 case AML_DWORD_OP: /* AML_DWORDATA_ARG */
828 case AML_QWORD_OP: /* AML_QWORDATA_ARG */
829 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
831 /* Fill in constant or string argument directly */
833 AcpiPsGetNextSimpleArg (ParserState,
834 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op);
835 break;
837 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
839 Status = AcpiPsGetNextNamepath (WalkState, ParserState, Op, 1);
840 if (ACPI_FAILURE (Status))
842 goto CloseThisOp;
845 WalkState->ArgTypes = 0;
846 break;
848 default:
850 /* Op is not a constant or string, append each argument to the Op */
852 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
853 !WalkState->ArgCount)
855 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (ParserState->Aml,
856 ParserState->AmlStart);
857 Status = AcpiPsGetNextArg (WalkState, ParserState,
858 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
859 if (ACPI_FAILURE (Status))
861 goto CloseThisOp;
864 if (Arg)
866 Arg->Common.AmlOffset = WalkState->AmlOffset;
867 AcpiPsAppendArg (Op, Arg);
869 INCREMENT_ARG_LIST (WalkState->ArgTypes);
872 /* Special processing for certain opcodes */
874 switch (Op->Common.AmlOpcode)
876 case AML_METHOD_OP:
879 * Skip parsing of control method
880 * because we don't have enough info in the first pass
881 * to parse it correctly.
883 * Save the length and address of the body
885 Op->Named.Data = ParserState->Aml;
886 Op->Named.Length = (UINT32) (ParserState->PkgEnd - ParserState->Aml);
888 /* Skip body of method */
890 ParserState->Aml = ParserState->PkgEnd;
891 WalkState->ArgCount = 0;
892 break;
894 case AML_BUFFER_OP:
895 case AML_PACKAGE_OP:
896 case AML_VAR_PACKAGE_OP:
898 if ((Op->Common.Parent) &&
899 (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
900 (WalkState->DescendingCallback != AcpiDsExecBeginOp))
903 * Skip parsing of Buffers and Packages
904 * because we don't have enough info in the first pass
905 * to parse them correctly.
907 Op->Named.Data = AmlOpStart;
908 Op->Named.Length = (UINT32) (ParserState->PkgEnd - AmlOpStart);
910 /* Skip body */
912 ParserState->Aml = ParserState->PkgEnd;
913 WalkState->ArgCount = 0;
915 break;
917 case AML_WHILE_OP:
919 if (WalkState->ControlState)
921 WalkState->ControlState->Control.PackageEnd = ParserState->PkgEnd;
923 break;
925 default:
927 /* No action for all other opcodes */
928 break;
930 break;
934 /* Check for arguments that need to be processed */
936 if (WalkState->ArgCount)
938 /* There are arguments (complex ones), push Op and prepare for argument */
940 Status = AcpiPsPushScope (ParserState, Op,
941 WalkState->ArgTypes, WalkState->ArgCount);
942 if (ACPI_FAILURE (Status))
944 goto CloseThisOp;
946 Op = NULL;
947 continue;
950 /* All arguments have been processed -- Op is complete, prepare for next */
952 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
953 if (WalkState->OpInfo->Flags & AML_NAMED)
955 if (AcpiGbl_Depth)
957 AcpiGbl_Depth--;
960 if (Op->Common.AmlOpcode == AML_REGION_OP)
963 * Skip parsing of control method or opregion body,
964 * because we don't have enough info in the first pass
965 * to parse them correctly.
967 * Completed parsing an OpRegion declaration, we now
968 * know the length.
970 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
974 if (WalkState->OpInfo->Flags & AML_CREATE)
977 * Backup to beginning of CreateXXXfield declaration (1 for
978 * Opcode)
980 * BodyLength is unknown until we parse the body
982 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
985 /* This op complete, notify the dispatcher */
987 if (WalkState->AscendingCallback != NULL)
989 WalkState->Op = Op;
990 WalkState->Opcode = Op->Common.AmlOpcode;
992 Status = WalkState->AscendingCallback (WalkState);
993 Status = AcpiPsNextParseState (WalkState, Op, Status);
994 if (Status == AE_CTRL_PENDING)
996 Status = AE_OK;
997 goto CloseThisOp;
1002 CloseThisOp:
1004 * Finished one argument of the containing scope
1006 ParserState->Scope->ParseScope.ArgCount--;
1008 /* Close this Op (will result in parse subtree deletion) */
1010 AcpiPsCompleteThisOp (WalkState, Op);
1011 Op = NULL;
1012 if (PreOp)
1014 AcpiPsFreeOp (PreOp);
1015 PreOp = NULL;
1018 switch (Status)
1020 case AE_OK:
1021 break;
1024 case AE_CTRL_TRANSFER:
1027 * We are about to transfer to a called method.
1029 WalkState->PrevOp = Op;
1030 WalkState->PrevArgTypes = WalkState->ArgTypes;
1031 return_ACPI_STATUS (Status);
1034 case AE_CTRL_END:
1036 AcpiPsPopScope (ParserState, &Op,
1037 &WalkState->ArgTypes, &WalkState->ArgCount);
1039 if (Op)
1041 WalkState->Op = Op;
1042 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1043 WalkState->Opcode = Op->Common.AmlOpcode;
1045 Status = WalkState->AscendingCallback (WalkState);
1046 Status = AcpiPsNextParseState (WalkState, Op, Status);
1048 AcpiPsCompleteThisOp (WalkState, Op);
1049 Op = NULL;
1051 Status = AE_OK;
1052 break;
1055 case AE_CTRL_BREAK:
1056 case AE_CTRL_CONTINUE:
1058 /* Pop off scopes until we find the While */
1060 while (!Op || (Op->Common.AmlOpcode != AML_WHILE_OP))
1062 AcpiPsPopScope (ParserState, &Op,
1063 &WalkState->ArgTypes, &WalkState->ArgCount);
1066 /* Close this iteration of the While loop */
1068 WalkState->Op = Op;
1069 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1070 WalkState->Opcode = Op->Common.AmlOpcode;
1072 Status = WalkState->AscendingCallback (WalkState);
1073 Status = AcpiPsNextParseState (WalkState, Op, Status);
1075 AcpiPsCompleteThisOp (WalkState, Op);
1076 Op = NULL;
1078 Status = AE_OK;
1079 break;
1082 case AE_CTRL_TERMINATE:
1084 Status = AE_OK;
1086 /* Clean up */
1089 if (Op)
1091 AcpiPsCompleteThisOp (WalkState, Op);
1093 AcpiPsPopScope (ParserState, &Op,
1094 &WalkState->ArgTypes, &WalkState->ArgCount);
1096 } while (Op);
1098 return_ACPI_STATUS (Status);
1101 default: /* All other non-AE_OK status */
1105 if (Op)
1107 AcpiPsCompleteThisOp (WalkState, Op);
1109 AcpiPsPopScope (ParserState, &Op,
1110 &WalkState->ArgTypes, &WalkState->ArgCount);
1112 } while (Op);
1116 * TBD: Cleanup parse ops on error
1118 #if 0
1119 if (Op == NULL)
1121 AcpiPsPopScope (ParserState, &Op,
1122 &WalkState->ArgTypes, &WalkState->ArgCount);
1124 #endif
1125 WalkState->PrevOp = Op;
1126 WalkState->PrevArgTypes = WalkState->ArgTypes;
1127 return_ACPI_STATUS (Status);
1130 /* This scope complete? */
1132 if (AcpiPsHasCompletedScope (ParserState))
1134 AcpiPsPopScope (ParserState, &Op,
1135 &WalkState->ArgTypes, &WalkState->ArgCount);
1136 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
1138 else
1140 Op = NULL;
1143 } /* while ParserState->Aml */
1147 * Complete the last Op (if not completed), and clear the scope stack.
1148 * It is easily possible to end an AML "package" with an unbounded number
1149 * of open scopes (such as when several ASL blocks are closed with
1150 * sequential closing braces). We want to terminate each one cleanly.
1152 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
1155 if (Op)
1157 if (WalkState->AscendingCallback != NULL)
1159 WalkState->Op = Op;
1160 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1161 WalkState->Opcode = Op->Common.AmlOpcode;
1163 Status = WalkState->AscendingCallback (WalkState);
1164 Status = AcpiPsNextParseState (WalkState, Op, Status);
1165 if (Status == AE_CTRL_PENDING)
1167 Status = AE_OK;
1168 goto CloseThisOp;
1171 if (Status == AE_CTRL_TERMINATE)
1173 Status = AE_OK;
1175 /* Clean up */
1178 if (Op)
1180 AcpiPsCompleteThisOp (WalkState, Op);
1183 AcpiPsPopScope (ParserState, &Op,
1184 &WalkState->ArgTypes, &WalkState->ArgCount);
1186 } while (Op);
1188 return_ACPI_STATUS (Status);
1191 else if (ACPI_FAILURE (Status))
1193 AcpiPsCompleteThisOp (WalkState, Op);
1194 return_ACPI_STATUS (Status);
1198 AcpiPsCompleteThisOp (WalkState, Op);
1201 AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes,
1202 &WalkState->ArgCount);
1204 } while (Op);
1206 return_ACPI_STATUS (Status);
1210 /*******************************************************************************
1212 * FUNCTION: AcpiPsParseAml
1214 * PARAMETERS: StartScope - The starting point of the parse. Becomes the
1215 * root of the parsed op tree.
1216 * Aml - Pointer to the raw AML code to parse
1217 * AmlSize - Length of the AML to parse
1220 * RETURN: Status
1222 * DESCRIPTION: Parse raw AML and return a tree of ops
1224 ******************************************************************************/
1226 ACPI_STATUS
1227 AcpiPsParseAml (
1228 ACPI_WALK_STATE *WalkState)
1230 ACPI_STATUS Status;
1231 ACPI_STATUS TerminateStatus;
1232 ACPI_THREAD_STATE *Thread;
1233 ACPI_THREAD_STATE *PrevWalkList = AcpiGbl_CurrentWalkList;
1234 ACPI_WALK_STATE *PreviousWalkState;
1237 ACPI_FUNCTION_TRACE ("PsParseAml");
1239 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Entered with WalkState=%p Aml=%p size=%X\n",
1240 WalkState, WalkState->ParserState.Aml, WalkState->ParserState.AmlSize));
1243 /* Create and initialize a new thread state */
1245 Thread = AcpiUtCreateThreadState ();
1246 if (!Thread)
1248 return_ACPI_STATUS (AE_NO_MEMORY);
1251 WalkState->Thread = Thread;
1252 AcpiDsPushWalkState (WalkState, Thread);
1255 * This global allows the AML debugger to get a handle to the currently
1256 * executing control method.
1258 AcpiGbl_CurrentWalkList = Thread;
1261 * Execute the walk loop as long as there is a valid Walk State. This
1262 * handles nested control method invocations without recursion.
1264 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState));
1266 Status = AE_OK;
1267 while (WalkState)
1269 if (ACPI_SUCCESS (Status))
1272 * The ParseLoop executes AML until the method terminates
1273 * or calls another method.
1275 Status = AcpiPsParseLoop (WalkState);
1278 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
1279 "Completed one call to walk loop, %s State=%p\n",
1280 AcpiFormatException (Status), WalkState));
1282 if (Status == AE_CTRL_TRANSFER)
1285 * A method call was detected.
1286 * Transfer control to the called control method
1288 Status = AcpiDsCallControlMethod (Thread, WalkState, NULL);
1291 * If the transfer to the new method method call worked, a new walk
1292 * state was created -- get it
1294 WalkState = AcpiDsGetCurrentWalkState (Thread);
1295 continue;
1297 else if (Status == AE_CTRL_TERMINATE)
1299 Status = AE_OK;
1301 else if ((Status != AE_OK) && (WalkState->MethodDesc))
1303 ACPI_REPORT_METHOD_ERROR ("Method execution failed",
1304 WalkState->MethodNode, NULL, Status);
1306 /* Check for possible multi-thread reentrancy problem */
1308 if ((Status == AE_ALREADY_EXISTS) &&
1309 (!WalkState->MethodDesc->Method.Semaphore))
1312 * This method is marked NotSerialized, but it tried to create a named
1313 * object, causing the second thread entrance to fail. We will workaround
1314 * this by marking the method permanently as Serialized.
1316 WalkState->MethodDesc->Method.MethodFlags |= AML_METHOD_SERIALIZED;
1317 WalkState->MethodDesc->Method.Concurrency = 1;
1321 if (WalkState->MethodDesc)
1323 /* Decrement the thread count on the method parse tree */
1325 if (WalkState->MethodDesc->Method.ThreadCount)
1327 WalkState->MethodDesc->Method.ThreadCount--;
1331 /* We are done with this walk, move on to the parent if any */
1333 WalkState = AcpiDsPopWalkState (Thread);
1335 /* Reset the current scope to the beginning of scope stack */
1337 AcpiDsScopeStackClear (WalkState);
1340 * If we just returned from the execution of a control method,
1341 * there's lots of cleanup to do
1343 if ((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE)
1345 TerminateStatus = AcpiDsTerminateControlMethod (WalkState);
1346 if (ACPI_FAILURE (TerminateStatus))
1348 ACPI_REPORT_ERROR ((
1349 "Could not terminate control method properly\n"));
1351 /* Ignore error and continue */
1355 /* Delete this walk state and all linked control states */
1357 AcpiPsCleanupScope (&WalkState->ParserState);
1359 PreviousWalkState = WalkState;
1361 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "ReturnValue=%p, ImplicitValue=%p State=%p\n",
1362 WalkState->ReturnDesc, WalkState->ImplicitReturnObj, WalkState));
1364 /* Check if we have restarted a preempted walk */
1366 WalkState = AcpiDsGetCurrentWalkState (Thread);
1367 if (WalkState)
1369 if (ACPI_SUCCESS (Status))
1372 * There is another walk state, restart it.
1373 * If the method return value is not used by the parent,
1374 * The object is deleted
1376 if (!PreviousWalkState->ReturnDesc)
1378 Status = AcpiDsRestartControlMethod (WalkState,
1379 PreviousWalkState->ImplicitReturnObj);
1381 else
1384 * We have a valid return value, delete any implicit
1385 * return value.
1387 AcpiDsClearImplicitReturn (PreviousWalkState);
1389 Status = AcpiDsRestartControlMethod (WalkState,
1390 PreviousWalkState->ReturnDesc);
1392 if (ACPI_SUCCESS (Status))
1394 WalkState->WalkType |= ACPI_WALK_METHOD_RESTART;
1397 else
1399 /* On error, delete any return object */
1401 AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);
1406 * Just completed a 1st-level method, save the final internal return
1407 * value (if any)
1409 else if (PreviousWalkState->CallerReturnDesc)
1411 if (PreviousWalkState->ImplicitReturnObj)
1413 *(PreviousWalkState->CallerReturnDesc) = PreviousWalkState->ImplicitReturnObj;
1415 else
1417 /* NULL if no return value */
1419 *(PreviousWalkState->CallerReturnDesc) = PreviousWalkState->ReturnDesc;
1422 else
1424 if (PreviousWalkState->ReturnDesc)
1426 /* Caller doesn't want it, must delete it */
1428 AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);
1430 if (PreviousWalkState->ImplicitReturnObj)
1432 /* Caller doesn't want it, must delete it */
1434 AcpiUtRemoveReference (PreviousWalkState->ImplicitReturnObj);
1438 AcpiDsDeleteWalkState (PreviousWalkState);
1441 /* Normal exit */
1443 AcpiExReleaseAllMutexes (Thread);
1444 AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread));
1445 AcpiGbl_CurrentWalkList = PrevWalkList;
1446 return_ACPI_STATUS (Status);