1 /******************************************************************************
3 * Module Name: dswstate - Dispatcher parse tree walk management routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2013, 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.
45 #define __DSWSTATE_C__
53 #define _COMPONENT ACPI_DISPATCHER
54 ACPI_MODULE_NAME ("dswstate")
56 /* Local prototypes */
59 AcpiDsResultStackPush (
60 ACPI_WALK_STATE
*WalkState
);
63 AcpiDsResultStackPop (
64 ACPI_WALK_STATE
*WalkState
);
67 /*******************************************************************************
69 * FUNCTION: AcpiDsResultPop
71 * PARAMETERS: Object - Where to return the popped object
72 * WalkState - Current Walk state
76 * DESCRIPTION: Pop an object off the top of this walk's result stack
78 ******************************************************************************/
82 ACPI_OPERAND_OBJECT
**Object
,
83 ACPI_WALK_STATE
*WalkState
)
86 ACPI_GENERIC_STATE
*State
;
90 ACPI_FUNCTION_NAME (DsResultPop
);
93 State
= WalkState
->Results
;
95 /* Incorrect state of result stack */
97 if (State
&& !WalkState
->ResultCount
)
99 ACPI_ERROR ((AE_INFO
, "No results on result stack"));
100 return (AE_AML_INTERNAL
);
103 if (!State
&& WalkState
->ResultCount
)
105 ACPI_ERROR ((AE_INFO
, "No result state for result stack"));
106 return (AE_AML_INTERNAL
);
109 /* Empty result stack */
113 ACPI_ERROR ((AE_INFO
, "Result stack is empty! State=%p", WalkState
));
114 return (AE_AML_NO_RETURN_VALUE
);
117 /* Return object of the top element and clean that top element result stack */
119 WalkState
->ResultCount
--;
120 Index
= (UINT32
) WalkState
->ResultCount
% ACPI_RESULTS_FRAME_OBJ_NUM
;
122 *Object
= State
->Results
.ObjDesc
[Index
];
125 ACPI_ERROR ((AE_INFO
, "No result objects on result stack, State=%p",
127 return (AE_AML_NO_RETURN_VALUE
);
130 State
->Results
.ObjDesc
[Index
] = NULL
;
133 Status
= AcpiDsResultStackPop (WalkState
);
134 if (ACPI_FAILURE (Status
))
140 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
,
141 "Obj=%p [%s] Index=%X State=%p Num=%X\n", *Object
,
142 AcpiUtGetObjectTypeName (*Object
),
143 Index
, WalkState
, WalkState
->ResultCount
));
149 /*******************************************************************************
151 * FUNCTION: AcpiDsResultPush
153 * PARAMETERS: Object - Where to return the popped object
154 * WalkState - Current Walk state
158 * DESCRIPTION: Push an object onto the current result stack
160 ******************************************************************************/
164 ACPI_OPERAND_OBJECT
*Object
,
165 ACPI_WALK_STATE
*WalkState
)
167 ACPI_GENERIC_STATE
*State
;
172 ACPI_FUNCTION_NAME (DsResultPush
);
175 if (WalkState
->ResultCount
> WalkState
->ResultSize
)
177 ACPI_ERROR ((AE_INFO
, "Result stack is full"));
178 return (AE_AML_INTERNAL
);
180 else if (WalkState
->ResultCount
== WalkState
->ResultSize
)
182 /* Extend the result stack */
184 Status
= AcpiDsResultStackPush (WalkState
);
185 if (ACPI_FAILURE (Status
))
187 ACPI_ERROR ((AE_INFO
, "Failed to extend the result stack"));
192 if (!(WalkState
->ResultCount
< WalkState
->ResultSize
))
194 ACPI_ERROR ((AE_INFO
, "No free elements in result stack"));
195 return (AE_AML_INTERNAL
);
198 State
= WalkState
->Results
;
201 ACPI_ERROR ((AE_INFO
, "No result stack frame during push"));
202 return (AE_AML_INTERNAL
);
207 ACPI_ERROR ((AE_INFO
,
208 "Null Object! Obj=%p State=%p Num=%u",
209 Object
, WalkState
, WalkState
->ResultCount
));
210 return (AE_BAD_PARAMETER
);
213 /* Assign the address of object to the top free element of result stack */
215 Index
= (UINT32
) WalkState
->ResultCount
% ACPI_RESULTS_FRAME_OBJ_NUM
;
216 State
->Results
.ObjDesc
[Index
] = Object
;
217 WalkState
->ResultCount
++;
219 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
220 Object
, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT
*) Object
),
221 WalkState
, WalkState
->ResultCount
, WalkState
->CurrentResult
));
227 /*******************************************************************************
229 * FUNCTION: AcpiDsResultStackPush
231 * PARAMETERS: WalkState - Current Walk state
235 * DESCRIPTION: Push an object onto the WalkState result stack
237 ******************************************************************************/
240 AcpiDsResultStackPush (
241 ACPI_WALK_STATE
*WalkState
)
243 ACPI_GENERIC_STATE
*State
;
246 ACPI_FUNCTION_NAME (DsResultStackPush
);
249 /* Check for stack overflow */
251 if (((UINT32
) WalkState
->ResultSize
+ ACPI_RESULTS_FRAME_OBJ_NUM
) >
252 ACPI_RESULTS_OBJ_NUM_MAX
)
254 ACPI_ERROR ((AE_INFO
, "Result stack overflow: State=%p Num=%u",
255 WalkState
, WalkState
->ResultSize
));
256 return (AE_STACK_OVERFLOW
);
259 State
= AcpiUtCreateGenericState ();
262 return (AE_NO_MEMORY
);
265 State
->Common
.DescriptorType
= ACPI_DESC_TYPE_STATE_RESULT
;
266 AcpiUtPushGenericState (&WalkState
->Results
, State
);
268 /* Increase the length of the result stack by the length of frame */
270 WalkState
->ResultSize
+= ACPI_RESULTS_FRAME_OBJ_NUM
;
272 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Results=%p State=%p\n",
279 /*******************************************************************************
281 * FUNCTION: AcpiDsResultStackPop
283 * PARAMETERS: WalkState - Current Walk state
287 * DESCRIPTION: Pop an object off of the WalkState result stack
289 ******************************************************************************/
292 AcpiDsResultStackPop (
293 ACPI_WALK_STATE
*WalkState
)
295 ACPI_GENERIC_STATE
*State
;
298 ACPI_FUNCTION_NAME (DsResultStackPop
);
301 /* Check for stack underflow */
303 if (WalkState
->Results
== NULL
)
305 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Result stack underflow - State=%p\n",
307 return (AE_AML_NO_OPERAND
);
310 if (WalkState
->ResultSize
< ACPI_RESULTS_FRAME_OBJ_NUM
)
312 ACPI_ERROR ((AE_INFO
, "Insufficient result stack size"));
313 return (AE_AML_INTERNAL
);
316 State
= AcpiUtPopGenericState (&WalkState
->Results
);
317 AcpiUtDeleteGenericState (State
);
319 /* Decrease the length of result stack by the length of frame */
321 WalkState
->ResultSize
-= ACPI_RESULTS_FRAME_OBJ_NUM
;
323 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
,
324 "Result=%p RemainingResults=%X State=%p\n",
325 State
, WalkState
->ResultCount
, WalkState
));
331 /*******************************************************************************
333 * FUNCTION: AcpiDsObjStackPush
335 * PARAMETERS: Object - Object to push
336 * WalkState - Current Walk state
340 * DESCRIPTION: Push an object onto this walk's object/operand stack
342 ******************************************************************************/
347 ACPI_WALK_STATE
*WalkState
)
349 ACPI_FUNCTION_NAME (DsObjStackPush
);
352 /* Check for stack overflow */
354 if (WalkState
->NumOperands
>= ACPI_OBJ_NUM_OPERANDS
)
356 ACPI_ERROR ((AE_INFO
,
357 "Object stack overflow! Obj=%p State=%p #Ops=%u",
358 Object
, WalkState
, WalkState
->NumOperands
));
359 return (AE_STACK_OVERFLOW
);
362 /* Put the object onto the stack */
364 WalkState
->Operands
[WalkState
->OperandIndex
] = Object
;
365 WalkState
->NumOperands
++;
367 /* For the usual order of filling the operand stack */
369 WalkState
->OperandIndex
++;
371 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Obj=%p [%s] State=%p #Ops=%X\n",
372 Object
, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT
*) Object
),
373 WalkState
, WalkState
->NumOperands
));
379 /*******************************************************************************
381 * FUNCTION: AcpiDsObjStackPop
383 * PARAMETERS: PopCount - Number of objects/entries to pop
384 * WalkState - Current Walk state
388 * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
389 * deleted by this routine.
391 ******************************************************************************/
396 ACPI_WALK_STATE
*WalkState
)
401 ACPI_FUNCTION_NAME (DsObjStackPop
);
404 for (i
= 0; i
< PopCount
; i
++)
406 /* Check for stack underflow */
408 if (WalkState
->NumOperands
== 0)
410 ACPI_ERROR ((AE_INFO
,
411 "Object stack underflow! Count=%X State=%p #Ops=%u",
412 PopCount
, WalkState
, WalkState
->NumOperands
));
413 return (AE_STACK_UNDERFLOW
);
416 /* Just set the stack entry to null */
418 WalkState
->NumOperands
--;
419 WalkState
->Operands
[WalkState
->NumOperands
] = NULL
;
422 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Count=%X State=%p #Ops=%u\n",
423 PopCount
, WalkState
, WalkState
->NumOperands
));
429 /*******************************************************************************
431 * FUNCTION: AcpiDsObjStackPopAndDelete
433 * PARAMETERS: PopCount - Number of objects/entries to pop
434 * WalkState - Current Walk state
438 * DESCRIPTION: Pop this walk's object stack and delete each object that is
441 ******************************************************************************/
444 AcpiDsObjStackPopAndDelete (
446 ACPI_WALK_STATE
*WalkState
)
449 ACPI_OPERAND_OBJECT
*ObjDesc
;
452 ACPI_FUNCTION_NAME (DsObjStackPopAndDelete
);
460 for (i
= (INT32
) PopCount
- 1; i
>= 0; i
--)
462 if (WalkState
->NumOperands
== 0)
467 /* Pop the stack and delete an object if present in this stack entry */
469 WalkState
->NumOperands
--;
470 ObjDesc
= WalkState
->Operands
[i
];
473 AcpiUtRemoveReference (WalkState
->Operands
[i
]);
474 WalkState
->Operands
[i
] = NULL
;
478 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Count=%X State=%p #Ops=%X\n",
479 PopCount
, WalkState
, WalkState
->NumOperands
));
483 /*******************************************************************************
485 * FUNCTION: AcpiDsGetCurrentWalkState
487 * PARAMETERS: Thread - Get current active state for this Thread
489 * RETURN: Pointer to the current walk state
491 * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
494 ******************************************************************************/
497 AcpiDsGetCurrentWalkState (
498 ACPI_THREAD_STATE
*Thread
)
500 ACPI_FUNCTION_NAME (DsGetCurrentWalkState
);
508 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE
, "Current WalkState %p\n",
509 Thread
->WalkStateList
));
511 return (Thread
->WalkStateList
);
515 /*******************************************************************************
517 * FUNCTION: AcpiDsPushWalkState
519 * PARAMETERS: WalkState - State to push
520 * Thread - Thread state object
524 * DESCRIPTION: Place the Thread state at the head of the state list
526 ******************************************************************************/
529 AcpiDsPushWalkState (
530 ACPI_WALK_STATE
*WalkState
,
531 ACPI_THREAD_STATE
*Thread
)
533 ACPI_FUNCTION_TRACE (DsPushWalkState
);
536 WalkState
->Next
= Thread
->WalkStateList
;
537 Thread
->WalkStateList
= WalkState
;
543 /*******************************************************************************
545 * FUNCTION: AcpiDsPopWalkState
547 * PARAMETERS: Thread - Current thread state
549 * RETURN: A WalkState object popped from the thread's stack
551 * DESCRIPTION: Remove and return the walkstate object that is at the head of
552 * the walk stack for the given walk list. NULL indicates that
555 ******************************************************************************/
559 ACPI_THREAD_STATE
*Thread
)
561 ACPI_WALK_STATE
*WalkState
;
564 ACPI_FUNCTION_TRACE (DsPopWalkState
);
567 WalkState
= Thread
->WalkStateList
;
571 /* Next walk state becomes the current walk state */
573 Thread
->WalkStateList
= WalkState
->Next
;
576 * Don't clear the NEXT field, this serves as an indicator
577 * that there is a parent WALK STATE
578 * Do Not: WalkState->Next = NULL;
582 return_PTR (WalkState
);
586 /*******************************************************************************
588 * FUNCTION: AcpiDsCreateWalkState
590 * PARAMETERS: OwnerId - ID for object creation
591 * Origin - Starting point for this walk
592 * MethodDesc - Method object
593 * Thread - Current thread state
595 * RETURN: Pointer to the new walk state.
597 * DESCRIPTION: Allocate and initialize a new walk state. The current walk
598 * state is set to this new state.
600 ******************************************************************************/
603 AcpiDsCreateWalkState (
604 ACPI_OWNER_ID OwnerId
,
605 ACPI_PARSE_OBJECT
*Origin
,
606 ACPI_OPERAND_OBJECT
*MethodDesc
,
607 ACPI_THREAD_STATE
*Thread
)
609 ACPI_WALK_STATE
*WalkState
;
612 ACPI_FUNCTION_TRACE (DsCreateWalkState
);
615 WalkState
= ACPI_ALLOCATE_ZEROED (sizeof (ACPI_WALK_STATE
));
621 WalkState
->DescriptorType
= ACPI_DESC_TYPE_WALK
;
622 WalkState
->MethodDesc
= MethodDesc
;
623 WalkState
->OwnerId
= OwnerId
;
624 WalkState
->Origin
= Origin
;
625 WalkState
->Thread
= Thread
;
627 WalkState
->ParserState
.StartOp
= Origin
;
629 /* Init the method args/local */
631 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
632 AcpiDsMethodDataInit (WalkState
);
635 /* Put the new state at the head of the walk list */
639 AcpiDsPushWalkState (WalkState
, Thread
);
642 return_PTR (WalkState
);
646 /*******************************************************************************
648 * FUNCTION: AcpiDsInitAmlWalk
650 * PARAMETERS: WalkState - New state to be initialized
651 * Op - Current parse op
652 * MethodNode - Control method NS node, if any
653 * AmlStart - Start of AML
654 * AmlLength - Length of AML
655 * Info - Method info block (params, etc.)
656 * PassNumber - 1, 2, or 3
660 * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
662 ******************************************************************************/
666 ACPI_WALK_STATE
*WalkState
,
667 ACPI_PARSE_OBJECT
*Op
,
668 ACPI_NAMESPACE_NODE
*MethodNode
,
671 ACPI_EVALUATE_INFO
*Info
,
675 ACPI_PARSE_STATE
*ParserState
= &WalkState
->ParserState
;
676 ACPI_PARSE_OBJECT
*ExtraOp
;
679 ACPI_FUNCTION_TRACE (DsInitAmlWalk
);
682 WalkState
->ParserState
.Aml
=
683 WalkState
->ParserState
.AmlStart
= AmlStart
;
684 WalkState
->ParserState
.AmlEnd
=
685 WalkState
->ParserState
.PkgEnd
= AmlStart
+ AmlLength
;
687 /* The NextOp of the NextWalk will be the beginning of the method */
689 WalkState
->NextOp
= NULL
;
690 WalkState
->PassNumber
= PassNumber
;
694 WalkState
->Params
= Info
->Parameters
;
695 WalkState
->CallerReturnDesc
= &Info
->ReturnObject
;
698 Status
= AcpiPsInitScope (&WalkState
->ParserState
, Op
);
699 if (ACPI_FAILURE (Status
))
701 return_ACPI_STATUS (Status
);
706 WalkState
->ParserState
.StartNode
= MethodNode
;
707 WalkState
->WalkType
= ACPI_WALK_METHOD
;
708 WalkState
->MethodNode
= MethodNode
;
709 WalkState
->MethodDesc
= AcpiNsGetAttachedObject (MethodNode
);
711 /* Push start scope on scope stack and make it current */
713 Status
= AcpiDsScopeStackPush (MethodNode
, ACPI_TYPE_METHOD
, WalkState
);
714 if (ACPI_FAILURE (Status
))
716 return_ACPI_STATUS (Status
);
719 /* Init the method arguments */
721 Status
= AcpiDsMethodDataInitArgs (WalkState
->Params
,
722 ACPI_METHOD_NUM_ARGS
, WalkState
);
723 if (ACPI_FAILURE (Status
))
725 return_ACPI_STATUS (Status
);
731 * Setup the current scope.
732 * Find a Named Op that has a namespace node associated with it.
733 * search upwards from this Op. Current scope is the first
734 * Op with a namespace node.
736 ExtraOp
= ParserState
->StartOp
;
737 while (ExtraOp
&& !ExtraOp
->Common
.Node
)
739 ExtraOp
= ExtraOp
->Common
.Parent
;
744 ParserState
->StartNode
= NULL
;
748 ParserState
->StartNode
= ExtraOp
->Common
.Node
;
751 if (ParserState
->StartNode
)
753 /* Push start scope on scope stack and make it current */
755 Status
= AcpiDsScopeStackPush (ParserState
->StartNode
,
756 ParserState
->StartNode
->Type
, WalkState
);
757 if (ACPI_FAILURE (Status
))
759 return_ACPI_STATUS (Status
);
764 Status
= AcpiDsInitCallbacks (WalkState
, PassNumber
);
765 return_ACPI_STATUS (Status
);
769 /*******************************************************************************
771 * FUNCTION: AcpiDsDeleteWalkState
773 * PARAMETERS: WalkState - State to delete
777 * DESCRIPTION: Delete a walk state including all internal data structures
779 ******************************************************************************/
782 AcpiDsDeleteWalkState (
783 ACPI_WALK_STATE
*WalkState
)
785 ACPI_GENERIC_STATE
*State
;
788 ACPI_FUNCTION_TRACE_PTR (DsDeleteWalkState
, WalkState
);
796 if (WalkState
->DescriptorType
!= ACPI_DESC_TYPE_WALK
)
798 ACPI_ERROR ((AE_INFO
, "%p is not a valid walk state",
803 /* There should not be any open scopes */
805 if (WalkState
->ParserState
.Scope
)
807 ACPI_ERROR ((AE_INFO
, "%p walk still has a scope list",
809 AcpiPsCleanupScope (&WalkState
->ParserState
);
812 /* Always must free any linked control states */
814 while (WalkState
->ControlState
)
816 State
= WalkState
->ControlState
;
817 WalkState
->ControlState
= State
->Common
.Next
;
819 AcpiUtDeleteGenericState (State
);
822 /* Always must free any linked parse states */
824 while (WalkState
->ScopeInfo
)
826 State
= WalkState
->ScopeInfo
;
827 WalkState
->ScopeInfo
= State
->Common
.Next
;
829 AcpiUtDeleteGenericState (State
);
832 /* Always must free any stacked result states */
834 while (WalkState
->Results
)
836 State
= WalkState
->Results
;
837 WalkState
->Results
= State
->Common
.Next
;
839 AcpiUtDeleteGenericState (State
);
842 ACPI_FREE (WalkState
);