1 /******************************************************************************
3 * Module Name: dswstate - Dispatcher parse tree walk management routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2014, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
44 #define __DSWSTATE_C__
52 #define _COMPONENT ACPI_DISPATCHER
53 ACPI_MODULE_NAME ("dswstate")
55 /* Local prototypes */
58 AcpiDsResultStackPush (
59 ACPI_WALK_STATE *WalkState);
62 AcpiDsResultStackPop (
63 ACPI_WALK_STATE *WalkState);
66 /*******************************************************************************
68 * FUNCTION: AcpiDsResultPop
70 * PARAMETERS: Object - Where to return the popped object
71 * WalkState - Current Walk state
75 * DESCRIPTION: Pop an object off the top of this walk's result stack
77 ******************************************************************************/
81 ACPI_OPERAND_OBJECT **Object,
82 ACPI_WALK_STATE *WalkState)
85 ACPI_GENERIC_STATE *State;
89 ACPI_FUNCTION_NAME (DsResultPop);
92 State = WalkState->Results;
94 /* Incorrect state of result stack */
96 if (State && !WalkState->ResultCount)
98 ACPI_ERROR ((AE_INFO, "No results on result stack"));
99 return (AE_AML_INTERNAL);
102 if (!State && WalkState->ResultCount)
104 ACPI_ERROR ((AE_INFO, "No result state for result stack"));
105 return (AE_AML_INTERNAL);
108 /* Empty result stack */
112 ACPI_ERROR ((AE_INFO, "Result stack is empty! State=%p", WalkState));
113 return (AE_AML_NO_RETURN_VALUE);
116 /* Return object of the top element and clean that top element result stack */
118 WalkState->ResultCount--;
119 Index = (UINT32) WalkState->ResultCount % ACPI_RESULTS_FRAME_OBJ_NUM;
121 *Object = State->Results.ObjDesc [Index];
124 ACPI_ERROR ((AE_INFO, "No result objects on result stack, State=%p",
126 return (AE_AML_NO_RETURN_VALUE);
129 State->Results.ObjDesc [Index] = NULL;
132 Status = AcpiDsResultStackPop (WalkState);
133 if (ACPI_FAILURE (Status))
139 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
140 "Obj=%p [%s] Index=%X State=%p Num=%X\n", *Object,
141 AcpiUtGetObjectTypeName (*Object),
142 Index, WalkState, WalkState->ResultCount));
148 /*******************************************************************************
150 * FUNCTION: AcpiDsResultPush
152 * PARAMETERS: Object - Where to return the popped object
153 * WalkState - Current Walk state
157 * DESCRIPTION: Push an object onto the current result stack
159 ******************************************************************************/
163 ACPI_OPERAND_OBJECT *Object,
164 ACPI_WALK_STATE *WalkState)
166 ACPI_GENERIC_STATE *State;
171 ACPI_FUNCTION_NAME (DsResultPush);
174 if (WalkState->ResultCount > WalkState->ResultSize)
176 ACPI_ERROR ((AE_INFO, "Result stack is full"));
177 return (AE_AML_INTERNAL);
179 else if (WalkState->ResultCount == WalkState->ResultSize)
181 /* Extend the result stack */
183 Status = AcpiDsResultStackPush (WalkState);
184 if (ACPI_FAILURE (Status))
186 ACPI_ERROR ((AE_INFO, "Failed to extend the result stack"));
191 if (!(WalkState->ResultCount < WalkState->ResultSize))
193 ACPI_ERROR ((AE_INFO, "No free elements in result stack"));
194 return (AE_AML_INTERNAL);
197 State = WalkState->Results;
200 ACPI_ERROR ((AE_INFO, "No result stack frame during push"));
201 return (AE_AML_INTERNAL);
206 ACPI_ERROR ((AE_INFO,
207 "Null Object! Obj=%p State=%p Num=%u",
208 Object, WalkState, WalkState->ResultCount));
209 return (AE_BAD_PARAMETER);
212 /* Assign the address of object to the top free element of result stack */
214 Index = (UINT32) WalkState->ResultCount % ACPI_RESULTS_FRAME_OBJ_NUM;
215 State->Results.ObjDesc [Index] = Object;
216 WalkState->ResultCount++;
218 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
219 Object, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT *) Object),
220 WalkState, WalkState->ResultCount, WalkState->CurrentResult));
226 /*******************************************************************************
228 * FUNCTION: AcpiDsResultStackPush
230 * PARAMETERS: WalkState - Current Walk state
234 * DESCRIPTION: Push an object onto the WalkState result stack
236 ******************************************************************************/
239 AcpiDsResultStackPush (
240 ACPI_WALK_STATE *WalkState)
242 ACPI_GENERIC_STATE *State;
245 ACPI_FUNCTION_NAME (DsResultStackPush);
248 /* Check for stack overflow */
250 if (((UINT32) WalkState->ResultSize + ACPI_RESULTS_FRAME_OBJ_NUM) >
251 ACPI_RESULTS_OBJ_NUM_MAX)
253 ACPI_ERROR ((AE_INFO, "Result stack overflow: State=%p Num=%u",
254 WalkState, WalkState->ResultSize));
255 return (AE_STACK_OVERFLOW);
258 State = AcpiUtCreateGenericState ();
261 return (AE_NO_MEMORY);
264 State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_RESULT;
265 AcpiUtPushGenericState (&WalkState->Results, State);
267 /* Increase the length of the result stack by the length of frame */
269 WalkState->ResultSize += ACPI_RESULTS_FRAME_OBJ_NUM;
271 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Results=%p State=%p\n",
278 /*******************************************************************************
280 * FUNCTION: AcpiDsResultStackPop
282 * PARAMETERS: WalkState - Current Walk state
286 * DESCRIPTION: Pop an object off of the WalkState result stack
288 ******************************************************************************/
291 AcpiDsResultStackPop (
292 ACPI_WALK_STATE *WalkState)
294 ACPI_GENERIC_STATE *State;
297 ACPI_FUNCTION_NAME (DsResultStackPop);
300 /* Check for stack underflow */
302 if (WalkState->Results == NULL)
304 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Result stack underflow - State=%p\n",
306 return (AE_AML_NO_OPERAND);
309 if (WalkState->ResultSize < ACPI_RESULTS_FRAME_OBJ_NUM)
311 ACPI_ERROR ((AE_INFO, "Insufficient result stack size"));
312 return (AE_AML_INTERNAL);
315 State = AcpiUtPopGenericState (&WalkState->Results);
316 AcpiUtDeleteGenericState (State);
318 /* Decrease the length of result stack by the length of frame */
320 WalkState->ResultSize -= ACPI_RESULTS_FRAME_OBJ_NUM;
322 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
323 "Result=%p RemainingResults=%X State=%p\n",
324 State, WalkState->ResultCount, WalkState));
330 /*******************************************************************************
332 * FUNCTION: AcpiDsObjStackPush
334 * PARAMETERS: Object - Object to push
335 * WalkState - Current Walk state
339 * DESCRIPTION: Push an object onto this walk's object/operand stack
341 ******************************************************************************/
346 ACPI_WALK_STATE *WalkState)
348 ACPI_FUNCTION_NAME (DsObjStackPush);
351 /* Check for stack overflow */
353 if (WalkState->NumOperands >= ACPI_OBJ_NUM_OPERANDS)
355 ACPI_ERROR ((AE_INFO,
356 "Object stack overflow! Obj=%p State=%p #Ops=%u",
357 Object, WalkState, WalkState->NumOperands));
358 return (AE_STACK_OVERFLOW);
361 /* Put the object onto the stack */
363 WalkState->Operands [WalkState->OperandIndex] = Object;
364 WalkState->NumOperands++;
366 /* For the usual order of filling the operand stack */
368 WalkState->OperandIndex++;
370 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
371 Object, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT *) Object),
372 WalkState, WalkState->NumOperands));
378 /*******************************************************************************
380 * FUNCTION: AcpiDsObjStackPop
382 * PARAMETERS: PopCount - Number of objects/entries to pop
383 * WalkState - Current Walk state
387 * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
388 * deleted by this routine.
390 ******************************************************************************/
395 ACPI_WALK_STATE *WalkState)
400 ACPI_FUNCTION_NAME (DsObjStackPop);
403 for (i = 0; i < PopCount; i++)
405 /* Check for stack underflow */
407 if (WalkState->NumOperands == 0)
409 ACPI_ERROR ((AE_INFO,
410 "Object stack underflow! Count=%X State=%p #Ops=%u",
411 PopCount, WalkState, WalkState->NumOperands));
412 return (AE_STACK_UNDERFLOW);
415 /* Just set the stack entry to null */
417 WalkState->NumOperands--;
418 WalkState->Operands [WalkState->NumOperands] = NULL;
421 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%u\n",
422 PopCount, WalkState, WalkState->NumOperands));
428 /*******************************************************************************
430 * FUNCTION: AcpiDsObjStackPopAndDelete
432 * PARAMETERS: PopCount - Number of objects/entries to pop
433 * WalkState - Current Walk state
437 * DESCRIPTION: Pop this walk's object stack and delete each object that is
440 ******************************************************************************/
443 AcpiDsObjStackPopAndDelete (
445 ACPI_WALK_STATE *WalkState)
448 ACPI_OPERAND_OBJECT *ObjDesc;
451 ACPI_FUNCTION_NAME (DsObjStackPopAndDelete);
459 for (i = (INT32) PopCount - 1; i >= 0; i--)
461 if (WalkState->NumOperands == 0)
466 /* Pop the stack and delete an object if present in this stack entry */
468 WalkState->NumOperands--;
469 ObjDesc = WalkState->Operands [i];
472 AcpiUtRemoveReference (WalkState->Operands [i]);
473 WalkState->Operands [i] = NULL;
477 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
478 PopCount, WalkState, WalkState->NumOperands));
482 /*******************************************************************************
484 * FUNCTION: AcpiDsGetCurrentWalkState
486 * PARAMETERS: Thread - Get current active state for this Thread
488 * RETURN: Pointer to the current walk state
490 * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
493 ******************************************************************************/
496 AcpiDsGetCurrentWalkState (
497 ACPI_THREAD_STATE *Thread)
499 ACPI_FUNCTION_NAME (DsGetCurrentWalkState);
507 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Current WalkState %p\n",
508 Thread->WalkStateList));
510 return (Thread->WalkStateList);
514 /*******************************************************************************
516 * FUNCTION: AcpiDsPushWalkState
518 * PARAMETERS: WalkState - State to push
519 * Thread - Thread state object
523 * DESCRIPTION: Place the Thread state at the head of the state list
525 ******************************************************************************/
528 AcpiDsPushWalkState (
529 ACPI_WALK_STATE *WalkState,
530 ACPI_THREAD_STATE *Thread)
532 ACPI_FUNCTION_TRACE (DsPushWalkState);
535 WalkState->Next = Thread->WalkStateList;
536 Thread->WalkStateList = WalkState;
542 /*******************************************************************************
544 * FUNCTION: AcpiDsPopWalkState
546 * PARAMETERS: Thread - Current thread state
548 * RETURN: A WalkState object popped from the thread's stack
550 * DESCRIPTION: Remove and return the walkstate object that is at the head of
551 * the walk stack for the given walk list. NULL indicates that
554 ******************************************************************************/
558 ACPI_THREAD_STATE *Thread)
560 ACPI_WALK_STATE *WalkState;
563 ACPI_FUNCTION_TRACE (DsPopWalkState);
566 WalkState = Thread->WalkStateList;
570 /* Next walk state becomes the current walk state */
572 Thread->WalkStateList = WalkState->Next;
575 * Don't clear the NEXT field, this serves as an indicator
576 * that there is a parent WALK STATE
577 * Do Not: WalkState->Next = NULL;
581 return_PTR (WalkState);
585 /*******************************************************************************
587 * FUNCTION: AcpiDsCreateWalkState
589 * PARAMETERS: OwnerId - ID for object creation
590 * Origin - Starting point for this walk
591 * MethodDesc - Method object
592 * Thread - Current thread state
594 * RETURN: Pointer to the new walk state.
596 * DESCRIPTION: Allocate and initialize a new walk state. The current walk
597 * state is set to this new state.
599 ******************************************************************************/
602 AcpiDsCreateWalkState (
603 ACPI_OWNER_ID OwnerId,
604 ACPI_PARSE_OBJECT *Origin,
605 ACPI_OPERAND_OBJECT *MethodDesc,
606 ACPI_THREAD_STATE *Thread)
608 ACPI_WALK_STATE *WalkState;
611 ACPI_FUNCTION_TRACE (DsCreateWalkState);
614 WalkState = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_WALK_STATE));
620 WalkState->DescriptorType = ACPI_DESC_TYPE_WALK;
621 WalkState->MethodDesc = MethodDesc;
622 WalkState->OwnerId = OwnerId;
623 WalkState->Origin = Origin;
624 WalkState->Thread = Thread;
626 WalkState->ParserState.StartOp = Origin;
628 /* Init the method args/local */
630 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
631 AcpiDsMethodDataInit (WalkState);
634 /* Put the new state at the head of the walk list */
638 AcpiDsPushWalkState (WalkState, Thread);
641 return_PTR (WalkState);
645 /*******************************************************************************
647 * FUNCTION: AcpiDsInitAmlWalk
649 * PARAMETERS: WalkState - New state to be initialized
650 * Op - Current parse op
651 * MethodNode - Control method NS node, if any
652 * AmlStart - Start of AML
653 * AmlLength - Length of AML
654 * Info - Method info block (params, etc.)
655 * PassNumber - 1, 2, or 3
659 * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
661 ******************************************************************************/
665 ACPI_WALK_STATE *WalkState,
666 ACPI_PARSE_OBJECT *Op,
667 ACPI_NAMESPACE_NODE *MethodNode,
670 ACPI_EVALUATE_INFO *Info,
674 ACPI_PARSE_STATE *ParserState = &WalkState->ParserState;
675 ACPI_PARSE_OBJECT *ExtraOp;
678 ACPI_FUNCTION_TRACE (DsInitAmlWalk);
681 WalkState->ParserState.Aml =
682 WalkState->ParserState.AmlStart = AmlStart;
683 WalkState->ParserState.AmlEnd =
684 WalkState->ParserState.PkgEnd = AmlStart + AmlLength;
686 /* The NextOp of the NextWalk will be the beginning of the method */
688 WalkState->NextOp = NULL;
689 WalkState->PassNumber = PassNumber;
693 WalkState->Params = Info->Parameters;
694 WalkState->CallerReturnDesc = &Info->ReturnObject;
697 Status = AcpiPsInitScope (&WalkState->ParserState, Op);
698 if (ACPI_FAILURE (Status))
700 return_ACPI_STATUS (Status);
705 WalkState->ParserState.StartNode = MethodNode;
706 WalkState->WalkType = ACPI_WALK_METHOD;
707 WalkState->MethodNode = MethodNode;
708 WalkState->MethodDesc = AcpiNsGetAttachedObject (MethodNode);
710 /* Push start scope on scope stack and make it current */
712 Status = AcpiDsScopeStackPush (MethodNode, ACPI_TYPE_METHOD, WalkState);
713 if (ACPI_FAILURE (Status))
715 return_ACPI_STATUS (Status);
718 /* Init the method arguments */
720 Status = AcpiDsMethodDataInitArgs (WalkState->Params,
721 ACPI_METHOD_NUM_ARGS, WalkState);
722 if (ACPI_FAILURE (Status))
724 return_ACPI_STATUS (Status);
730 * Setup the current scope.
731 * Find a Named Op that has a namespace node associated with it.
732 * search upwards from this Op. Current scope is the first
733 * Op with a namespace node.
735 ExtraOp = ParserState->StartOp;
736 while (ExtraOp && !ExtraOp->Common.Node)
738 ExtraOp = ExtraOp->Common.Parent;
743 ParserState->StartNode = NULL;
747 ParserState->StartNode = ExtraOp->Common.Node;
750 if (ParserState->StartNode)
752 /* Push start scope on scope stack and make it current */
754 Status = AcpiDsScopeStackPush (ParserState->StartNode,
755 ParserState->StartNode->Type, WalkState);
756 if (ACPI_FAILURE (Status))
758 return_ACPI_STATUS (Status);
763 Status = AcpiDsInitCallbacks (WalkState, PassNumber);
764 return_ACPI_STATUS (Status);
768 /*******************************************************************************
770 * FUNCTION: AcpiDsDeleteWalkState
772 * PARAMETERS: WalkState - State to delete
776 * DESCRIPTION: Delete a walk state including all internal data structures
778 ******************************************************************************/
781 AcpiDsDeleteWalkState (
782 ACPI_WALK_STATE *WalkState)
784 ACPI_GENERIC_STATE *State;
787 ACPI_FUNCTION_TRACE_PTR (DsDeleteWalkState, WalkState);
795 if (WalkState->DescriptorType != ACPI_DESC_TYPE_WALK)
797 ACPI_ERROR ((AE_INFO, "%p is not a valid walk state",
802 /* There should not be any open scopes */
804 if (WalkState->ParserState.Scope)
806 ACPI_ERROR ((AE_INFO, "%p walk still has a scope list",
808 AcpiPsCleanupScope (&WalkState->ParserState);
811 /* Always must free any linked control states */
813 while (WalkState->ControlState)
815 State = WalkState->ControlState;
816 WalkState->ControlState = State->Common.Next;
818 AcpiUtDeleteGenericState (State);
821 /* Always must free any linked parse states */
823 while (WalkState->ScopeInfo)
825 State = WalkState->ScopeInfo;
826 WalkState->ScopeInfo = State->Common.Next;
828 AcpiUtDeleteGenericState (State);
831 /* Always must free any stacked result states */
833 while (WalkState->Results)
835 State = WalkState->Results;
836 WalkState->Results = State->Common.Next;
838 AcpiUtDeleteGenericState (State);
841 ACPI_FREE (WalkState);