xref: /freebsd/sys/contrib/dev/acpica/components/dispatcher/dswstate.c (revision 273c26a3c3bea87a241d6879abd4f991db180bf0)
1 /******************************************************************************
2  *
3  * Module Name: dswstate - Dispatcher parse tree walk management routines
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
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.
25  *
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.
29  *
30  * NO WARRANTY
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.
42  */
43 
44 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acparser.h>
47 #include <contrib/dev/acpica/include/acdispat.h>
48 #include <contrib/dev/acpica/include/acnamesp.h>
49 
50 #define _COMPONENT          ACPI_DISPATCHER
51         ACPI_MODULE_NAME    ("dswstate")
52 
53 /* Local prototypes */
54 
55 static ACPI_STATUS
56 AcpiDsResultStackPush (
57     ACPI_WALK_STATE         *WalkState);
58 
59 static ACPI_STATUS
60 AcpiDsResultStackPop (
61     ACPI_WALK_STATE         *WalkState);
62 
63 
64 /*******************************************************************************
65  *
66  * FUNCTION:    AcpiDsResultPop
67  *
68  * PARAMETERS:  Object              - Where to return the popped object
69  *              WalkState           - Current Walk state
70  *
71  * RETURN:      Status
72  *
73  * DESCRIPTION: Pop an object off the top of this walk's result stack
74  *
75  ******************************************************************************/
76 
77 ACPI_STATUS
78 AcpiDsResultPop (
79     ACPI_OPERAND_OBJECT     **Object,
80     ACPI_WALK_STATE         *WalkState)
81 {
82     UINT32                  Index;
83     ACPI_GENERIC_STATE      *State;
84     ACPI_STATUS             Status;
85 
86 
87     ACPI_FUNCTION_NAME (DsResultPop);
88 
89 
90     State = WalkState->Results;
91 
92     /* Incorrect state of result stack */
93 
94     if (State && !WalkState->ResultCount)
95     {
96         ACPI_ERROR ((AE_INFO, "No results on result stack"));
97         return (AE_AML_INTERNAL);
98     }
99 
100     if (!State && WalkState->ResultCount)
101     {
102         ACPI_ERROR ((AE_INFO, "No result state for result stack"));
103         return (AE_AML_INTERNAL);
104     }
105 
106     /* Empty result stack */
107 
108     if (!State)
109     {
110         ACPI_ERROR ((AE_INFO, "Result stack is empty! State=%p", WalkState));
111         return (AE_AML_NO_RETURN_VALUE);
112     }
113 
114     /* Return object of the top element and clean that top element result stack */
115 
116     WalkState->ResultCount--;
117     Index = (UINT32) WalkState->ResultCount % ACPI_RESULTS_FRAME_OBJ_NUM;
118 
119     *Object = State->Results.ObjDesc [Index];
120     if (!*Object)
121     {
122         ACPI_ERROR ((AE_INFO, "No result objects on result stack, State=%p",
123             WalkState));
124         return (AE_AML_NO_RETURN_VALUE);
125     }
126 
127     State->Results.ObjDesc [Index] = NULL;
128     if (Index == 0)
129     {
130         Status = AcpiDsResultStackPop (WalkState);
131         if (ACPI_FAILURE (Status))
132         {
133             return (Status);
134         }
135     }
136 
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));
141 
142     return (AE_OK);
143 }
144 
145 
146 /*******************************************************************************
147  *
148  * FUNCTION:    AcpiDsResultPush
149  *
150  * PARAMETERS:  Object              - Where to return the popped object
151  *              WalkState           - Current Walk state
152  *
153  * RETURN:      Status
154  *
155  * DESCRIPTION: Push an object onto the current result stack
156  *
157  ******************************************************************************/
158 
159 ACPI_STATUS
160 AcpiDsResultPush (
161     ACPI_OPERAND_OBJECT     *Object,
162     ACPI_WALK_STATE         *WalkState)
163 {
164     ACPI_GENERIC_STATE      *State;
165     ACPI_STATUS             Status;
166     UINT32                  Index;
167 
168 
169     ACPI_FUNCTION_NAME (DsResultPush);
170 
171 
172     if (WalkState->ResultCount > WalkState->ResultSize)
173     {
174         ACPI_ERROR ((AE_INFO, "Result stack is full"));
175         return (AE_AML_INTERNAL);
176     }
177     else if (WalkState->ResultCount == WalkState->ResultSize)
178     {
179         /* Extend the result stack */
180 
181         Status = AcpiDsResultStackPush (WalkState);
182         if (ACPI_FAILURE (Status))
183         {
184             ACPI_ERROR ((AE_INFO, "Failed to extend the result stack"));
185             return (Status);
186         }
187     }
188 
189     if (!(WalkState->ResultCount < WalkState->ResultSize))
190     {
191         ACPI_ERROR ((AE_INFO, "No free elements in result stack"));
192         return (AE_AML_INTERNAL);
193     }
194 
195     State = WalkState->Results;
196     if (!State)
197     {
198         ACPI_ERROR ((AE_INFO, "No result stack frame during push"));
199         return (AE_AML_INTERNAL);
200     }
201 
202     if (!Object)
203     {
204         ACPI_ERROR ((AE_INFO,
205             "Null Object! Obj=%p State=%p Num=%u",
206             Object, WalkState, WalkState->ResultCount));
207         return (AE_BAD_PARAMETER);
208     }
209 
210     /* Assign the address of object to the top free element of result stack */
211 
212     Index = (UINT32) WalkState->ResultCount % ACPI_RESULTS_FRAME_OBJ_NUM;
213     State->Results.ObjDesc [Index] = Object;
214     WalkState->ResultCount++;
215 
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));
219 
220     return (AE_OK);
221 }
222 
223 
224 /*******************************************************************************
225  *
226  * FUNCTION:    AcpiDsResultStackPush
227  *
228  * PARAMETERS:  WalkState           - Current Walk state
229  *
230  * RETURN:      Status
231  *
232  * DESCRIPTION: Push an object onto the WalkState result stack
233  *
234  ******************************************************************************/
235 
236 static ACPI_STATUS
237 AcpiDsResultStackPush (
238     ACPI_WALK_STATE         *WalkState)
239 {
240     ACPI_GENERIC_STATE      *State;
241 
242 
243     ACPI_FUNCTION_NAME (DsResultStackPush);
244 
245 
246     /* Check for stack overflow */
247 
248     if (((UINT32) WalkState->ResultSize + ACPI_RESULTS_FRAME_OBJ_NUM) >
249         ACPI_RESULTS_OBJ_NUM_MAX)
250     {
251         ACPI_ERROR ((AE_INFO, "Result stack overflow: State=%p Num=%u",
252             WalkState, WalkState->ResultSize));
253         return (AE_STACK_OVERFLOW);
254     }
255 
256     State = AcpiUtCreateGenericState ();
257     if (!State)
258     {
259         return (AE_NO_MEMORY);
260     }
261 
262     State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_RESULT;
263     AcpiUtPushGenericState (&WalkState->Results, State);
264 
265     /* Increase the length of the result stack by the length of frame */
266 
267     WalkState->ResultSize += ACPI_RESULTS_FRAME_OBJ_NUM;
268 
269     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Results=%p State=%p\n",
270         State, WalkState));
271 
272     return (AE_OK);
273 }
274 
275 
276 /*******************************************************************************
277  *
278  * FUNCTION:    AcpiDsResultStackPop
279  *
280  * PARAMETERS:  WalkState           - Current Walk state
281  *
282  * RETURN:      Status
283  *
284  * DESCRIPTION: Pop an object off of the WalkState result stack
285  *
286  ******************************************************************************/
287 
288 static ACPI_STATUS
289 AcpiDsResultStackPop (
290     ACPI_WALK_STATE         *WalkState)
291 {
292     ACPI_GENERIC_STATE      *State;
293 
294 
295     ACPI_FUNCTION_NAME (DsResultStackPop);
296 
297 
298     /* Check for stack underflow */
299 
300     if (WalkState->Results == NULL)
301     {
302         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
303             "Result stack underflow - State=%p\n", WalkState));
304         return (AE_AML_NO_OPERAND);
305     }
306 
307     if (WalkState->ResultSize < ACPI_RESULTS_FRAME_OBJ_NUM)
308     {
309         ACPI_ERROR ((AE_INFO, "Insufficient result stack size"));
310         return (AE_AML_INTERNAL);
311     }
312 
313     State = AcpiUtPopGenericState (&WalkState->Results);
314     AcpiUtDeleteGenericState (State);
315 
316     /* Decrease the length of result stack by the length of frame */
317 
318     WalkState->ResultSize -= ACPI_RESULTS_FRAME_OBJ_NUM;
319 
320     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
321         "Result=%p RemainingResults=%X State=%p\n",
322         State, WalkState->ResultCount, WalkState));
323 
324     return (AE_OK);
325 }
326 
327 
328 /*******************************************************************************
329  *
330  * FUNCTION:    AcpiDsObjStackPush
331  *
332  * PARAMETERS:  Object              - Object to push
333  *              WalkState           - Current Walk state
334  *
335  * RETURN:      Status
336  *
337  * DESCRIPTION: Push an object onto this walk's object/operand stack
338  *
339  ******************************************************************************/
340 
341 ACPI_STATUS
342 AcpiDsObjStackPush (
343     void                    *Object,
344     ACPI_WALK_STATE         *WalkState)
345 {
346     ACPI_FUNCTION_NAME (DsObjStackPush);
347 
348 
349     /* Check for stack overflow */
350 
351     if (WalkState->NumOperands >= ACPI_OBJ_NUM_OPERANDS)
352     {
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);
357     }
358 
359     /* Put the object onto the stack */
360 
361     WalkState->Operands [WalkState->OperandIndex] = Object;
362     WalkState->NumOperands++;
363 
364     /* For the usual order of filling the operand stack */
365 
366     WalkState->OperandIndex++;
367 
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));
371 
372     return (AE_OK);
373 }
374 
375 
376 /*******************************************************************************
377  *
378  * FUNCTION:    AcpiDsObjStackPop
379  *
380  * PARAMETERS:  PopCount            - Number of objects/entries to pop
381  *              WalkState           - Current Walk state
382  *
383  * RETURN:      Status
384  *
385  * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
386  *              deleted by this routine.
387  *
388  ******************************************************************************/
389 
390 ACPI_STATUS
391 AcpiDsObjStackPop (
392     UINT32                  PopCount,
393     ACPI_WALK_STATE         *WalkState)
394 {
395     UINT32                  i;
396 
397 
398     ACPI_FUNCTION_NAME (DsObjStackPop);
399 
400 
401     for (i = 0; i < PopCount; i++)
402     {
403         /* Check for stack underflow */
404 
405         if (WalkState->NumOperands == 0)
406         {
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);
411         }
412 
413         /* Just set the stack entry to null */
414 
415         WalkState->NumOperands--;
416         WalkState->Operands [WalkState->NumOperands] = NULL;
417     }
418 
419     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%u\n",
420         PopCount, WalkState, WalkState->NumOperands));
421 
422     return (AE_OK);
423 }
424 
425 
426 /*******************************************************************************
427  *
428  * FUNCTION:    AcpiDsObjStackPopAndDelete
429  *
430  * PARAMETERS:  PopCount            - Number of objects/entries to pop
431  *              WalkState           - Current Walk state
432  *
433  * RETURN:      Status
434  *
435  * DESCRIPTION: Pop this walk's object stack and delete each object that is
436  *              popped off.
437  *
438  ******************************************************************************/
439 
440 void
441 AcpiDsObjStackPopAndDelete (
442     UINT32                  PopCount,
443     ACPI_WALK_STATE         *WalkState)
444 {
445     INT32                   i;
446     ACPI_OPERAND_OBJECT     *ObjDesc;
447 
448 
449     ACPI_FUNCTION_NAME (DsObjStackPopAndDelete);
450 
451 
452     if (PopCount == 0)
453     {
454         return;
455     }
456 
457     for (i = (INT32) PopCount - 1; i >= 0; i--)
458     {
459         if (WalkState->NumOperands == 0)
460         {
461             return;
462         }
463 
464         /* Pop the stack and delete an object if present in this stack entry */
465 
466         WalkState->NumOperands--;
467         ObjDesc = WalkState->Operands [i];
468         if (ObjDesc)
469         {
470             AcpiUtRemoveReference (WalkState->Operands [i]);
471             WalkState->Operands [i] = NULL;
472         }
473     }
474 
475     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
476         PopCount, WalkState, WalkState->NumOperands));
477 }
478 
479 
480 /*******************************************************************************
481  *
482  * FUNCTION:    AcpiDsGetCurrentWalkState
483  *
484  * PARAMETERS:  Thread          - Get current active state for this Thread
485  *
486  * RETURN:      Pointer to the current walk state
487  *
488  * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
489  *              walk state.)
490  *
491  ******************************************************************************/
492 
493 ACPI_WALK_STATE *
494 AcpiDsGetCurrentWalkState (
495     ACPI_THREAD_STATE       *Thread)
496 {
497     ACPI_FUNCTION_NAME (DsGetCurrentWalkState);
498 
499 
500     if (!Thread)
501     {
502         return (NULL);
503     }
504 
505     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Current WalkState %p\n",
506         Thread->WalkStateList));
507 
508     return (Thread->WalkStateList);
509 }
510 
511 
512 /*******************************************************************************
513  *
514  * FUNCTION:    AcpiDsPushWalkState
515  *
516  * PARAMETERS:  WalkState       - State to push
517  *              Thread          - Thread state object
518  *
519  * RETURN:      None
520  *
521  * DESCRIPTION: Place the Thread state at the head of the state list
522  *
523  ******************************************************************************/
524 
525 void
526 AcpiDsPushWalkState (
527     ACPI_WALK_STATE         *WalkState,
528     ACPI_THREAD_STATE       *Thread)
529 {
530     ACPI_FUNCTION_TRACE (DsPushWalkState);
531 
532 
533     WalkState->Next = Thread->WalkStateList;
534     Thread->WalkStateList = WalkState;
535 
536     return_VOID;
537 }
538 
539 
540 /*******************************************************************************
541  *
542  * FUNCTION:    AcpiDsPopWalkState
543  *
544  * PARAMETERS:  Thread      - Current thread state
545  *
546  * RETURN:      A WalkState object popped from the thread's stack
547  *
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
550  *              the list is empty.
551  *
552  ******************************************************************************/
553 
554 ACPI_WALK_STATE *
555 AcpiDsPopWalkState (
556     ACPI_THREAD_STATE       *Thread)
557 {
558     ACPI_WALK_STATE         *WalkState;
559 
560 
561     ACPI_FUNCTION_TRACE (DsPopWalkState);
562 
563 
564     WalkState = Thread->WalkStateList;
565 
566     if (WalkState)
567     {
568         /* Next walk state becomes the current walk state */
569 
570         Thread->WalkStateList = WalkState->Next;
571 
572         /*
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;
576          */
577     }
578 
579     return_PTR (WalkState);
580 }
581 
582 
583 /*******************************************************************************
584  *
585  * FUNCTION:    AcpiDsCreateWalkState
586  *
587  * PARAMETERS:  OwnerId         - ID for object creation
588  *              Origin          - Starting point for this walk
589  *              MethodDesc      - Method object
590  *              Thread          - Current thread state
591  *
592  * RETURN:      Pointer to the new walk state.
593  *
594  * DESCRIPTION: Allocate and initialize a new walk state. The current walk
595  *              state is set to this new state.
596  *
597  ******************************************************************************/
598 
599 ACPI_WALK_STATE *
600 AcpiDsCreateWalkState (
601     ACPI_OWNER_ID           OwnerId,
602     ACPI_PARSE_OBJECT       *Origin,
603     ACPI_OPERAND_OBJECT     *MethodDesc,
604     ACPI_THREAD_STATE       *Thread)
605 {
606     ACPI_WALK_STATE         *WalkState;
607 
608 
609     ACPI_FUNCTION_TRACE (DsCreateWalkState);
610 
611 
612     WalkState = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_WALK_STATE));
613     if (!WalkState)
614     {
615         return_PTR (NULL);
616     }
617 
618     WalkState->DescriptorType = ACPI_DESC_TYPE_WALK;
619     WalkState->MethodDesc = MethodDesc;
620     WalkState->OwnerId = OwnerId;
621     WalkState->Origin = Origin;
622     WalkState->Thread = Thread;
623 
624     WalkState->ParserState.StartOp = Origin;
625 
626     /* Init the method args/local */
627 
628 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
629     AcpiDsMethodDataInit (WalkState);
630 #endif
631 
632     /* Put the new state at the head of the walk list */
633 
634     if (Thread)
635     {
636         AcpiDsPushWalkState (WalkState, Thread);
637     }
638 
639     return_PTR (WalkState);
640 }
641 
642 
643 /*******************************************************************************
644  *
645  * FUNCTION:    AcpiDsInitAmlWalk
646  *
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
654  *
655  * RETURN:      Status
656  *
657  * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
658  *
659  ******************************************************************************/
660 
661 ACPI_STATUS
662 AcpiDsInitAmlWalk (
663     ACPI_WALK_STATE         *WalkState,
664     ACPI_PARSE_OBJECT       *Op,
665     ACPI_NAMESPACE_NODE     *MethodNode,
666     UINT8                   *AmlStart,
667     UINT32                  AmlLength,
668     ACPI_EVALUATE_INFO      *Info,
669     UINT8                   PassNumber)
670 {
671     ACPI_STATUS             Status;
672     ACPI_PARSE_STATE        *ParserState = &WalkState->ParserState;
673     ACPI_PARSE_OBJECT       *ExtraOp;
674 
675 
676     ACPI_FUNCTION_TRACE (DsInitAmlWalk);
677 
678 
679     WalkState->ParserState.Aml =
680     WalkState->ParserState.AmlStart = AmlStart;
681     WalkState->ParserState.AmlEnd =
682     WalkState->ParserState.PkgEnd = AmlStart + AmlLength;
683 
684     /* The NextOp of the NextWalk will be the beginning of the method */
685 
686     WalkState->NextOp = NULL;
687     WalkState->PassNumber = PassNumber;
688 
689     if (Info)
690     {
691         WalkState->Params = Info->Parameters;
692         WalkState->CallerReturnDesc = &Info->ReturnObject;
693     }
694 
695     Status = AcpiPsInitScope (&WalkState->ParserState, Op);
696     if (ACPI_FAILURE (Status))
697     {
698         return_ACPI_STATUS (Status);
699     }
700 
701     if (MethodNode)
702     {
703         WalkState->ParserState.StartNode = MethodNode;
704         WalkState->WalkType = ACPI_WALK_METHOD;
705         WalkState->MethodNode = MethodNode;
706         WalkState->MethodDesc = AcpiNsGetAttachedObject (MethodNode);
707 
708         /* Push start scope on scope stack and make it current  */
709 
710         Status = AcpiDsScopeStackPush (
711             MethodNode, ACPI_TYPE_METHOD, WalkState);
712         if (ACPI_FAILURE (Status))
713         {
714             return_ACPI_STATUS (Status);
715         }
716 
717         /* Init the method arguments */
718 
719         Status = AcpiDsMethodDataInitArgs (WalkState->Params,
720                     ACPI_METHOD_NUM_ARGS, WalkState);
721         if (ACPI_FAILURE (Status))
722         {
723             return_ACPI_STATUS (Status);
724         }
725     }
726     else
727     {
728         /*
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.
733          */
734         ExtraOp = ParserState->StartOp;
735         while (ExtraOp && !ExtraOp->Common.Node)
736         {
737             ExtraOp = ExtraOp->Common.Parent;
738         }
739 
740         if (!ExtraOp)
741         {
742             ParserState->StartNode = NULL;
743         }
744         else
745         {
746             ParserState->StartNode = ExtraOp->Common.Node;
747         }
748 
749         if (ParserState->StartNode)
750         {
751             /* Push start scope on scope stack and make it current  */
752 
753             Status = AcpiDsScopeStackPush (ParserState->StartNode,
754                 ParserState->StartNode->Type, WalkState);
755             if (ACPI_FAILURE (Status))
756             {
757                 return_ACPI_STATUS (Status);
758             }
759         }
760     }
761 
762     Status = AcpiDsInitCallbacks (WalkState, PassNumber);
763     return_ACPI_STATUS (Status);
764 }
765 
766 
767 /*******************************************************************************
768  *
769  * FUNCTION:    AcpiDsDeleteWalkState
770  *
771  * PARAMETERS:  WalkState       - State to delete
772  *
773  * RETURN:      Status
774  *
775  * DESCRIPTION: Delete a walk state including all internal data structures
776  *
777  ******************************************************************************/
778 
779 void
780 AcpiDsDeleteWalkState (
781     ACPI_WALK_STATE         *WalkState)
782 {
783     ACPI_GENERIC_STATE      *State;
784 
785 
786     ACPI_FUNCTION_TRACE_PTR (DsDeleteWalkState, WalkState);
787 
788 
789     if (!WalkState)
790     {
791         return_VOID;
792     }
793 
794     if (WalkState->DescriptorType != ACPI_DESC_TYPE_WALK)
795     {
796         ACPI_ERROR ((AE_INFO, "%p is not a valid walk state",
797             WalkState));
798         return_VOID;
799     }
800 
801     /* There should not be any open scopes */
802 
803     if (WalkState->ParserState.Scope)
804     {
805         ACPI_ERROR ((AE_INFO, "%p walk still has a scope list",
806             WalkState));
807         AcpiPsCleanupScope (&WalkState->ParserState);
808     }
809 
810     /* Always must free any linked control states */
811 
812     while (WalkState->ControlState)
813     {
814         State = WalkState->ControlState;
815         WalkState->ControlState = State->Common.Next;
816 
817         AcpiUtDeleteGenericState (State);
818     }
819 
820     /* Always must free any linked parse states */
821 
822     while (WalkState->ScopeInfo)
823     {
824         State = WalkState->ScopeInfo;
825         WalkState->ScopeInfo = State->Common.Next;
826 
827         AcpiUtDeleteGenericState (State);
828     }
829 
830     /* Always must free any stacked result states */
831 
832     while (WalkState->Results)
833     {
834         State = WalkState->Results;
835         WalkState->Results = State->Common.Next;
836 
837         AcpiUtDeleteGenericState (State);
838     }
839 
840     ACPI_FREE (WalkState);
841     return_VOID;
842 }
843