Subversion Repositories Kolibri OS

Rev

Rev 1498 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 1
/******************************************************************************
2
 *
3
 * Module Name: psparse - Parser top level AML parse routines
4
 *
5
 *****************************************************************************/
6
 
7
/******************************************************************************
8
 *
9
 * 1. Copyright Notice
10
 *
2216 Serge 11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
1498 serge 12
 * All rights reserved.
13
 *
14
 * 2. License
15
 *
16
 * 2.1. This is your license from Intel Corp. under its intellectual property
17
 * rights.  You may have additional license terms from the party that provided
18
 * you this software, covering your right to use that party's intellectual
19
 * property rights.
20
 *
21
 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
 * copy of the source code appearing in this file ("Covered Code") an
23
 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
 * base code distributed originally by Intel ("Original Intel Code") to copy,
25
 * make derivatives, distribute, use and display any portion of the Covered
26
 * Code in any form, with the right to sublicense such rights; and
27
 *
28
 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
 * license (with the right to sublicense), under only those claims of Intel
30
 * patents that are infringed by the Original Intel Code, to make, use, sell,
31
 * offer to sell, and import the Covered Code and derivative works thereof
32
 * solely to the minimum extent necessary to exercise the above copyright
33
 * license, and in no event shall the patent license extend to any additions
34
 * to or modifications of the Original Intel Code.  No other license or right
35
 * is granted directly or by implication, estoppel or otherwise;
36
 *
37
 * The above copyright and patent license is granted only if the following
38
 * conditions are met:
39
 *
40
 * 3. Conditions
41
 *
42
 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
 * Redistribution of source code of any substantial portion of the Covered
44
 * Code or modification with rights to further distribute source must include
45
 * the above Copyright Notice, the above License, this list of Conditions,
46
 * and the following Disclaimer and Export Compliance provision.  In addition,
47
 * Licensee must cause all Covered Code to which Licensee contributes to
48
 * contain a file documenting the changes Licensee made to create that Covered
49
 * Code and the date of any change.  Licensee must include in that file the
50
 * documentation of any changes made by any predecessor Licensee.  Licensee
51
 * must include a prominent statement that the modification is derived,
52
 * directly or indirectly, from Original Intel Code.
53
 *
54
 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
 * Redistribution of source code of any substantial portion of the Covered
56
 * Code or modification without rights to further distribute source must
57
 * include the following Disclaimer and Export Compliance provision in the
58
 * documentation and/or other materials provided with distribution.  In
59
 * addition, Licensee may not authorize further sublicense of source of any
60
 * portion of the Covered Code, and must include terms to the effect that the
61
 * license from Licensee to its licensee is limited to the intellectual
62
 * property embodied in the software Licensee provides to its licensee, and
63
 * not to intellectual property embodied in modifications its licensee may
64
 * make.
65
 *
66
 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67
 * substantial portion of the Covered Code or modification must reproduce the
68
 * above Copyright Notice, and the following Disclaimer and Export Compliance
69
 * provision in the documentation and/or other materials provided with the
70
 * distribution.
71
 *
72
 * 3.4. Intel retains all right, title, and interest in and to the Original
73
 * Intel Code.
74
 *
75
 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
 * Intel shall be used in advertising or otherwise to promote the sale, use or
77
 * other dealings in products derived from or relating to the Covered Code
78
 * without prior written authorization from Intel.
79
 *
80
 * 4. Disclaimer and Export Compliance
81
 *
82
 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85
 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86
 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
 * PARTICULAR PURPOSE.
89
 *
90
 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96
 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
 * LIMITED REMEDY.
98
 *
99
 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100
 * software or system incorporating such software without first obtaining any
101
 * required license or other approval from the U. S. Department of Commerce or
102
 * any other agency or department of the United States Government.  In the
103
 * event Licensee exports any such software from the United States or
104
 * re-exports any such software from a foreign destination, Licensee shall
105
 * ensure that the distribution and export/re-export of the software is in
106
 * compliance with all laws, regulations, orders, or other restrictions of the
107
 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
 * any of its subsidiaries will export/re-export any technical data, process,
109
 * software, or service, directly or indirectly, to any country for which the
110
 * United States government or any agency thereof requires an export license,
111
 * other governmental approval, or letter of assurance, without first obtaining
112
 * such license, approval or letter.
113
 *
114
 *****************************************************************************/
115
 
116
 
117
/*
118
 * Parse the AML and build an operation tree as most interpreters,
119
 * like Perl, do.  Parsing is done by hand rather than with a YACC
120
 * generated parser to tightly constrain stack and dynamic memory
121
 * usage.  At the same time, parsing is kept flexible and the code
122
 * fairly compact by parsing based on a list of AML opcode
123
 * templates in AmlOpInfo[]
124
 */
125
 
126
#include "acpi.h"
127
#include "accommon.h"
128
#include "acparser.h"
129
#include "acdispat.h"
130
#include "amlcode.h"
131
#include "acinterp.h"
132
 
133
#define _COMPONENT          ACPI_PARSER
134
        ACPI_MODULE_NAME    ("psparse")
135
 
136
 
137
/*******************************************************************************
138
 *
139
 * FUNCTION:    AcpiPsGetOpcodeSize
140
 *
141
 * PARAMETERS:  Opcode          - An AML opcode
142
 *
143
 * RETURN:      Size of the opcode, in bytes (1 or 2)
144
 *
145
 * DESCRIPTION: Get the size of the current opcode.
146
 *
147
 ******************************************************************************/
148
 
149
UINT32
150
AcpiPsGetOpcodeSize (
151
    UINT32                  Opcode)
152
{
153
 
154
    /* Extended (2-byte) opcode if > 255 */
155
 
156
    if (Opcode > 0x00FF)
157
    {
158
        return (2);
159
    }
160
 
161
    /* Otherwise, just a single byte opcode */
162
 
163
    return (1);
164
}
165
 
166
 
167
/*******************************************************************************
168
 *
169
 * FUNCTION:    AcpiPsPeekOpcode
170
 *
171
 * PARAMETERS:  ParserState         - A parser state object
172
 *
173
 * RETURN:      Next AML opcode
174
 *
175
 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer)
176
 *
177
 ******************************************************************************/
178
 
179
UINT16
180
AcpiPsPeekOpcode (
181
    ACPI_PARSE_STATE        *ParserState)
182
{
183
    UINT8                   *Aml;
184
    UINT16                  Opcode;
185
 
186
 
187
    Aml = ParserState->Aml;
188
    Opcode = (UINT16) ACPI_GET8 (Aml);
189
 
190
    if (Opcode == AML_EXTENDED_OP_PREFIX)
191
    {
192
        /* Extended opcode, get the second opcode byte */
193
 
194
        Aml++;
195
        Opcode = (UINT16) ((Opcode << 8) | ACPI_GET8 (Aml));
196
    }
197
 
198
    return (Opcode);
199
}
200
 
201
 
202
/*******************************************************************************
203
 *
204
 * FUNCTION:    AcpiPsCompleteThisOp
205
 *
206
 * PARAMETERS:  WalkState       - Current State
207
 *              Op              - Op to complete
208
 *
209
 * RETURN:      Status
210
 *
211
 * DESCRIPTION: Perform any cleanup at the completion of an Op.
212
 *
213
 ******************************************************************************/
214
 
215
ACPI_STATUS
216
AcpiPsCompleteThisOp (
217
    ACPI_WALK_STATE         *WalkState,
218
    ACPI_PARSE_OBJECT       *Op)
219
{
220
    ACPI_PARSE_OBJECT       *Prev;
221
    ACPI_PARSE_OBJECT       *Next;
222
    const ACPI_OPCODE_INFO  *ParentInfo;
223
    ACPI_PARSE_OBJECT       *ReplacementOp = NULL;
224
    ACPI_STATUS             Status = AE_OK;
225
 
226
 
227
    ACPI_FUNCTION_TRACE_PTR (PsCompleteThisOp, Op);
228
 
229
 
230
    /* Check for null Op, can happen if AML code is corrupt */
231
 
232
    if (!Op)
233
    {
234
        return_ACPI_STATUS (AE_OK);  /* OK for now */
235
    }
236
 
237
    /* Delete this op and the subtree below it if asked to */
238
 
239
    if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
240
         (WalkState->OpInfo->Class == AML_CLASS_ARGUMENT))
241
    {
242
        return_ACPI_STATUS (AE_OK);
243
    }
244
 
245
    /* Make sure that we only delete this subtree */
246
 
247
    if (Op->Common.Parent)
248
    {
249
        Prev = Op->Common.Parent->Common.Value.Arg;
250
        if (!Prev)
251
        {
252
            /* Nothing more to do */
253
 
254
            goto Cleanup;
255
        }
256
 
257
        /*
258
         * Check if we need to replace the operator and its subtree
259
         * with a return value op (placeholder op)
260
         */
261
        ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
262
 
263
        switch (ParentInfo->Class)
264
        {
265
        case AML_CLASS_CONTROL:
266
            break;
267
 
268
        case AML_CLASS_CREATE:
269
 
270
            /*
271
             * These opcodes contain TermArg operands.  The current
272
             * op must be replaced by a placeholder return op
273
             */
274
            ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
275
            if (!ReplacementOp)
276
            {
277
                Status = AE_NO_MEMORY;
278
            }
279
            break;
280
 
281
        case AML_CLASS_NAMED_OBJECT:
282
 
283
            /*
284
             * These opcodes contain TermArg operands.  The current
285
             * op must be replaced by a placeholder return op
286
             */
287
            if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
288
                (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
289
                (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
290
                (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
291
                (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP)   ||
292
                (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
293
            {
294
                ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
295
                if (!ReplacementOp)
296
                {
297
                    Status = AE_NO_MEMORY;
298
                }
299
            }
300
            else if ((Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
301
                     (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))
302
            {
303
                if ((Op->Common.AmlOpcode == AML_BUFFER_OP) ||
304
                    (Op->Common.AmlOpcode == AML_PACKAGE_OP) ||
305
                    (Op->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
306
                {
307
                    ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode);
308
                    if (!ReplacementOp)
309
                    {
310
                        Status = AE_NO_MEMORY;
311
                    }
312
                    else
313
                    {
314
                        ReplacementOp->Named.Data = Op->Named.Data;
315
                        ReplacementOp->Named.Length = Op->Named.Length;
316
                    }
317
                }
318
            }
319
            break;
320
 
321
        default:
322
 
323
            ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
324
            if (!ReplacementOp)
325
            {
326
                Status = AE_NO_MEMORY;
327
            }
328
        }
329
 
330
        /* We must unlink this op from the parent tree */
331
 
332
        if (Prev == Op)
333
        {
334
            /* This op is the first in the list */
335
 
336
            if (ReplacementOp)
337
            {
338
                ReplacementOp->Common.Parent        = Op->Common.Parent;
339
                ReplacementOp->Common.Value.Arg     = NULL;
340
                ReplacementOp->Common.Node          = Op->Common.Node;
341
                Op->Common.Parent->Common.Value.Arg = ReplacementOp;
342
                ReplacementOp->Common.Next          = Op->Common.Next;
343
            }
344
            else
345
            {
346
                Op->Common.Parent->Common.Value.Arg = Op->Common.Next;
347
            }
348
        }
349
 
350
        /* Search the parent list */
351
 
352
        else while (Prev)
353
        {
354
            /* Traverse all siblings in the parent's argument list */
355
 
356
            Next = Prev->Common.Next;
357
            if (Next == Op)
358
            {
359
                if (ReplacementOp)
360
                {
361
                    ReplacementOp->Common.Parent    = Op->Common.Parent;
362
                    ReplacementOp->Common.Value.Arg = NULL;
363
                    ReplacementOp->Common.Node      = Op->Common.Node;
364
                    Prev->Common.Next               = ReplacementOp;
365
                    ReplacementOp->Common.Next      = Op->Common.Next;
366
                    Next = NULL;
367
                }
368
                else
369
                {
370
                    Prev->Common.Next = Op->Common.Next;
371
                    Next = NULL;
372
                }
373
            }
374
            Prev = Next;
375
        }
376
    }
377
 
378
 
379
Cleanup:
380
 
381
    /* Now we can actually delete the subtree rooted at Op */
382
 
383
    AcpiPsDeleteParseTree (Op);
384
    return_ACPI_STATUS (Status);
385
}
386
 
387
 
388
/*******************************************************************************
389
 *
390
 * FUNCTION:    AcpiPsNextParseState
391
 *
392
 * PARAMETERS:  WalkState           - Current state
393
 *              Op                  - Current parse op
394
 *              CallbackStatus      - Status from previous operation
395
 *
396
 * RETURN:      Status
397
 *
398
 * DESCRIPTION: Update the parser state based upon the return exception from
399
 *              the parser callback.
400
 *
401
 ******************************************************************************/
402
 
403
ACPI_STATUS
404
AcpiPsNextParseState (
405
    ACPI_WALK_STATE         *WalkState,
406
    ACPI_PARSE_OBJECT       *Op,
407
    ACPI_STATUS             CallbackStatus)
408
{
409
    ACPI_PARSE_STATE        *ParserState = &WalkState->ParserState;
410
    ACPI_STATUS             Status = AE_CTRL_PENDING;
411
 
412
 
413
    ACPI_FUNCTION_TRACE_PTR (PsNextParseState, Op);
414
 
415
 
416
    switch (CallbackStatus)
417
    {
418
    case AE_CTRL_TERMINATE:
419
        /*
420
         * A control method was terminated via a RETURN statement.
421
         * The walk of this method is complete.
422
         */
423
        ParserState->Aml = ParserState->AmlEnd;
424
        Status = AE_CTRL_TERMINATE;
425
        break;
426
 
427
 
428
    case AE_CTRL_BREAK:
429
 
430
        ParserState->Aml = WalkState->AmlLastWhile;
431
        WalkState->ControlState->Common.Value = FALSE;
432
        Status = AE_CTRL_BREAK;
433
        break;
434
 
435
 
436
    case AE_CTRL_CONTINUE:
437
 
438
        ParserState->Aml = WalkState->AmlLastWhile;
439
        Status = AE_CTRL_CONTINUE;
440
        break;
441
 
442
 
443
    case AE_CTRL_PENDING:
444
 
445
        ParserState->Aml = WalkState->AmlLastWhile;
446
        break;
447
 
448
#if 0
449
    case AE_CTRL_SKIP:
450
 
451
        ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd;
452
        Status = AE_OK;
453
        break;
454
#endif
455
 
456
    case AE_CTRL_TRUE:
457
        /*
458
         * Predicate of an IF was true, and we are at the matching ELSE.
459
         * Just close out this package
460
         */
461
        ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState);
462
        Status = AE_CTRL_PENDING;
463
        break;
464
 
465
 
466
    case AE_CTRL_FALSE:
467
        /*
468
         * Either an IF/WHILE Predicate was false or we encountered a BREAK
469
         * opcode.  In both cases, we do not execute the rest of the
470
         * package;  We simply close out the parent (finishing the walk of
471
         * this branch of the tree) and continue execution at the parent
472
         * level.
473
         */
474
        ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd;
475
 
476
        /* In the case of a BREAK, just force a predicate (if any) to FALSE */
477
 
478
        WalkState->ControlState->Common.Value = FALSE;
479
        Status = AE_CTRL_END;
480
        break;
481
 
482
 
483
    case AE_CTRL_TRANSFER:
484
 
485
        /* A method call (invocation) -- transfer control */
486
 
487
        Status = AE_CTRL_TRANSFER;
488
        WalkState->PrevOp = Op;
489
        WalkState->MethodCallOp = Op;
490
        WalkState->MethodCallNode = (Op->Common.Value.Arg)->Common.Node;
491
 
492
        /* Will return value (if any) be used by the caller? */
493
 
494
        WalkState->ReturnUsed = AcpiDsIsResultUsed (Op, WalkState);
495
        break;
496
 
497
 
498
    default:
499
 
500
        Status = CallbackStatus;
501
        if ((CallbackStatus & AE_CODE_MASK) == AE_CODE_CONTROL)
502
        {
503
            Status = AE_OK;
504
        }
505
        break;
506
    }
507
 
508
    return_ACPI_STATUS (Status);
509
}
510
 
511
 
512
/*******************************************************************************
513
 *
514
 * FUNCTION:    AcpiPsParseAml
515
 *
516
 * PARAMETERS:  WalkState       - Current state
517
 *
518
 *
519
 * RETURN:      Status
520
 *
521
 * DESCRIPTION: Parse raw AML and return a tree of ops
522
 *
523
 ******************************************************************************/
524
 
525
ACPI_STATUS
526
AcpiPsParseAml (
527
    ACPI_WALK_STATE         *WalkState)
528
{
529
    ACPI_STATUS             Status;
530
    ACPI_THREAD_STATE       *Thread;
531
    ACPI_THREAD_STATE       *PrevWalkList = AcpiGbl_CurrentWalkList;
532
    ACPI_WALK_STATE         *PreviousWalkState;
533
 
534
 
535
    ACPI_FUNCTION_TRACE (PsParseAml);
536
 
537
    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
538
        "Entered with WalkState=%p Aml=%p size=%X\n",
539
        WalkState, WalkState->ParserState.Aml,
540
        WalkState->ParserState.AmlSize));
541
 
542
    if (!WalkState->ParserState.Aml)
543
    {
544
        return_ACPI_STATUS (AE_NULL_OBJECT);
545
    }
546
 
547
    /* Create and initialize a new thread state */
548
 
549
    Thread = AcpiUtCreateThreadState ();
550
    if (!Thread)
551
    {
552
        if (WalkState->MethodDesc)
553
        {
554
            /* Executing a control method - additional cleanup */
555
 
556
            AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState);
557
        }
558
 
559
        AcpiDsDeleteWalkState (WalkState);
560
        return_ACPI_STATUS (AE_NO_MEMORY);
561
    }
562
 
563
    WalkState->Thread = Thread;
564
 
565
    /*
566
     * If executing a method, the starting SyncLevel is this method's
567
     * SyncLevel
568
     */
569
    if (WalkState->MethodDesc)
570
    {
571
        WalkState->Thread->CurrentSyncLevel = WalkState->MethodDesc->Method.SyncLevel;
572
    }
573
 
574
    AcpiDsPushWalkState (WalkState, Thread);
575
 
576
    /*
577
     * This global allows the AML debugger to get a handle to the currently
578
     * executing control method.
579
     */
580
    AcpiGbl_CurrentWalkList = Thread;
581
 
582
    /*
583
     * Execute the walk loop as long as there is a valid Walk State.  This
584
     * handles nested control method invocations without recursion.
585
     */
586
    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState));
587
 
588
    Status = AE_OK;
589
    while (WalkState)
590
    {
591
        if (ACPI_SUCCESS (Status))
592
        {
593
            /*
594
             * The ParseLoop executes AML until the method terminates
595
             * or calls another method.
596
             */
597
            Status = AcpiPsParseLoop (WalkState);
598
        }
599
 
600
        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
601
            "Completed one call to walk loop, %s State=%p\n",
602
            AcpiFormatException (Status), WalkState));
603
 
604
        if (Status == AE_CTRL_TRANSFER)
605
        {
606
            /*
607
             * A method call was detected.
608
             * Transfer control to the called control method
609
             */
610
            Status = AcpiDsCallControlMethod (Thread, WalkState, NULL);
611
            if (ACPI_FAILURE (Status))
612
            {
613
                Status = AcpiDsMethodError (Status, WalkState);
614
            }
615
 
616
            /*
617
             * If the transfer to the new method method call worked, a new walk
618
             * state was created -- get it
619
             */
620
            WalkState = AcpiDsGetCurrentWalkState (Thread);
621
            continue;
622
        }
623
        else if (Status == AE_CTRL_TERMINATE)
624
        {
625
            Status = AE_OK;
626
        }
627
        else if ((Status != AE_OK) && (WalkState->MethodDesc))
628
        {
629
            /* Either the method parse or actual execution failed */
630
 
631
            ACPI_ERROR_METHOD ("Method parse/execution failed",
632
                WalkState->MethodNode, NULL, Status);
633
 
634
            /* Check for possible multi-thread reentrancy problem */
635
 
636
            if ((Status == AE_ALREADY_EXISTS) &&
2216 Serge 637
                (!(WalkState->MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)))
1498 serge 638
            {
639
                /*
2216 Serge 640
                 * Method is not serialized and tried to create an object
641
                 * twice. The probable cause is that the method cannot
642
                 * handle reentrancy. Mark as "pending serialized" now, and
643
                 * then mark "serialized" when the last thread exits.
1498 serge 644
                 */
2216 Serge 645
                WalkState->MethodDesc->Method.InfoFlags |=
646
                    ACPI_METHOD_SERIALIZED_PENDING;
1498 serge 647
            }
648
        }
649
 
650
        /* We are done with this walk, move on to the parent if any */
651
 
652
        WalkState = AcpiDsPopWalkState (Thread);
653
 
654
        /* Reset the current scope to the beginning of scope stack */
655
 
656
        AcpiDsScopeStackClear (WalkState);
657
 
658
        /*
659
         * If we just returned from the execution of a control method or if we
660
         * encountered an error during the method parse phase, there's lots of
661
         * cleanup to do
662
         */
663
        if (((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) ||
664
            (ACPI_FAILURE (Status)))
665
        {
666
            AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState);
667
        }
668
 
669
        /* Delete this walk state and all linked control states */
670
 
671
        AcpiPsCleanupScope (&WalkState->ParserState);
672
        PreviousWalkState = WalkState;
673
 
674
        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
675
            "ReturnValue=%p, ImplicitValue=%p State=%p\n",
676
            WalkState->ReturnDesc, WalkState->ImplicitReturnObj, WalkState));
677
 
678
        /* Check if we have restarted a preempted walk */
679
 
680
        WalkState = AcpiDsGetCurrentWalkState (Thread);
681
        if (WalkState)
682
        {
683
            if (ACPI_SUCCESS (Status))
684
            {
685
                /*
686
                 * There is another walk state, restart it.
687
                 * If the method return value is not used by the parent,
688
                 * The object is deleted
689
                 */
690
                if (!PreviousWalkState->ReturnDesc)
691
                {
692
                    /*
693
                     * In slack mode execution, if there is no return value
694
                     * we should implicitly return zero (0) as a default value.
695
                     */
696
                    if (AcpiGbl_EnableInterpreterSlack &&
697
                        !PreviousWalkState->ImplicitReturnObj)
698
                    {
699
                        PreviousWalkState->ImplicitReturnObj =
700
                            AcpiUtCreateIntegerObject ((UINT64) 0);
701
                        if (!PreviousWalkState->ImplicitReturnObj)
702
                        {
703
                            return_ACPI_STATUS (AE_NO_MEMORY);
704
                        }
705
                    }
706
 
707
                    /* Restart the calling control method */
708
 
709
                    Status = AcpiDsRestartControlMethod (WalkState,
710
                                PreviousWalkState->ImplicitReturnObj);
711
                }
712
                else
713
                {
714
                    /*
715
                     * We have a valid return value, delete any implicit
716
                     * return value.
717
                     */
718
                    AcpiDsClearImplicitReturn (PreviousWalkState);
719
 
720
                    Status = AcpiDsRestartControlMethod (WalkState,
721
                                PreviousWalkState->ReturnDesc);
722
                }
723
                if (ACPI_SUCCESS (Status))
724
                {
725
                    WalkState->WalkType |= ACPI_WALK_METHOD_RESTART;
726
                }
727
            }
728
            else
729
            {
730
                /* On error, delete any return object or implicit return */
731
 
732
                AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);
733
                AcpiDsClearImplicitReturn (PreviousWalkState);
734
            }
735
        }
736
 
737
        /*
738
         * Just completed a 1st-level method, save the final internal return
739
         * value (if any)
740
         */
741
        else if (PreviousWalkState->CallerReturnDesc)
742
        {
743
            if (PreviousWalkState->ImplicitReturnObj)
744
            {
745
                *(PreviousWalkState->CallerReturnDesc) =
746
                    PreviousWalkState->ImplicitReturnObj;
747
            }
748
            else
749
            {
750
                 /* NULL if no return value */
751
 
752
                *(PreviousWalkState->CallerReturnDesc) =
753
                    PreviousWalkState->ReturnDesc;
754
            }
755
        }
756
        else
757
        {
758
            if (PreviousWalkState->ReturnDesc)
759
            {
760
                /* Caller doesn't want it, must delete it */
761
 
762
                AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);
763
            }
764
            if (PreviousWalkState->ImplicitReturnObj)
765
            {
766
                /* Caller doesn't want it, must delete it */
767
 
768
                AcpiUtRemoveReference (PreviousWalkState->ImplicitReturnObj);
769
            }
770
        }
771
 
772
        AcpiDsDeleteWalkState (PreviousWalkState);
773
    }
774
 
775
    /* Normal exit */
776
 
777
    AcpiExReleaseAllMutexes (Thread);
778
    AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread));
779
    AcpiGbl_CurrentWalkList = PrevWalkList;
780
    return_ACPI_STATUS (Status);
781
}
782