Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: psparse - Parser top level AML parse routines
  4.  *
  5.  *****************************************************************************/
  6.  
  7. /******************************************************************************
  8.  *
  9.  * 1. Copyright Notice
  10.  *
  11.  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
  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 "acnamesp.h"
  132. #include "acinterp.h"
  133.  
  134. #define _COMPONENT          ACPI_PARSER
  135.         ACPI_MODULE_NAME    ("psparse")
  136.  
  137.  
  138. /*******************************************************************************
  139.  *
  140.  * FUNCTION:    AcpiPsGetOpcodeSize
  141.  *
  142.  * PARAMETERS:  Opcode          - An AML opcode
  143.  *
  144.  * RETURN:      Size of the opcode, in bytes (1 or 2)
  145.  *
  146.  * DESCRIPTION: Get the size of the current opcode.
  147.  *
  148.  ******************************************************************************/
  149.  
  150. UINT32
  151. AcpiPsGetOpcodeSize (
  152.     UINT32                  Opcode)
  153. {
  154.  
  155.     /* Extended (2-byte) opcode if > 255 */
  156.  
  157.     if (Opcode > 0x00FF)
  158.     {
  159.         return (2);
  160.     }
  161.  
  162.     /* Otherwise, just a single byte opcode */
  163.  
  164.     return (1);
  165. }
  166.  
  167.  
  168. /*******************************************************************************
  169.  *
  170.  * FUNCTION:    AcpiPsPeekOpcode
  171.  *
  172.  * PARAMETERS:  ParserState         - A parser state object
  173.  *
  174.  * RETURN:      Next AML opcode
  175.  *
  176.  * DESCRIPTION: Get next AML opcode (without incrementing AML pointer)
  177.  *
  178.  ******************************************************************************/
  179.  
  180. UINT16
  181. AcpiPsPeekOpcode (
  182.     ACPI_PARSE_STATE        *ParserState)
  183. {
  184.     UINT8                   *Aml;
  185.     UINT16                  Opcode;
  186.  
  187.  
  188.     Aml = ParserState->Aml;
  189.     Opcode = (UINT16) ACPI_GET8 (Aml);
  190.  
  191.     if (Opcode == AML_EXTENDED_OP_PREFIX)
  192.     {
  193.         /* Extended opcode, get the second opcode byte */
  194.  
  195.         Aml++;
  196.         Opcode = (UINT16) ((Opcode << 8) | ACPI_GET8 (Aml));
  197.     }
  198.  
  199.     return (Opcode);
  200. }
  201.  
  202.  
  203. /*******************************************************************************
  204.  *
  205.  * FUNCTION:    AcpiPsCompleteThisOp
  206.  *
  207.  * PARAMETERS:  WalkState       - Current State
  208.  *              Op              - Op to complete
  209.  *
  210.  * RETURN:      Status
  211.  *
  212.  * DESCRIPTION: Perform any cleanup at the completion of an Op.
  213.  *
  214.  ******************************************************************************/
  215.  
  216. ACPI_STATUS
  217. AcpiPsCompleteThisOp (
  218.     ACPI_WALK_STATE         *WalkState,
  219.     ACPI_PARSE_OBJECT       *Op)
  220. {
  221.     ACPI_PARSE_OBJECT       *Prev;
  222.     ACPI_PARSE_OBJECT       *Next;
  223.     const ACPI_OPCODE_INFO  *ParentInfo;
  224.     ACPI_PARSE_OBJECT       *ReplacementOp = NULL;
  225.     ACPI_STATUS             Status = AE_OK;
  226.  
  227.  
  228.     ACPI_FUNCTION_TRACE_PTR (PsCompleteThisOp, Op);
  229.  
  230.  
  231.     /* Check for null Op, can happen if AML code is corrupt */
  232.  
  233.     if (!Op)
  234.     {
  235.         return_ACPI_STATUS (AE_OK);  /* OK for now */
  236.     }
  237.  
  238.     /* Delete this op and the subtree below it if asked to */
  239.  
  240.     if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
  241.          (WalkState->OpInfo->Class == AML_CLASS_ARGUMENT))
  242.     {
  243.         return_ACPI_STATUS (AE_OK);
  244.     }
  245.  
  246.     /* Make sure that we only delete this subtree */
  247.  
  248.     if (Op->Common.Parent)
  249.     {
  250.         Prev = Op->Common.Parent->Common.Value.Arg;
  251.         if (!Prev)
  252.         {
  253.             /* Nothing more to do */
  254.  
  255.             goto Cleanup;
  256.         }
  257.  
  258.         /*
  259.          * Check if we need to replace the operator and its subtree
  260.          * with a return value op (placeholder op)
  261.          */
  262.         ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
  263.  
  264.         switch (ParentInfo->Class)
  265.         {
  266.         case AML_CLASS_CONTROL:
  267.             break;
  268.  
  269.         case AML_CLASS_CREATE:
  270.  
  271.             /*
  272.              * These opcodes contain TermArg operands.  The current
  273.              * op must be replaced by a placeholder return op
  274.              */
  275.             ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
  276.             if (!ReplacementOp)
  277.             {
  278.                 Status = AE_NO_MEMORY;
  279.             }
  280.             break;
  281.  
  282.         case AML_CLASS_NAMED_OBJECT:
  283.  
  284.             /*
  285.              * These opcodes contain TermArg operands.  The current
  286.              * op must be replaced by a placeholder return op
  287.              */
  288.             if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
  289.                 (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
  290.                 (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
  291.                 (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
  292.                 (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP)   ||
  293.                 (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
  294.             {
  295.                 ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
  296.                 if (!ReplacementOp)
  297.                 {
  298.                     Status = AE_NO_MEMORY;
  299.                 }
  300.             }
  301.             else if ((Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
  302.                      (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))
  303.             {
  304.                 if ((Op->Common.AmlOpcode == AML_BUFFER_OP) ||
  305.                     (Op->Common.AmlOpcode == AML_PACKAGE_OP) ||
  306.                     (Op->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
  307.                 {
  308.                     ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode);
  309.                     if (!ReplacementOp)
  310.                     {
  311.                         Status = AE_NO_MEMORY;
  312.                     }
  313.                     else
  314.                     {
  315.                         ReplacementOp->Named.Data = Op->Named.Data;
  316.                         ReplacementOp->Named.Length = Op->Named.Length;
  317.                     }
  318.                 }
  319.             }
  320.             break;
  321.  
  322.         default:
  323.  
  324.             ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP);
  325.             if (!ReplacementOp)
  326.             {
  327.                 Status = AE_NO_MEMORY;
  328.             }
  329.         }
  330.  
  331.         /* We must unlink this op from the parent tree */
  332.  
  333.         if (Prev == Op)
  334.         {
  335.             /* This op is the first in the list */
  336.  
  337.             if (ReplacementOp)
  338.             {
  339.                 ReplacementOp->Common.Parent        = Op->Common.Parent;
  340.                 ReplacementOp->Common.Value.Arg     = NULL;
  341.                 ReplacementOp->Common.Node          = Op->Common.Node;
  342.                 Op->Common.Parent->Common.Value.Arg = ReplacementOp;
  343.                 ReplacementOp->Common.Next          = Op->Common.Next;
  344.             }
  345.             else
  346.             {
  347.                 Op->Common.Parent->Common.Value.Arg = Op->Common.Next;
  348.             }
  349.         }
  350.  
  351.         /* Search the parent list */
  352.  
  353.         else while (Prev)
  354.         {
  355.             /* Traverse all siblings in the parent's argument list */
  356.  
  357.             Next = Prev->Common.Next;
  358.             if (Next == Op)
  359.             {
  360.                 if (ReplacementOp)
  361.                 {
  362.                     ReplacementOp->Common.Parent    = Op->Common.Parent;
  363.                     ReplacementOp->Common.Value.Arg = NULL;
  364.                     ReplacementOp->Common.Node      = Op->Common.Node;
  365.                     Prev->Common.Next               = ReplacementOp;
  366.                     ReplacementOp->Common.Next      = Op->Common.Next;
  367.                     Next = NULL;
  368.                 }
  369.                 else
  370.                 {
  371.                     Prev->Common.Next = Op->Common.Next;
  372.                     Next = NULL;
  373.                 }
  374.             }
  375.             Prev = Next;
  376.         }
  377.     }
  378.  
  379.  
  380. Cleanup:
  381.  
  382.     /* Now we can actually delete the subtree rooted at Op */
  383.  
  384.     AcpiPsDeleteParseTree (Op);
  385.     return_ACPI_STATUS (Status);
  386. }
  387.  
  388.  
  389. /*******************************************************************************
  390.  *
  391.  * FUNCTION:    AcpiPsNextParseState
  392.  *
  393.  * PARAMETERS:  WalkState           - Current state
  394.  *              Op                  - Current parse op
  395.  *              CallbackStatus      - Status from previous operation
  396.  *
  397.  * RETURN:      Status
  398.  *
  399.  * DESCRIPTION: Update the parser state based upon the return exception from
  400.  *              the parser callback.
  401.  *
  402.  ******************************************************************************/
  403.  
  404. ACPI_STATUS
  405. AcpiPsNextParseState (
  406.     ACPI_WALK_STATE         *WalkState,
  407.     ACPI_PARSE_OBJECT       *Op,
  408.     ACPI_STATUS             CallbackStatus)
  409. {
  410.     ACPI_PARSE_STATE        *ParserState = &WalkState->ParserState;
  411.     ACPI_STATUS             Status = AE_CTRL_PENDING;
  412.  
  413.  
  414.     ACPI_FUNCTION_TRACE_PTR (PsNextParseState, Op);
  415.  
  416.  
  417.     switch (CallbackStatus)
  418.     {
  419.     case AE_CTRL_TERMINATE:
  420.         /*
  421.          * A control method was terminated via a RETURN statement.
  422.          * The walk of this method is complete.
  423.          */
  424.         ParserState->Aml = ParserState->AmlEnd;
  425.         Status = AE_CTRL_TERMINATE;
  426.         break;
  427.  
  428.  
  429.     case AE_CTRL_BREAK:
  430.  
  431.         ParserState->Aml = WalkState->AmlLastWhile;
  432.         WalkState->ControlState->Common.Value = FALSE;
  433.         Status = AE_CTRL_BREAK;
  434.         break;
  435.  
  436.  
  437.     case AE_CTRL_CONTINUE:
  438.  
  439.         ParserState->Aml = WalkState->AmlLastWhile;
  440.         Status = AE_CTRL_CONTINUE;
  441.         break;
  442.  
  443.  
  444.     case AE_CTRL_PENDING:
  445.  
  446.         ParserState->Aml = WalkState->AmlLastWhile;
  447.         break;
  448.  
  449. #if 0
  450.     case AE_CTRL_SKIP:
  451.  
  452.         ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd;
  453.         Status = AE_OK;
  454.         break;
  455. #endif
  456.  
  457.     case AE_CTRL_TRUE:
  458.         /*
  459.          * Predicate of an IF was true, and we are at the matching ELSE.
  460.          * Just close out this package
  461.          */
  462.         ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState);
  463.         Status = AE_CTRL_PENDING;
  464.         break;
  465.  
  466.  
  467.     case AE_CTRL_FALSE:
  468.         /*
  469.          * Either an IF/WHILE Predicate was false or we encountered a BREAK
  470.          * opcode.  In both cases, we do not execute the rest of the
  471.          * package;  We simply close out the parent (finishing the walk of
  472.          * this branch of the tree) and continue execution at the parent
  473.          * level.
  474.          */
  475.         ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd;
  476.  
  477.         /* In the case of a BREAK, just force a predicate (if any) to FALSE */
  478.  
  479.         WalkState->ControlState->Common.Value = FALSE;
  480.         Status = AE_CTRL_END;
  481.         break;
  482.  
  483.  
  484.     case AE_CTRL_TRANSFER:
  485.  
  486.         /* A method call (invocation) -- transfer control */
  487.  
  488.         Status = AE_CTRL_TRANSFER;
  489.         WalkState->PrevOp = Op;
  490.         WalkState->MethodCallOp = Op;
  491.         WalkState->MethodCallNode = (Op->Common.Value.Arg)->Common.Node;
  492.  
  493.         /* Will return value (if any) be used by the caller? */
  494.  
  495.         WalkState->ReturnUsed = AcpiDsIsResultUsed (Op, WalkState);
  496.         break;
  497.  
  498.  
  499.     default:
  500.  
  501.         Status = CallbackStatus;
  502.         if ((CallbackStatus & AE_CODE_MASK) == AE_CODE_CONTROL)
  503.         {
  504.             Status = AE_OK;
  505.         }
  506.         break;
  507.     }
  508.  
  509.     return_ACPI_STATUS (Status);
  510. }
  511.  
  512.  
  513. /*******************************************************************************
  514.  *
  515.  * FUNCTION:    AcpiPsParseAml
  516.  *
  517.  * PARAMETERS:  WalkState       - Current state
  518.  *
  519.  *
  520.  * RETURN:      Status
  521.  *
  522.  * DESCRIPTION: Parse raw AML and return a tree of ops
  523.  *
  524.  ******************************************************************************/
  525.  
  526. ACPI_STATUS
  527. AcpiPsParseAml (
  528.     ACPI_WALK_STATE         *WalkState)
  529. {
  530.     ACPI_STATUS             Status;
  531.     ACPI_THREAD_STATE       *Thread;
  532.     ACPI_THREAD_STATE       *PrevWalkList = AcpiGbl_CurrentWalkList;
  533.     ACPI_WALK_STATE         *PreviousWalkState;
  534.  
  535.  
  536.     ACPI_FUNCTION_TRACE (PsParseAml);
  537.  
  538.     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
  539.         "Entered with WalkState=%p Aml=%p size=%X\n",
  540.         WalkState, WalkState->ParserState.Aml,
  541.         WalkState->ParserState.AmlSize));
  542.  
  543.     if (!WalkState->ParserState.Aml)
  544.     {
  545.         return_ACPI_STATUS (AE_NULL_OBJECT);
  546.     }
  547.  
  548.     /* Create and initialize a new thread state */
  549.  
  550.     Thread = AcpiUtCreateThreadState ();
  551.     if (!Thread)
  552.     {
  553.         if (WalkState->MethodDesc)
  554.         {
  555.             /* Executing a control method - additional cleanup */
  556.  
  557.             AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState);
  558.         }
  559.  
  560.         AcpiDsDeleteWalkState (WalkState);
  561.         return_ACPI_STATUS (AE_NO_MEMORY);
  562.     }
  563.  
  564.     WalkState->Thread = Thread;
  565.  
  566.     /*
  567.      * If executing a method, the starting SyncLevel is this method's
  568.      * SyncLevel
  569.      */
  570.     if (WalkState->MethodDesc)
  571.     {
  572.         WalkState->Thread->CurrentSyncLevel = WalkState->MethodDesc->Method.SyncLevel;
  573.     }
  574.  
  575.     AcpiDsPushWalkState (WalkState, Thread);
  576.  
  577.     /*
  578.      * This global allows the AML debugger to get a handle to the currently
  579.      * executing control method.
  580.      */
  581.     AcpiGbl_CurrentWalkList = Thread;
  582.  
  583.     /*
  584.      * Execute the walk loop as long as there is a valid Walk State.  This
  585.      * handles nested control method invocations without recursion.
  586.      */
  587.     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState));
  588.  
  589.     Status = AE_OK;
  590.     while (WalkState)
  591.     {
  592.         if (ACPI_SUCCESS (Status))
  593.         {
  594.             /*
  595.              * The ParseLoop executes AML until the method terminates
  596.              * or calls another method.
  597.              */
  598.             Status = AcpiPsParseLoop (WalkState);
  599.         }
  600.  
  601.         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
  602.             "Completed one call to walk loop, %s State=%p\n",
  603.             AcpiFormatException (Status), WalkState));
  604.  
  605.         if (Status == AE_CTRL_TRANSFER)
  606.         {
  607.             /*
  608.              * A method call was detected.
  609.              * Transfer control to the called control method
  610.              */
  611.             Status = AcpiDsCallControlMethod (Thread, WalkState, NULL);
  612.             if (ACPI_FAILURE (Status))
  613.             {
  614.                 Status = AcpiDsMethodError (Status, WalkState);
  615.             }
  616.  
  617.             /*
  618.              * If the transfer to the new method method call worked, a new walk
  619.              * state was created -- get it
  620.              */
  621.             WalkState = AcpiDsGetCurrentWalkState (Thread);
  622.             continue;
  623.         }
  624.         else if (Status == AE_CTRL_TERMINATE)
  625.         {
  626.             Status = AE_OK;
  627.         }
  628.         else if ((Status != AE_OK) && (WalkState->MethodDesc))
  629.         {
  630.             /* Either the method parse or actual execution failed */
  631.  
  632.             ACPI_ERROR_METHOD ("Method parse/execution failed",
  633.                 WalkState->MethodNode, NULL, Status);
  634.  
  635.             /* Check for possible multi-thread reentrancy problem */
  636.  
  637.             if ((Status == AE_ALREADY_EXISTS) &&
  638.                 (!WalkState->MethodDesc->Method.Mutex))
  639.             {
  640.                 ACPI_INFO ((AE_INFO,
  641.                     "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
  642.                     WalkState->MethodNode->Name.Ascii));
  643.  
  644.                 /*
  645.                  * Method tried to create an object twice. The probable cause is
  646.                  * that the method cannot handle reentrancy.
  647.                  *
  648.                  * The method is marked NotSerialized, but it tried to create
  649.                  * a named object, causing the second thread entrance to fail.
  650.                  * Workaround this problem by marking the method permanently
  651.                  * as Serialized.
  652.                  */
  653.                 WalkState->MethodDesc->Method.MethodFlags |= AML_METHOD_SERIALIZED;
  654.                 WalkState->MethodDesc->Method.SyncLevel = 0;
  655.             }
  656.         }
  657.  
  658.         /* We are done with this walk, move on to the parent if any */
  659.  
  660.         WalkState = AcpiDsPopWalkState (Thread);
  661.  
  662.         /* Reset the current scope to the beginning of scope stack */
  663.  
  664.         AcpiDsScopeStackClear (WalkState);
  665.  
  666.         /*
  667.          * If we just returned from the execution of a control method or if we
  668.          * encountered an error during the method parse phase, there's lots of
  669.          * cleanup to do
  670.          */
  671.         if (((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) ||
  672.             (ACPI_FAILURE (Status)))
  673.         {
  674.             AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState);
  675.         }
  676.  
  677.         /* Delete this walk state and all linked control states */
  678.  
  679.         AcpiPsCleanupScope (&WalkState->ParserState);
  680.         PreviousWalkState = WalkState;
  681.  
  682.         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
  683.             "ReturnValue=%p, ImplicitValue=%p State=%p\n",
  684.             WalkState->ReturnDesc, WalkState->ImplicitReturnObj, WalkState));
  685.  
  686.         /* Check if we have restarted a preempted walk */
  687.  
  688.         WalkState = AcpiDsGetCurrentWalkState (Thread);
  689.         if (WalkState)
  690.         {
  691.             if (ACPI_SUCCESS (Status))
  692.             {
  693.                 /*
  694.                  * There is another walk state, restart it.
  695.                  * If the method return value is not used by the parent,
  696.                  * The object is deleted
  697.                  */
  698.                 if (!PreviousWalkState->ReturnDesc)
  699.                 {
  700.                     /*
  701.                      * In slack mode execution, if there is no return value
  702.                      * we should implicitly return zero (0) as a default value.
  703.                      */
  704.                     if (AcpiGbl_EnableInterpreterSlack &&
  705.                         !PreviousWalkState->ImplicitReturnObj)
  706.                     {
  707.                         PreviousWalkState->ImplicitReturnObj =
  708.                             AcpiUtCreateIntegerObject ((UINT64) 0);
  709.                         if (!PreviousWalkState->ImplicitReturnObj)
  710.                         {
  711.                             return_ACPI_STATUS (AE_NO_MEMORY);
  712.                         }
  713.                     }
  714.  
  715.                     /* Restart the calling control method */
  716.  
  717.                     Status = AcpiDsRestartControlMethod (WalkState,
  718.                                 PreviousWalkState->ImplicitReturnObj);
  719.                 }
  720.                 else
  721.                 {
  722.                     /*
  723.                      * We have a valid return value, delete any implicit
  724.                      * return value.
  725.                      */
  726.                     AcpiDsClearImplicitReturn (PreviousWalkState);
  727.  
  728.                     Status = AcpiDsRestartControlMethod (WalkState,
  729.                                 PreviousWalkState->ReturnDesc);
  730.                 }
  731.                 if (ACPI_SUCCESS (Status))
  732.                 {
  733.                     WalkState->WalkType |= ACPI_WALK_METHOD_RESTART;
  734.                 }
  735.             }
  736.             else
  737.             {
  738.                 /* On error, delete any return object or implicit return */
  739.  
  740.                 AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);
  741.                 AcpiDsClearImplicitReturn (PreviousWalkState);
  742.             }
  743.         }
  744.  
  745.         /*
  746.          * Just completed a 1st-level method, save the final internal return
  747.          * value (if any)
  748.          */
  749.         else if (PreviousWalkState->CallerReturnDesc)
  750.         {
  751.             if (PreviousWalkState->ImplicitReturnObj)
  752.             {
  753.                 *(PreviousWalkState->CallerReturnDesc) =
  754.                     PreviousWalkState->ImplicitReturnObj;
  755.             }
  756.             else
  757.             {
  758.                  /* NULL if no return value */
  759.  
  760.                 *(PreviousWalkState->CallerReturnDesc) =
  761.                     PreviousWalkState->ReturnDesc;
  762.             }
  763.         }
  764.         else
  765.         {
  766.             if (PreviousWalkState->ReturnDesc)
  767.             {
  768.                 /* Caller doesn't want it, must delete it */
  769.  
  770.                 AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);
  771.             }
  772.             if (PreviousWalkState->ImplicitReturnObj)
  773.             {
  774.                 /* Caller doesn't want it, must delete it */
  775.  
  776.                 AcpiUtRemoveReference (PreviousWalkState->ImplicitReturnObj);
  777.             }
  778.         }
  779.  
  780.         AcpiDsDeleteWalkState (PreviousWalkState);
  781.     }
  782.  
  783.     /* Normal exit */
  784.  
  785.     AcpiExReleaseAllMutexes (Thread);
  786.     AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread));
  787.     AcpiGbl_CurrentWalkList = PrevWalkList;
  788.     return_ACPI_STATUS (Status);
  789. }
  790.  
  791.  
  792.