1 /******************************************************************************
3 * Module Name: dswstate - Dispatcher parse tree walk management routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2015, 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.
50 #define _COMPONENT ACPI_DISPATCHER
51 ACPI_MODULE_NAME ("dswstate")
53 /* Local prototypes */
56 AcpiDsResultStackPush (
57 ACPI_WALK_STATE
*WalkState
);
60 AcpiDsResultStackPop (
61 ACPI_WALK_STATE
*WalkState
);
64 /*******************************************************************************
66 * FUNCTION: AcpiDsResultPop
68 * PARAMETERS: Object - Where to return the popped object
69 * WalkState - Current Walk state
73 * DESCRIPTION: Pop an object off the top of this walk's result stack
75 ******************************************************************************/
79 ACPI_OPERAND_OBJECT
**Object
,
80 ACPI_WALK_STATE
*WalkState
)
83 ACPI_GENERIC_STATE
*State
;
87 ACPI_FUNCTION_NAME (DsResultPop
);
90 State
= WalkState
->Results
;
92 /* Incorrect state of result stack */
94 if (State
&& !WalkState
->ResultCount
)
96 ACPI_ERROR ((AE_INFO
, "No results on result stack"));
97 return (AE_AML_INTERNAL
);
100 if (!State
&& WalkState
->ResultCount
)
102 ACPI_ERROR ((AE_INFO
, "No result state for result stack"));
103 return (AE_AML_INTERNAL
);
106 /* Empty result stack */
110 ACPI_ERROR ((AE_INFO
, "Result stack is empty! State=%p", WalkState
));
111 return (AE_AML_NO_RETURN_VALUE
);
114 /* Return object of the top element and clean that top element result stack */
116 WalkState
->ResultCount
--;
117 Index
= (UINT32
) WalkState
->ResultCount
% ACPI_RESULTS_FRAME_OBJ_NUM
;
119 *Object
= State
->Results
.ObjDesc
[Index
];
122 ACPI_ERROR ((AE_INFO
, "No result objects on result stack, State=%p",
124 return (AE_AML_NO_RETURN_VALUE
);
127 State
->Results
.ObjDesc
[Index
] = NULL
;
130 Status
= AcpiDsResultStackPop (WalkState
);
131 if (ACPI_FAILURE (Status
))
137 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
,
138 "Obj=%p [%s] Index=%X State=%p Num=%X\n", *Object
,
139 AcpiUtGetObjectTypeName (*Object
),
140 Index
, WalkState
, WalkState
->ResultCount
));
146 /*******************************************************************************
148 * FUNCTION: AcpiDsResultPush
150 * PARAMETERS: Object - Where to return the popped object
151 * WalkState - Current Walk state
155 * DESCRIPTION: Push an object onto the current result stack
157 ******************************************************************************/
161 ACPI_OPERAND_OBJECT
*Object
,
162 ACPI_WALK_STATE
*WalkState
)
164 ACPI_GENERIC_STATE
*State
;
169 ACPI_FUNCTION_NAME (DsResultPush
);
172 if (WalkState
->ResultCount
> WalkState
->ResultSize
)
174 ACPI_ERROR ((AE_INFO
, "Result stack is full"));
175 return (AE_AML_INTERNAL
);
177 else if (WalkState
->ResultCount
== WalkState
->ResultSize
)
179 /* Extend the result stack */
181 Status
= AcpiDsResultStackPush (WalkState
);
182 if (ACPI_FAILURE (Status
))
184 ACPI_ERROR ((AE_INFO
, "Failed to extend the result stack"));
189 if (!(WalkState
->ResultCount
< WalkState
->ResultSize
))
191 ACPI_ERROR ((AE_INFO
, "No free elements in result stack"));
192 return (AE_AML_INTERNAL
);
195 State
= WalkState
->Results
;
198 ACPI_ERROR ((AE_INFO
, "No result stack frame during push"));
199 return (AE_AML_INTERNAL
);
204 ACPI_ERROR ((AE_INFO
,
205 "Null Object! Obj=%p State=%p Num=%u",
206 Object
, WalkState
, WalkState
->ResultCount
));
207 return (AE_BAD_PARAMETER
);
210 /* Assign the address of object to the top free element of result stack */
212 Index
= (UINT32
) WalkState
->ResultCount
% ACPI_RESULTS_FRAME_OBJ_NUM
;
213 State
->Results
.ObjDesc
[Index
] = Object
;
214 WalkState
->ResultCount
++;
216 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
217 Object
, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT
*) Object
),
218 WalkState
, WalkState
->ResultCount
, WalkState
->CurrentResult
));
224 /*******************************************************************************
226 * FUNCTION: AcpiDsResultStackPush
228 * PARAMETERS: WalkState - Current Walk state
232 * DESCRIPTION: Push an object onto the WalkState result stack
234 ******************************************************************************/
237 AcpiDsResultStackPush (
238 ACPI_WALK_STATE
*WalkState
)
240 ACPI_GENERIC_STATE
*State
;
243 ACPI_FUNCTION_NAME (DsResultStackPush
);
246 /* Check for stack overflow */
248 if (((UINT32
) WalkState
->ResultSize
+ ACPI_RESULTS_FRAME_OBJ_NUM
) >
249 ACPI_RESULTS_OBJ_NUM_MAX
)
251 ACPI_ERROR ((AE_INFO
, "Result stack overflow: State=%p Num=%u",
252 WalkState
, WalkState
->ResultSize
));
253 return (AE_STACK_OVERFLOW
);
256 State
= AcpiUtCreateGenericState ();
259 return (AE_NO_MEMORY
);
262 State
->Common
.DescriptorType
= ACPI_DESC_TYPE_STATE_RESULT
;
263 AcpiUtPushGenericState (&WalkState
->Results
, State
);
265 /* Increase the length of the result stack by the length of frame */
267 WalkState
->ResultSize
+= ACPI_RESULTS_FRAME_OBJ_NUM
;
269 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Results=%p State=%p\n",
276 /*******************************************************************************
278 * FUNCTION: AcpiDsResultStackPop
280 * PARAMETERS: WalkState - Current Walk state
284 * DESCRIPTION: Pop an object off of the WalkState result stack
286 ******************************************************************************/
289 AcpiDsResultStackPop (
290 ACPI_WALK_STATE
*WalkState
)
292 ACPI_GENERIC_STATE
*State
;
295 ACPI_FUNCTION_NAME (DsResultStackPop
);
298 /* Check for stack underflow */
300 if (WalkState
->Results
== NULL
)
302 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
,
303 "Result stack underflow - State=%p\n", WalkState
));
304 return (AE_AML_NO_OPERAND
);
307 if (WalkState
->ResultSize
< ACPI_RESULTS_FRAME_OBJ_NUM
)
309 ACPI_ERROR ((AE_INFO
, "Insufficient result stack size"));
310 return (AE_AML_INTERNAL
);
313 State
= AcpiUtPopGenericState (&WalkState
->Results
);
314 AcpiUtDeleteGenericState (State
);
316 /* Decrease the length of result stack by the length of frame */
318 WalkState
->ResultSize
-= ACPI_RESULTS_FRAME_OBJ_NUM
;
320 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
,
321 "Result=%p RemainingResults=%X State=%p\n",
322 State
, WalkState
->ResultCount
, WalkState
));
328 /*******************************************************************************
330 * FUNCTION: AcpiDsObjStackPush
332 * PARAMETERS: Object - Object to push
333 * WalkState - Current Walk state
337 * DESCRIPTION: Push an object onto this walk's object/operand stack
339 ******************************************************************************/
344 ACPI_WALK_STATE
*WalkState
)
346 ACPI_FUNCTION_NAME (DsObjStackPush
);
349 /* Check for stack overflow */
351 if (WalkState
->NumOperands
>= ACPI_OBJ_NUM_OPERANDS
)
353 ACPI_ERROR ((AE_INFO
,
354 "Object stack overflow! Obj=%p State=%p #Ops=%u",
355 Object
, WalkState
, WalkState
->NumOperands
));
356 return (AE_STACK_OVERFLOW
);
359 /* Put the object onto the stack */
361 WalkState
->Operands
[WalkState
->OperandIndex
] = Object
;
362 WalkState
->NumOperands
++;
364 /* For the usual order of filling the operand stack */
366 WalkState
->OperandIndex
++;
368 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Obj=%p [%s] State=%p #Ops=%X\n",
369 Object
, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT
*) Object
),
370 WalkState
, WalkState
->NumOperands
));
376 /*******************************************************************************
378 * FUNCTION: AcpiDsObjStackPop
380 * PARAMETERS: PopCount - Number of objects/entries to pop
381 * WalkState - Current Walk state
385 * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
386 * deleted by this routine.
388 ******************************************************************************/
393 ACPI_WALK_STATE
*WalkState
)
398 ACPI_FUNCTION_NAME (DsObjStackPop
);
401 for (i
= 0; i
< PopCount
; i
++)
403 /* Check for stack underflow */
405 if (WalkState
->NumOperands
== 0)
407 ACPI_ERROR ((AE_INFO
,
408 "Object stack underflow! Count=%X State=%p #Ops=%u",
409 PopCount
, WalkState
, WalkState
->NumOperands
));
410 return (AE_STACK_UNDERFLOW
);
413 /* Just set the stack entry to null */
415 WalkState
->NumOperands
--;
416 WalkState
->Operands
[WalkState
->NumOperands
] = NULL
;
419 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Count=%X State=%p #Ops=%u\n",
420 PopCount
, WalkState
, WalkState
->NumOperands
));
426 /*******************************************************************************
428 * FUNCTION: AcpiDsObjStackPopAndDelete
430 * PARAMETERS: PopCount - Number of objects/entries to pop
431 * WalkState - Current Walk state
435 * DESCRIPTION: Pop this walk's object stack and delete each object that is
438 ******************************************************************************/
441 AcpiDsObjStackPopAndDelete (
443 ACPI_WALK_STATE
*WalkState
)
446 ACPI_OPERAND_OBJECT
*ObjDesc
;
449 ACPI_FUNCTION_NAME (DsObjStackPopAndDelete
);
457 for (i
= (INT32
) PopCount
- 1; i
>= 0; i
--)
459 if (WalkState
->NumOperands
== 0)
464 /* Pop the stack and delete an object if present in this stack entry */
466 WalkState
->NumOperands
--;
467 ObjDesc
= WalkState
->Operands
[i
];
470 AcpiUtRemoveReference (WalkState
->Operands
[i
]);
471 WalkState
->Operands
[i
] = NULL
;
475 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "Count=%X State=%p #Ops=%X\n",
476 PopCount
, WalkState
, WalkState
->NumOperands
));
480 /*******************************************************************************
482 * FUNCTION: AcpiDsGetCurrentWalkState
484 * PARAMETERS: Thread - Get current active state for this Thread
486 * RETURN: Pointer to the current walk state
488 * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
491 ******************************************************************************/
494 AcpiDsGetCurrentWalkState (
495 ACPI_THREAD_STATE
*Thread
)
497 ACPI_FUNCTION_NAME (DsGetCurrentWalkState
);
505 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE
, "Current WalkState %p\n",
506 Thread
->WalkStateList
));
508 return (Thread
->WalkStateList
);
512 /*******************************************************************************
514 * FUNCTION: AcpiDsPushWalkState
516 * PARAMETERS: WalkState - State to push
517 * Thread - Thread state object
521 * DESCRIPTION: Place the Thread state at the head of the state list
523 ******************************************************************************/
526 AcpiDsPushWalkState (
527 ACPI_WALK_STATE
*WalkState
,
528 ACPI_THREAD_STATE
*Thread
)
530 ACPI_FUNCTION_TRACE (DsPushWalkState
);
533 WalkState
->Next
= Thread
->WalkStateList
;
534 Thread
->WalkStateList
= WalkState
;
540 /*******************************************************************************
542 * FUNCTION: AcpiDsPopWalkState
544 * PARAMETERS: Thread - Current thread state
546 * RETURN: A WalkState object popped from the thread's stack
548 * DESCRIPTION: Remove and return the walkstate object that is at the head of
549 * the walk stack for the given walk list. NULL indicates that
552 ******************************************************************************/
556 ACPI_THREAD_STATE
*Thread
)
558 ACPI_WALK_STATE
*WalkState
;
561 ACPI_FUNCTION_TRACE (DsPopWalkState
);
564 WalkState
= Thread
->WalkStateList
;
568 /* Next walk state becomes the current walk state */
570 Thread
->WalkStateList
= WalkState
->Next
;
573 * Don't clear the NEXT field, this serves as an indicator
574 * that there is a parent WALK STATE
575 * Do Not: WalkState->Next = NULL;
579 return_PTR (WalkState
);
583 /*******************************************************************************
585 * FUNCTION: AcpiDsCreateWalkState
587 * PARAMETERS: OwnerId - ID for object creation
588 * Origin - Starting point for this walk
589 * MethodDesc - Method object
590 * Thread - Current thread state
592 * RETURN: Pointer to the new walk state.
594 * DESCRIPTION: Allocate and initialize a new walk state. The current walk
595 * state is set to this new state.
597 ******************************************************************************/
600 AcpiDsCreateWalkState (
601 ACPI_OWNER_ID OwnerId
,
602 ACPI_PARSE_OBJECT
*Origin
,
603 ACPI_OPERAND_OBJECT
*MethodDesc
,
604 ACPI_THREAD_STATE
*Thread
)
606 ACPI_WALK_STATE
*WalkState
;
609 ACPI_FUNCTION_TRACE (DsCreateWalkState
);
612 WalkState
= ACPI_ALLOCATE_ZEROED (sizeof (ACPI_WALK_STATE
));
618 WalkState
->DescriptorType
= ACPI_DESC_TYPE_WALK
;
619 WalkState
->MethodDesc
= MethodDesc
;
620 WalkState
->OwnerId
= OwnerId
;
621 WalkState
->Origin
= Origin
;
622 WalkState
->Thread
= Thread
;
624 WalkState
->ParserState
.StartOp
= Origin
;
626 /* Init the method args/local */
628 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
629 AcpiDsMethodDataInit (WalkState
);
632 /* Put the new state at the head of the walk list */
636 AcpiDsPushWalkState (WalkState
, Thread
);
639 return_PTR (WalkState
);
643 /*******************************************************************************
645 * FUNCTION: AcpiDsInitAmlWalk
647 * PARAMETERS: WalkState - New state to be initialized
648 * Op - Current parse op
649 * MethodNode - Control method NS node, if any
650 * AmlStart - Start of AML
651 * AmlLength - Length of AML
652 * Info - Method info block (params, etc.)
653 * PassNumber - 1, 2, or 3
657 * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
659 ******************************************************************************/
663 ACPI_WALK_STATE
*WalkState
,
664 ACPI_PARSE_OBJECT
*Op
,
665 ACPI_NAMESPACE_NODE
*MethodNode
,
668 ACPI_EVALUATE_INFO
*Info
,
672 ACPI_PARSE_STATE
*ParserState
= &WalkState
->ParserState
;
673 ACPI_PARSE_OBJECT
*ExtraOp
;
676 ACPI_FUNCTION_TRACE (DsInitAmlWalk
);
679 WalkState
->ParserState
.Aml
=
680 WalkState
->ParserState
.AmlStart
= AmlStart
;
681 WalkState
->ParserState
.AmlEnd
=
682 WalkState
->ParserState
.PkgEnd
= AmlStart
+ AmlLength
;
684 /* The NextOp of the NextWalk will be the beginning of the method */
686 WalkState
->NextOp
= NULL
;
687 WalkState
->PassNumber
= PassNumber
;
691 WalkState
->Params
= Info
->Parameters
;
692 WalkState
->CallerReturnDesc
= &Info
->ReturnObject
;
695 Status
= AcpiPsInitScope (&WalkState
->ParserState
, Op
);
696 if (ACPI_FAILURE (Status
))
698 return_ACPI_STATUS (Status
);
703 WalkState
->ParserState
.StartNode
= MethodNode
;
704 WalkState
->WalkType
= ACPI_WALK_METHOD
;
705 WalkState
->MethodNode
= MethodNode
;
706 WalkState
->MethodDesc
= AcpiNsGetAttachedObject (MethodNode
);
708 /* Push start scope on scope stack and make it current */
710 Status
= AcpiDsScopeStackPush (
711 MethodNode
, ACPI_TYPE_METHOD
, WalkState
);
712 if (ACPI_FAILURE (Status
))
714 return_ACPI_STATUS (Status
);
717 /* Init the method arguments */
719 Status
= AcpiDsMethodDataInitArgs (WalkState
->Params
,
720 ACPI_METHOD_NUM_ARGS
, WalkState
);
721 if (ACPI_FAILURE (Status
))
723 return_ACPI_STATUS (Status
);
729 * Setup the current scope.
730 * Find a Named Op that has a namespace node associated with it.
731 * search upwards from this Op. Current scope is the first
732 * Op with a namespace node.
734 ExtraOp
= ParserState
->StartOp
;
735 while (ExtraOp
&& !ExtraOp
->Common
.Node
)
737 ExtraOp
= ExtraOp
->Common
.Parent
;
742 ParserState
->StartNode
= NULL
;
746 ParserState
->StartNode
= ExtraOp
->Common
.Node
;
749 if (ParserState
->StartNode
)
751 /* Push start scope on scope stack and make it current */
753 Status
= AcpiDsScopeStackPush (ParserState
->StartNode
,
754 ParserState
->StartNode
->Type
, WalkState
);
755 if (ACPI_FAILURE (Status
))
757 return_ACPI_STATUS (Status
);
762 Status
= AcpiDsInitCallbacks (WalkState
, PassNumber
);
763 return_ACPI_STATUS (Status
);
767 /*******************************************************************************
769 * FUNCTION: AcpiDsDeleteWalkState
771 * PARAMETERS: WalkState - State to delete
775 * DESCRIPTION: Delete a walk state including all internal data structures
777 ******************************************************************************/
780 AcpiDsDeleteWalkState (
781 ACPI_WALK_STATE
*WalkState
)
783 ACPI_GENERIC_STATE
*State
;
786 ACPI_FUNCTION_TRACE_PTR (DsDeleteWalkState
, WalkState
);
794 if (WalkState
->DescriptorType
!= ACPI_DESC_TYPE_WALK
)
796 ACPI_ERROR ((AE_INFO
, "%p is not a valid walk state",
801 /* There should not be any open scopes */
803 if (WalkState
->ParserState
.Scope
)
805 ACPI_ERROR ((AE_INFO
, "%p walk still has a scope list",
807 AcpiPsCleanupScope (&WalkState
->ParserState
);
810 /* Always must free any linked control states */
812 while (WalkState
->ControlState
)
814 State
= WalkState
->ControlState
;
815 WalkState
->ControlState
= State
->Common
.Next
;
817 AcpiUtDeleteGenericState (State
);
820 /* Always must free any linked parse states */
822 while (WalkState
->ScopeInfo
)
824 State
= WalkState
->ScopeInfo
;
825 WalkState
->ScopeInfo
= State
->Common
.Next
;
827 AcpiUtDeleteGenericState (State
);
830 /* Always must free any stacked result states */
832 while (WalkState
->Results
)
834 State
= WalkState
->Results
;
835 WalkState
->Results
= State
->Common
.Next
;
837 AcpiUtDeleteGenericState (State
);
840 ACPI_FREE (WalkState
);