Subversion Repositories Kolibri OS

Rev

Rev 1498 | 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 - 2011, 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 "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) &&
  637.                 (!(WalkState->MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)))
  638.             {
  639.                 /*
  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.
  644.                  */
  645.                 WalkState->MethodDesc->Method.InfoFlags |=
  646.                     ACPI_METHOD_SERIALIZED_PENDING;
  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.  
  783.  
  784.