dswstate.c revision 84491
1/******************************************************************************
2 *
3 * Module Name: dswstate - Dispatcher parse tree walk management routines
4 *              $Revision: 54 $
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999, 2000, 2001, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
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.
21 *
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
28 *
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;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
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.
54 *
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.
66 *
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.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
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.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
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.
90 *
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.
99 *
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.
114 *
115 *****************************************************************************/
116
117
118#define __DSWSTATE_C__
119
120#include "acpi.h"
121#include "amlcode.h"
122#include "acparser.h"
123#include "acdispat.h"
124#include "acnamesp.h"
125#include "acinterp.h"
126
127#define _COMPONENT          ACPI_DISPATCHER
128        MODULE_NAME         ("dswstate")
129
130
131/*******************************************************************************
132 *
133 * FUNCTION:    AcpiDsResultInsert
134 *
135 * PARAMETERS:  Object              - Object to push
136 *              WalkState           - Current Walk state
137 *
138 * RETURN:      Status
139 *
140 * DESCRIPTION: Push an object onto this walk's result stack
141 *
142 ******************************************************************************/
143
144ACPI_STATUS
145AcpiDsResultInsert (
146    void                    *Object,
147    UINT32                  Index,
148    ACPI_WALK_STATE         *WalkState)
149{
150    ACPI_GENERIC_STATE      *State;
151
152
153    PROC_NAME ("DsResultInsert");
154
155
156    State = WalkState->Results;
157    if (!State)
158    {
159        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n",
160            WalkState));
161        return (AE_NOT_EXIST);
162    }
163
164    if (Index >= OBJ_NUM_OPERANDS)
165    {
166        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
167            "Index out of range: %X Obj=%p State=%p Num=%X\n",
168            Index, Object, WalkState, State->Results.NumResults));
169        return (AE_BAD_PARAMETER);
170    }
171
172    if (!Object)
173    {
174        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
175            "Null Object! Index=%X Obj=%p State=%p Num=%X\n",
176            Index, Object, WalkState, State->Results.NumResults));
177        return (AE_BAD_PARAMETER);
178    }
179
180    State->Results.ObjDesc [Index] = Object;
181    State->Results.NumResults++;
182
183    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
184        "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
185        Object, Object ? AcpiUtGetTypeName (((ACPI_OPERAND_OBJECT *) Object)->Common.Type) : "NULL",
186        WalkState, State->Results.NumResults, WalkState->CurrentResult));
187
188    return (AE_OK);
189}
190
191
192/*******************************************************************************
193 *
194 * FUNCTION:    AcpiDsResultRemove
195 *
196 * PARAMETERS:  Object              - Where to return the popped object
197 *              WalkState           - Current Walk state
198 *
199 * RETURN:      Status
200 *
201 * DESCRIPTION: Pop an object off the bottom of this walk's result stack.  In
202 *              other words, this is a FIFO.
203 *
204 ******************************************************************************/
205
206ACPI_STATUS
207AcpiDsResultRemove (
208    ACPI_OPERAND_OBJECT     **Object,
209    UINT32                  Index,
210    ACPI_WALK_STATE         *WalkState)
211{
212    ACPI_GENERIC_STATE      *State;
213
214
215    PROC_NAME ("DsResultRemove");
216
217
218    State = WalkState->Results;
219    if (!State)
220    {
221        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n",
222            WalkState));
223        return (AE_NOT_EXIST);
224    }
225
226    if (Index >= OBJ_NUM_OPERANDS)
227    {
228        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
229            "Index out of range: %X State=%p Num=%X\n",
230            Index, WalkState, State->Results.NumResults));
231    }
232
233
234    /* Check for a valid result object */
235
236    if (!State->Results.ObjDesc [Index])
237    {
238        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
239            "Null operand! State=%p #Ops=%X, Index=%X\n",
240            WalkState, State->Results.NumResults, Index));
241        return (AE_AML_NO_RETURN_VALUE);
242    }
243
244    /* Remove the object */
245
246    State->Results.NumResults--;
247
248    *Object = State->Results.ObjDesc [Index];
249    State->Results.ObjDesc [Index] = NULL;
250
251    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
252        "Obj=%p [%s] Index=%X State=%p Num=%X\n",
253        *Object, (*Object) ? AcpiUtGetTypeName ((*Object)->Common.Type) : "NULL",
254        Index, WalkState, State->Results.NumResults));
255
256    return (AE_OK);
257}
258
259
260/*******************************************************************************
261 *
262 * FUNCTION:    AcpiDsResultPop
263 *
264 * PARAMETERS:  Object              - Where to return the popped object
265 *              WalkState           - Current Walk state
266 *
267 * RETURN:      Status
268 *
269 * DESCRIPTION: Pop an object off the bottom of this walk's result stack.  In
270 *              other words, this is a FIFO.
271 *
272 ******************************************************************************/
273
274ACPI_STATUS
275AcpiDsResultPop (
276    ACPI_OPERAND_OBJECT     **Object,
277    ACPI_WALK_STATE         *WalkState)
278{
279    UINT32                  Index;
280    ACPI_GENERIC_STATE      *State;
281
282
283    PROC_NAME ("DsResultPop");
284
285
286    State = WalkState->Results;
287    if (!State)
288    {
289        return (AE_OK);
290    }
291
292    if (!State->Results.NumResults)
293    {
294        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Result stack is empty! State=%p\n",
295            WalkState));
296        return (AE_AML_NO_RETURN_VALUE);
297    }
298
299    /* Remove top element */
300
301    State->Results.NumResults--;
302
303    for (Index = OBJ_NUM_OPERANDS; Index; Index--)
304    {
305        /* Check for a valid result object */
306
307        if (State->Results.ObjDesc [Index -1])
308        {
309            *Object = State->Results.ObjDesc [Index -1];
310            State->Results.ObjDesc [Index -1] = NULL;
311
312            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] Index=%X State=%p Num=%X\n",
313                *Object, (*Object) ? AcpiUtGetTypeName ((*Object)->Common.Type) : "NULL",
314                Index -1, WalkState, State->Results.NumResults));
315
316            return (AE_OK);
317        }
318    }
319
320    ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n", WalkState));
321    return (AE_AML_NO_RETURN_VALUE);
322}
323
324/*******************************************************************************
325 *
326 * FUNCTION:    AcpiDsResultPopFromBottom
327 *
328 * PARAMETERS:  Object              - Where to return the popped object
329 *              WalkState           - Current Walk state
330 *
331 * RETURN:      Status
332 *
333 * DESCRIPTION: Pop an object off the bottom of this walk's result stack.  In
334 *              other words, this is a FIFO.
335 *
336 ******************************************************************************/
337
338ACPI_STATUS
339AcpiDsResultPopFromBottom (
340    ACPI_OPERAND_OBJECT     **Object,
341    ACPI_WALK_STATE         *WalkState)
342{
343    UINT32                  Index;
344    ACPI_GENERIC_STATE      *State;
345
346
347    PROC_NAME ("DsResultPopFromBottom");
348
349
350    State = WalkState->Results;
351    if (!State)
352    {
353        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
354            "Warning: No result object pushed! State=%p\n", WalkState));
355        return (AE_NOT_EXIST);
356    }
357
358
359    if (!State->Results.NumResults)
360    {
361        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n", WalkState));
362        return (AE_AML_NO_RETURN_VALUE);
363    }
364
365    /* Remove Bottom element */
366
367    *Object = State->Results.ObjDesc [0];
368
369    /* Push entire stack down one element */
370
371    for (Index = 0; Index < State->Results.NumResults; Index++)
372    {
373        State->Results.ObjDesc [Index] = State->Results.ObjDesc [Index + 1];
374    }
375
376    State->Results.NumResults--;
377
378    /* Check for a valid result object */
379
380    if (!*Object)
381    {
382        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null operand! State=%p #Ops=%X, Index=%X\n",
383            WalkState, State->Results.NumResults, Index));
384        return (AE_AML_NO_RETURN_VALUE);
385    }
386
387    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s], Results=%p State=%p\n",
388        *Object, (*Object) ? AcpiUtGetTypeName ((*Object)->Common.Type) : "NULL",
389        State, WalkState));
390
391
392    return (AE_OK);
393}
394
395
396/*******************************************************************************
397 *
398 * FUNCTION:    AcpiDsResultPush
399 *
400 * PARAMETERS:  Object              - Where to return the popped object
401 *              WalkState           - Current Walk state
402 *
403 * RETURN:      Status
404 *
405 * DESCRIPTION: Push an object onto the current result stack
406 *
407 ******************************************************************************/
408
409ACPI_STATUS
410AcpiDsResultPush (
411    ACPI_OPERAND_OBJECT     *Object,
412    ACPI_WALK_STATE         *WalkState)
413{
414    ACPI_GENERIC_STATE      *State;
415
416
417    PROC_NAME ("DsResultPush");
418
419
420    State = WalkState->Results;
421    if (!State)
422    {
423        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result stack frame\n"));
424        return (AE_AML_INTERNAL);
425    }
426
427    if (State->Results.NumResults == OBJ_NUM_OPERANDS)
428    {
429        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
430            "Result stack overflow: Obj=%p State=%p Num=%X\n",
431            Object, WalkState, State->Results.NumResults));
432        return (AE_STACK_OVERFLOW);
433    }
434
435    if (!Object)
436    {
437        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Object! Obj=%p State=%p Num=%X\n",
438            Object, WalkState, State->Results.NumResults));
439        return (AE_BAD_PARAMETER);
440    }
441
442
443    State->Results.ObjDesc [State->Results.NumResults] = Object;
444    State->Results.NumResults++;
445
446    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
447        Object, Object ? AcpiUtGetTypeName (((ACPI_OPERAND_OBJECT *) Object)->Common.Type) : "NULL",
448        WalkState, State->Results.NumResults, WalkState->CurrentResult));
449
450    return (AE_OK);
451}
452
453
454/*******************************************************************************
455 *
456 * FUNCTION:    AcpiDsResultStackPush
457 *
458 * PARAMETERS:  Object              - Object to push
459 *              WalkState           - Current Walk state
460 *
461 * RETURN:      Status
462 *
463 * DESCRIPTION:
464 *
465 ******************************************************************************/
466
467ACPI_STATUS
468AcpiDsResultStackPush (
469    ACPI_WALK_STATE         *WalkState)
470{
471    ACPI_GENERIC_STATE      *State;
472
473    PROC_NAME ("DsResultStackPush");
474
475
476    State = AcpiUtCreateGenericState ();
477    if (!State)
478    {
479        return (AE_NO_MEMORY);
480    }
481
482    State->Common.DataType  = ACPI_DESC_TYPE_STATE_RESULT;
483    AcpiUtPushGenericState (&WalkState->Results, State);
484
485    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Results=%p State=%p\n",
486        State, WalkState));
487
488    return (AE_OK);
489}
490
491
492/*******************************************************************************
493 *
494 * FUNCTION:    AcpiDsResultStackPop
495 *
496 * PARAMETERS:  WalkState           - Current Walk state
497 *
498 * RETURN:      Status
499 *
500 * DESCRIPTION:
501 *
502 ******************************************************************************/
503
504ACPI_STATUS
505AcpiDsResultStackPop (
506    ACPI_WALK_STATE         *WalkState)
507{
508    ACPI_GENERIC_STATE      *State;
509
510    PROC_NAME ("DsResultStackPop");
511
512
513    /* Check for stack underflow */
514
515    if (WalkState->Results == NULL)
516    {
517        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Underflow - State=%p\n",
518            WalkState));
519        return (AE_AML_NO_OPERAND);
520    }
521
522
523    State = AcpiUtPopGenericState (&WalkState->Results);
524
525    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
526        "Result=%p RemainingResults=%X State=%p\n",
527        State, State->Results.NumResults, WalkState));
528
529    AcpiUtDeleteGenericState (State);
530
531    return (AE_OK);
532}
533
534
535/*******************************************************************************
536 *
537 * FUNCTION:    AcpiDsObjStackDeleteAll
538 *
539 * PARAMETERS:  WalkState           - Current Walk state
540 *
541 * RETURN:      Status
542 *
543 * DESCRIPTION: Clear the object stack by deleting all objects that are on it.
544 *              Should be used with great care, if at all!
545 *
546 ******************************************************************************/
547
548ACPI_STATUS
549AcpiDsObjStackDeleteAll (
550    ACPI_WALK_STATE         *WalkState)
551{
552    UINT32                  i;
553
554
555    FUNCTION_TRACE_PTR ("DsObjStackDeleteAll", WalkState);
556
557
558    /* The stack size is configurable, but fixed */
559
560    for (i = 0; i < OBJ_NUM_OPERANDS; i++)
561    {
562        if (WalkState->Operands[i])
563        {
564            AcpiUtRemoveReference (WalkState->Operands[i]);
565            WalkState->Operands[i] = NULL;
566        }
567    }
568
569    return_ACPI_STATUS (AE_OK);
570}
571
572
573/*******************************************************************************
574 *
575 * FUNCTION:    AcpiDsObjStackPush
576 *
577 * PARAMETERS:  Object              - Object to push
578 *              WalkState           - Current Walk state
579 *
580 * RETURN:      Status
581 *
582 * DESCRIPTION: Push an object onto this walk's object/operand stack
583 *
584 ******************************************************************************/
585
586ACPI_STATUS
587AcpiDsObjStackPush (
588    void                    *Object,
589    ACPI_WALK_STATE         *WalkState)
590{
591    PROC_NAME ("DsObjStackPush");
592
593
594    /* Check for stack overflow */
595
596    if (WalkState->NumOperands >= OBJ_NUM_OPERANDS)
597    {
598        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
599            "overflow! Obj=%p State=%p #Ops=%X\n",
600            Object, WalkState, WalkState->NumOperands));
601        return (AE_STACK_OVERFLOW);
602    }
603
604    /* Put the object onto the stack */
605
606    WalkState->Operands [WalkState->NumOperands] = Object;
607    WalkState->NumOperands++;
608
609    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
610                    Object, AcpiUtGetTypeName (((ACPI_OPERAND_OBJECT *) Object)->Common.Type),
611                    WalkState, WalkState->NumOperands));
612
613    return (AE_OK);
614}
615
616
617#if 0
618/*******************************************************************************
619 *
620 * FUNCTION:    AcpiDsObjStackPopObject
621 *
622 * PARAMETERS:  PopCount            - Number of objects/entries to pop
623 *              WalkState           - Current Walk state
624 *
625 * RETURN:      Status
626 *
627 * DESCRIPTION: Pop this walk's object stack.  Objects on the stack are NOT
628 *              deleted by this routine.
629 *
630 ******************************************************************************/
631
632ACPI_STATUS
633AcpiDsObjStackPopObject (
634    ACPI_OPERAND_OBJECT     **Object,
635    ACPI_WALK_STATE         *WalkState)
636{
637    PROC_NAME ("DsObjStackPopObject");
638
639
640    /* Check for stack underflow */
641
642    if (WalkState->NumOperands == 0)
643    {
644        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
645            "Missing operand/stack empty! State=%p #Ops=%X\n",
646            WalkState, WalkState->NumOperands));
647        *Object = NULL;
648        return (AE_AML_NO_OPERAND);
649    }
650
651    /* Pop the stack */
652
653    WalkState->NumOperands--;
654
655    /* Check for a valid operand */
656
657    if (!WalkState->Operands [WalkState->NumOperands])
658    {
659        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
660            "Null operand! State=%p #Ops=%X\n",
661            WalkState, WalkState->NumOperands));
662        *Object = NULL;
663        return (AE_AML_NO_OPERAND);
664    }
665
666    /* Get operand and set stack entry to null */
667
668    *Object = WalkState->Operands [WalkState->NumOperands];
669    WalkState->Operands [WalkState->NumOperands] = NULL;
670
671    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
672                    *Object, AcpiUtGetTypeName ((*Object)->Common.Type),
673                    WalkState, WalkState->NumOperands));
674
675    return (AE_OK);
676}
677#endif
678
679/*******************************************************************************
680 *
681 * FUNCTION:    AcpiDsObjStackPop
682 *
683 * PARAMETERS:  PopCount            - Number of objects/entries to pop
684 *              WalkState           - Current Walk state
685 *
686 * RETURN:      Status
687 *
688 * DESCRIPTION: Pop this walk's object stack.  Objects on the stack are NOT
689 *              deleted by this routine.
690 *
691 ******************************************************************************/
692
693ACPI_STATUS
694AcpiDsObjStackPop (
695    UINT32                  PopCount,
696    ACPI_WALK_STATE         *WalkState)
697{
698    UINT32                  i;
699
700    PROC_NAME ("DsObjStackPop");
701
702
703    for (i = 0; i < PopCount; i++)
704    {
705        /* Check for stack underflow */
706
707        if (WalkState->NumOperands == 0)
708        {
709            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
710                "Underflow! Count=%X State=%p #Ops=%X\n",
711                PopCount, WalkState, WalkState->NumOperands));
712            return (AE_STACK_UNDERFLOW);
713        }
714
715        /* Just set the stack entry to null */
716
717        WalkState->NumOperands--;
718        WalkState->Operands [WalkState->NumOperands] = NULL;
719    }
720
721    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
722                    PopCount, WalkState, WalkState->NumOperands));
723
724    return (AE_OK);
725}
726
727
728/*******************************************************************************
729 *
730 * FUNCTION:    AcpiDsObjStackPopAndDelete
731 *
732 * PARAMETERS:  PopCount            - Number of objects/entries to pop
733 *              WalkState           - Current Walk state
734 *
735 * RETURN:      Status
736 *
737 * DESCRIPTION: Pop this walk's object stack and delete each object that is
738 *              popped off.
739 *
740 ******************************************************************************/
741
742ACPI_STATUS
743AcpiDsObjStackPopAndDelete (
744    UINT32                  PopCount,
745    ACPI_WALK_STATE         *WalkState)
746{
747    UINT32                  i;
748    ACPI_OPERAND_OBJECT     *ObjDesc;
749
750    PROC_NAME ("DsObjStackPopAndDelete");
751
752
753    for (i = 0; i < PopCount; i++)
754    {
755        /* Check for stack underflow */
756
757        if (WalkState->NumOperands == 0)
758        {
759            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
760                "Underflow! Count=%X State=%p #Ops=%X\n",
761                PopCount, WalkState, WalkState->NumOperands));
762            return (AE_STACK_UNDERFLOW);
763        }
764
765        /* Pop the stack and delete an object if present in this stack entry */
766
767        WalkState->NumOperands--;
768        ObjDesc = WalkState->Operands [WalkState->NumOperands];
769        if (ObjDesc)
770        {
771            AcpiUtRemoveReference (WalkState->Operands [WalkState->NumOperands]);
772            WalkState->Operands [WalkState->NumOperands] = NULL;
773        }
774    }
775
776    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
777                    PopCount, WalkState, WalkState->NumOperands));
778
779    return (AE_OK);
780}
781
782
783/*******************************************************************************
784 *
785 * FUNCTION:    AcpiDsObjStackGetValue
786 *
787 * PARAMETERS:  Index               - Stack index whose value is desired.  Based
788 *                                    on the top of the stack (index=0 == top)
789 *              WalkState           - Current Walk state
790 *
791 * RETURN:      Status
792 *
793 * DESCRIPTION: Retrieve an object from this walk's object stack.  Index must
794 *              be within the range of the current stack pointer.
795 *
796 ******************************************************************************/
797
798void *
799AcpiDsObjStackGetValue (
800    UINT32                  Index,
801    ACPI_WALK_STATE         *WalkState)
802{
803
804    FUNCTION_TRACE_PTR ("DsObjStackGetValue", WalkState);
805
806
807    /* Can't do it if the stack is empty */
808
809    if (WalkState->NumOperands == 0)
810    {
811        return_PTR (NULL);
812    }
813
814    /* or if the index is past the top of the stack */
815
816    if (Index > (WalkState->NumOperands - (UINT32) 1))
817    {
818        return_PTR (NULL);
819    }
820
821
822    return_PTR (WalkState->Operands[(NATIVE_UINT)(WalkState->NumOperands - 1) -
823                    Index]);
824}
825
826
827/*******************************************************************************
828 *
829 * FUNCTION:    AcpiDsGetCurrentWalkState
830 *
831 * PARAMETERS:  WalkList        - Get current active state for this walk list
832 *
833 * RETURN:      Pointer to the current walk state
834 *
835 * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
836 *              walk state.
837 *
838 ******************************************************************************/
839
840ACPI_WALK_STATE *
841AcpiDsGetCurrentWalkState (
842    ACPI_WALK_LIST          *WalkList)
843
844{
845    PROC_NAME ("DsGetCurrentWalkState");
846
847
848    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "DsGetCurrentWalkState, =%p\n",
849        WalkList->WalkState));
850
851    if (!WalkList)
852    {
853        return (NULL);
854    }
855
856    return (WalkList->WalkState);
857}
858
859
860/*******************************************************************************
861 *
862 * FUNCTION:    AcpiDsPushWalkState
863 *
864 * PARAMETERS:  WalkState       - State to push
865 *              WalkList        - The list that owns the walk stack
866 *
867 * RETURN:      None
868 *
869 * DESCRIPTION: Place the WalkState at the head of the state list.
870 *
871 ******************************************************************************/
872
873void
874AcpiDsPushWalkState (
875    ACPI_WALK_STATE         *WalkState,
876    ACPI_WALK_LIST          *WalkList)
877{
878    FUNCTION_TRACE ("DsPushWalkState");
879
880
881    WalkState->Next     = WalkList->WalkState;
882    WalkList->WalkState = WalkState;
883
884    return_VOID;
885}
886
887
888/*******************************************************************************
889 *
890 * FUNCTION:    AcpiDsPopWalkState
891 *
892 * PARAMETERS:  WalkList        - The list that owns the walk stack
893 *
894 * RETURN:      A WalkState object popped from the stack
895 *
896 * DESCRIPTION: Remove and return the walkstate object that is at the head of
897 *              the walk stack for the given walk list.  NULL indicates that
898 *              the list is empty.
899 *
900 ******************************************************************************/
901
902ACPI_WALK_STATE *
903AcpiDsPopWalkState (
904    ACPI_WALK_LIST          *WalkList)
905{
906    ACPI_WALK_STATE         *WalkState;
907
908
909    FUNCTION_TRACE ("DsPopWalkState");
910
911
912    WalkState = WalkList->WalkState;
913
914    if (WalkState)
915    {
916        /* Next walk state becomes the current walk state */
917
918        WalkList->WalkState = WalkState->Next;
919
920        /*
921         * Don't clear the NEXT field, this serves as an indicator
922         * that there is a parent WALK STATE
923         *     WalkState->Next = NULL;
924         */
925    }
926
927    return_PTR (WalkState);
928}
929
930
931/*******************************************************************************
932 *
933 * FUNCTION:    AcpiDsCreateWalkState
934 *
935 * PARAMETERS:  Origin          - Starting point for this walk
936 *              WalkList        - Owning walk list
937 *
938 * RETURN:      Pointer to the new walk state.
939 *
940 * DESCRIPTION: Allocate and initialize a new walk state.  The current walk state
941 *              is set to this new state.
942 *
943 ******************************************************************************/
944
945ACPI_WALK_STATE *
946AcpiDsCreateWalkState (
947    ACPI_OWNER_ID           OwnerId,
948    ACPI_PARSE_OBJECT       *Origin,
949    ACPI_OPERAND_OBJECT     *MthDesc,
950    ACPI_WALK_LIST          *WalkList)
951{
952    ACPI_WALK_STATE         *WalkState;
953    ACPI_STATUS             Status;
954
955
956    FUNCTION_TRACE ("DsCreateWalkState");
957
958
959    WalkState = AcpiUtAcquireFromCache (ACPI_MEM_LIST_WALK);
960    if (!WalkState)
961    {
962        return_PTR (NULL);
963    }
964
965    WalkState->DataType         = ACPI_DESC_TYPE_WALK;
966    WalkState->OwnerId          = OwnerId;
967    WalkState->Origin           = Origin;
968    WalkState->MethodDesc       = MthDesc;
969    WalkState->WalkList         = WalkList;
970
971    /* Init the method args/local */
972
973#ifndef _ACPI_ASL_COMPILER
974    AcpiDsMethodDataInit (WalkState);
975#endif
976
977    /* Create an initial result stack entry */
978
979    Status = AcpiDsResultStackPush (WalkState);
980    if (ACPI_FAILURE (Status))
981    {
982        return_PTR (NULL);
983    }
984
985    /* Put the new state at the head of the walk list */
986
987    if (WalkList)
988    {
989        AcpiDsPushWalkState (WalkState, WalkList);
990    }
991
992    return_PTR (WalkState);
993}
994
995
996#ifndef _ACPI_ASL_COMPILER
997/*******************************************************************************
998 *
999 * FUNCTION:    AcpiDsInitAmlWalk
1000 *
1001 * PARAMETERS:  WalkState       - New state to be initialized
1002 *
1003 * RETURN:      None
1004 *
1005 * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
1006 *
1007 ******************************************************************************/
1008
1009ACPI_STATUS
1010AcpiDsInitAmlWalk (
1011    ACPI_WALK_STATE         *WalkState,
1012    ACPI_PARSE_OBJECT       *Op,
1013    ACPI_NAMESPACE_NODE     *MethodNode,
1014    UINT8                   *AmlStart,
1015    UINT32                  AmlLength,
1016    ACPI_OPERAND_OBJECT     **Params,
1017    ACPI_OPERAND_OBJECT     **ReturnObjDesc,
1018    UINT32                  PassNumber)
1019{
1020    ACPI_STATUS             Status;
1021    ACPI_PARSE_STATE        *ParserState = &WalkState->ParserState;
1022
1023
1024    FUNCTION_TRACE ("DsInitAmlWalk");
1025
1026
1027    WalkState->ParserState.Aml      =
1028    WalkState->ParserState.AmlStart = AmlStart;
1029    WalkState->ParserState.AmlEnd   =
1030    WalkState->ParserState.PkgEnd   = AmlStart + AmlLength;
1031
1032    /* The NextOp of the NextWalk will be the beginning of the method */
1033    /* TBD: [Restructure] -- obsolete? */
1034
1035    WalkState->NextOp               = NULL;
1036    WalkState->Params               = Params;
1037    WalkState->CallerReturnDesc     = ReturnObjDesc;
1038
1039    Status = AcpiPsInitScope (&WalkState->ParserState, Op);
1040    if (ACPI_FAILURE (Status))
1041    {
1042        return_ACPI_STATUS (Status);
1043    }
1044
1045    if (MethodNode)
1046    {
1047        WalkState->ParserState.StartNode    = MethodNode;
1048        WalkState->WalkType                 = WALK_METHOD;
1049        WalkState->MethodNode               = MethodNode;
1050        WalkState->MethodDesc               = AcpiNsGetAttachedObject (MethodNode);
1051
1052
1053        /* Push start scope on scope stack and make it current  */
1054
1055        Status = AcpiDsScopeStackPush (MethodNode, ACPI_TYPE_METHOD, WalkState);
1056        if (ACPI_FAILURE (Status))
1057        {
1058            return_ACPI_STATUS (Status);
1059        }
1060
1061        /* Init the method arguments */
1062
1063        AcpiDsMethodDataInitArgs (Params, MTH_NUM_ARGS, WalkState);
1064    }
1065
1066    else
1067    {
1068        /* Setup the current scope */
1069
1070        ParserState->StartNode = ParserState->StartOp->Node;
1071        if (ParserState->StartNode)
1072        {
1073            /* Push start scope on scope stack and make it current  */
1074
1075            Status = AcpiDsScopeStackPush (ParserState->StartNode,
1076                            ParserState->StartNode->Type, WalkState);
1077            if (ACPI_FAILURE (Status))
1078            {
1079                return_ACPI_STATUS (Status);
1080            }
1081        }
1082    }
1083
1084    AcpiDsInitCallbacks (WalkState, PassNumber);
1085
1086    return_ACPI_STATUS (AE_OK);
1087}
1088#endif
1089
1090
1091
1092/*******************************************************************************
1093 *
1094 * FUNCTION:    AcpiDsDeleteWalkState
1095 *
1096 * PARAMETERS:  WalkState       - State to delete
1097 *
1098 * RETURN:      Status
1099 *
1100 * DESCRIPTION: Delete a walk state including all internal data structures
1101 *
1102 ******************************************************************************/
1103
1104void
1105AcpiDsDeleteWalkState (
1106    ACPI_WALK_STATE         *WalkState)
1107{
1108    ACPI_GENERIC_STATE      *State;
1109
1110
1111    FUNCTION_TRACE_PTR ("DsDeleteWalkState", WalkState);
1112
1113
1114    if (!WalkState)
1115    {
1116        return;
1117    }
1118
1119    if (WalkState->DataType != ACPI_DESC_TYPE_WALK)
1120    {
1121        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p is not a valid walk state\n", WalkState));
1122        return;
1123    }
1124
1125
1126    if (WalkState->ParserState.Scope)
1127    {
1128        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p walk still has a scope list\n", WalkState));
1129    }
1130
1131   /* Always must free any linked control states */
1132
1133    while (WalkState->ControlState)
1134    {
1135        State = WalkState->ControlState;
1136        WalkState->ControlState = State->Common.Next;
1137
1138        AcpiUtDeleteGenericState (State);
1139    }
1140
1141    /* Always must free any linked parse states */
1142
1143    while (WalkState->ScopeInfo)
1144    {
1145        State = WalkState->ScopeInfo;
1146        WalkState->ScopeInfo = State->Common.Next;
1147
1148        AcpiUtDeleteGenericState (State);
1149    }
1150
1151    /* Always must free any stacked result states */
1152
1153    while (WalkState->Results)
1154    {
1155        State = WalkState->Results;
1156        WalkState->Results = State->Common.Next;
1157
1158        AcpiUtDeleteGenericState (State);
1159    }
1160
1161    AcpiUtReleaseToCache (ACPI_MEM_LIST_WALK, WalkState);
1162    return_VOID;
1163}
1164
1165
1166/******************************************************************************
1167 *
1168 * FUNCTION:    AcpiDsDeleteWalkStateCache
1169 *
1170 * PARAMETERS:  None
1171 *
1172 * RETURN:      Status
1173 *
1174 * DESCRIPTION: Purge the global state object cache.  Used during subsystem
1175 *              termination.
1176 *
1177 ******************************************************************************/
1178
1179void
1180AcpiDsDeleteWalkStateCache (
1181    void)
1182{
1183    FUNCTION_TRACE ("DsDeleteWalkStateCache");
1184
1185
1186    AcpiUtDeleteGenericCache (ACPI_MEM_LIST_WALK);
1187    return_VOID;
1188}
1189
1190
1191