ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dsutils.c
Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Module Name: dsutils - Dispatcher utilities
00004  *
00005  ******************************************************************************/
00006 
00007 /******************************************************************************
00008  *
00009  * 1. Copyright Notice
00010  *
00011  * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
00012  * All rights reserved.
00013  *
00014  * 2. License
00015  *
00016  * 2.1. This is your license from Intel Corp. under its intellectual property
00017  * rights.  You may have additional license terms from the party that provided
00018  * you this software, covering your right to use that party's intellectual
00019  * property rights.
00020  *
00021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
00022  * copy of the source code appearing in this file ("Covered Code") an
00023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
00024  * base code distributed originally by Intel ("Original Intel Code") to copy,
00025  * make derivatives, distribute, use and display any portion of the Covered
00026  * Code in any form, with the right to sublicense such rights; and
00027  *
00028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
00029  * license (with the right to sublicense), under only those claims of Intel
00030  * patents that are infringed by the Original Intel Code, to make, use, sell,
00031  * offer to sell, and import the Covered Code and derivative works thereof
00032  * solely to the minimum extent necessary to exercise the above copyright
00033  * license, and in no event shall the patent license extend to any additions
00034  * to or modifications of the Original Intel Code.  No other license or right
00035  * is granted directly or by implication, estoppel or otherwise;
00036  *
00037  * The above copyright and patent license is granted only if the following
00038  * conditions are met:
00039  *
00040  * 3. Conditions
00041  *
00042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
00043  * Redistribution of source code of any substantial portion of the Covered
00044  * Code or modification with rights to further distribute source must include
00045  * the above Copyright Notice, the above License, this list of Conditions,
00046  * and the following Disclaimer and Export Compliance provision.  In addition,
00047  * Licensee must cause all Covered Code to which Licensee contributes to
00048  * contain a file documenting the changes Licensee made to create that Covered
00049  * Code and the date of any change.  Licensee must include in that file the
00050  * documentation of any changes made by any predecessor Licensee.  Licensee
00051  * must include a prominent statement that the modification is derived,
00052  * directly or indirectly, from Original Intel Code.
00053  *
00054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
00055  * Redistribution of source code of any substantial portion of the Covered
00056  * Code or modification without rights to further distribute source must
00057  * include the following Disclaimer and Export Compliance provision in the
00058  * documentation and/or other materials provided with distribution.  In
00059  * addition, Licensee may not authorize further sublicense of source of any
00060  * portion of the Covered Code, and must include terms to the effect that the
00061  * license from Licensee to its licensee is limited to the intellectual
00062  * property embodied in the software Licensee provides to its licensee, and
00063  * not to intellectual property embodied in modifications its licensee may
00064  * make.
00065  *
00066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
00067  * substantial portion of the Covered Code or modification must reproduce the
00068  * above Copyright Notice, and the following Disclaimer and Export Compliance
00069  * provision in the documentation and/or other materials provided with the
00070  * distribution.
00071  *
00072  * 3.4. Intel retains all right, title, and interest in and to the Original
00073  * Intel Code.
00074  *
00075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
00076  * Intel shall be used in advertising or otherwise to promote the sale, use or
00077  * other dealings in products derived from or relating to the Covered Code
00078  * without prior written authorization from Intel.
00079  *
00080  * 4. Disclaimer and Export Compliance
00081  *
00082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
00083  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
00084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
00085  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
00086  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
00087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
00088  * PARTICULAR PURPOSE.
00089  *
00090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
00091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
00092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
00093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
00094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
00095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
00096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
00097  * LIMITED REMEDY.
00098  *
00099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
00100  * software or system incorporating such software without first obtaining any
00101  * required license or other approval from the U. S. Department of Commerce or
00102  * any other agency or department of the United States Government.  In the
00103  * event Licensee exports any such software from the United States or
00104  * re-exports any such software from a foreign destination, Licensee shall
00105  * ensure that the distribution and export/re-export of the software is in
00106  * compliance with all laws, regulations, orders, or other restrictions of the
00107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
00108  * any of its subsidiaries will export/re-export any technical data, process,
00109  * software, or service, directly or indirectly, to any country for which the
00110  * United States government or any agency thereof requires an export license,
00111  * other governmental approval, or letter of assurance, without first obtaining
00112  * such license, approval or letter.
00113  *
00114  *****************************************************************************/
00115 
00116 #define __DSUTILS_C__
00117 
00118 #include "acpi.h"
00119 #include "accommon.h"
00120 #include "acparser.h"
00121 #include "amlcode.h"
00122 #include "acdispat.h"
00123 #include "acinterp.h"
00124 #include "acnamesp.h"
00125 #include "acdebug.h"
00126 
00127 #define _COMPONENT          ACPI_DISPATCHER
00128         ACPI_MODULE_NAME    ("dsutils")
00129 
00130 
00131 /*******************************************************************************
00132  *
00133  * FUNCTION:    AcpiDsClearImplicitReturn
00134  *
00135  * PARAMETERS:  WalkState           - Current State
00136  *
00137  * RETURN:      None.
00138  *
00139  * DESCRIPTION: Clear and remove a reference on an implicit return value.  Used
00140  *              to delete "stale" return values (if enabled, the return value
00141  *              from every operator is saved at least momentarily, in case the
00142  *              parent method exits.)
00143  *
00144  ******************************************************************************/
00145 
00146 void
00147 AcpiDsClearImplicitReturn (
00148     ACPI_WALK_STATE         *WalkState)
00149 {
00150     ACPI_FUNCTION_NAME (DsClearImplicitReturn);
00151 
00152 
00153     /*
00154      * Slack must be enabled for this feature
00155      */
00156     if (!AcpiGbl_EnableInterpreterSlack)
00157     {
00158         return;
00159     }
00160 
00161     if (WalkState->ImplicitReturnObj)
00162     {
00163         /*
00164          * Delete any "stale" implicit return. However, in
00165          * complex statements, the implicit return value can be
00166          * bubbled up several levels.
00167          */
00168         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
00169             "Removing reference on stale implicit return obj %p\n",
00170             WalkState->ImplicitReturnObj));
00171 
00172         AcpiUtRemoveReference (WalkState->ImplicitReturnObj);
00173         WalkState->ImplicitReturnObj = NULL;
00174     }
00175 }
00176 
00177 
00178 #ifndef ACPI_NO_METHOD_EXECUTION
00179 /*******************************************************************************
00180  *
00181  * FUNCTION:    AcpiDsDoImplicitReturn
00182  *
00183  * PARAMETERS:  ReturnDesc          - The return value
00184  *              WalkState           - Current State
00185  *              AddReference        - True if a reference should be added to the
00186  *                                    return object
00187  *
00188  * RETURN:      TRUE if implicit return enabled, FALSE otherwise
00189  *
00190  * DESCRIPTION: Implements the optional "implicit return".  We save the result
00191  *              of every ASL operator and control method invocation in case the
00192  *              parent method exit.  Before storing a new return value, we
00193  *              delete the previous return value.
00194  *
00195  ******************************************************************************/
00196 
00197 BOOLEAN
00198 AcpiDsDoImplicitReturn (
00199     ACPI_OPERAND_OBJECT     *ReturnDesc,
00200     ACPI_WALK_STATE         *WalkState,
00201     BOOLEAN                 AddReference)
00202 {
00203     ACPI_FUNCTION_NAME (DsDoImplicitReturn);
00204 
00205 
00206     /*
00207      * Slack must be enabled for this feature, and we must
00208      * have a valid return object
00209      */
00210     if ((!AcpiGbl_EnableInterpreterSlack) ||
00211         (!ReturnDesc))
00212     {
00213         return (FALSE);
00214     }
00215 
00216     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
00217             "Result %p will be implicitly returned; Prev=%p\n",
00218             ReturnDesc,
00219             WalkState->ImplicitReturnObj));
00220 
00221     /*
00222      * Delete any "stale" implicit return value first. However, in
00223      * complex statements, the implicit return value can be
00224      * bubbled up several levels, so we don't clear the value if it
00225      * is the same as the ReturnDesc.
00226      */
00227     if (WalkState->ImplicitReturnObj)
00228     {
00229         if (WalkState->ImplicitReturnObj == ReturnDesc)
00230         {
00231             return (TRUE);
00232         }
00233         AcpiDsClearImplicitReturn (WalkState);
00234     }
00235 
00236     /* Save the implicit return value, add a reference if requested */
00237 
00238     WalkState->ImplicitReturnObj = ReturnDesc;
00239     if (AddReference)
00240     {
00241         AcpiUtAddReference (ReturnDesc);
00242     }
00243 
00244     return (TRUE);
00245 }
00246 
00247 
00248 /*******************************************************************************
00249  *
00250  * FUNCTION:    AcpiDsIsResultUsed
00251  *
00252  * PARAMETERS:  Op                  - Current Op
00253  *              WalkState           - Current State
00254  *
00255  * RETURN:      TRUE if result is used, FALSE otherwise
00256  *
00257  * DESCRIPTION: Check if a result object will be used by the parent
00258  *
00259  ******************************************************************************/
00260 
00261 BOOLEAN
00262 AcpiDsIsResultUsed (
00263     ACPI_PARSE_OBJECT       *Op,
00264     ACPI_WALK_STATE         *WalkState)
00265 {
00266     const ACPI_OPCODE_INFO  *ParentInfo;
00267 
00268     ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op);
00269 
00270 
00271     /* Must have both an Op and a Result Object */
00272 
00273     if (!Op)
00274     {
00275         ACPI_ERROR ((AE_INFO, "Null Op"));
00276         return_UINT8 (TRUE);
00277     }
00278 
00279     /*
00280      * We know that this operator is not a
00281      * Return() operator (would not come here.) The following code is the
00282      * optional support for a so-called "implicit return". Some AML code
00283      * assumes that the last value of the method is "implicitly" returned
00284      * to the caller. Just save the last result as the return value.
00285      * NOTE: this is optional because the ASL language does not actually
00286      * support this behavior.
00287      */
00288     (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE);
00289 
00290     /*
00291      * Now determine if the parent will use the result
00292      *
00293      * If there is no parent, or the parent is a ScopeOp, we are executing
00294      * at the method level. An executing method typically has no parent,
00295      * since each method is parsed separately.  A method invoked externally
00296      * via ExecuteControlMethod has a ScopeOp as the parent.
00297      */
00298     if ((!Op->Common.Parent) ||
00299         (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
00300     {
00301         /* No parent, the return value cannot possibly be used */
00302 
00303         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
00304             "At Method level, result of [%s] not used\n",
00305             AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
00306         return_UINT8 (FALSE);
00307     }
00308 
00309     /* Get info on the parent. The RootOp is AML_SCOPE */
00310 
00311     ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
00312     if (ParentInfo->Class == AML_CLASS_UNKNOWN)
00313     {
00314         ACPI_ERROR ((AE_INFO,
00315             "Unknown parent opcode Op=%p", Op));
00316         return_UINT8 (FALSE);
00317     }
00318 
00319     /*
00320      * Decide what to do with the result based on the parent.  If
00321      * the parent opcode will not use the result, delete the object.
00322      * Otherwise leave it as is, it will be deleted when it is used
00323      * as an operand later.
00324      */
00325     switch (ParentInfo->Class)
00326     {
00327     case AML_CLASS_CONTROL:
00328 
00329         switch (Op->Common.Parent->Common.AmlOpcode)
00330         {
00331         case AML_RETURN_OP:
00332 
00333             /* Never delete the return value associated with a return opcode */
00334 
00335             goto ResultUsed;
00336 
00337         case AML_IF_OP:
00338         case AML_WHILE_OP:
00339 
00340             /*
00341              * If we are executing the predicate AND this is the predicate op,
00342              * we will use the return value
00343              */
00344             if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) &&
00345                 (WalkState->ControlState->Control.PredicateOp == Op))
00346             {
00347                 goto ResultUsed;
00348             }
00349             break;
00350 
00351         default:
00352             /* Ignore other control opcodes */
00353             break;
00354         }
00355 
00356         /* The general control opcode returns no result */
00357 
00358         goto ResultNotUsed;
00359 
00360 
00361     case AML_CLASS_CREATE:
00362 
00363         /*
00364          * These opcodes allow TermArg(s) as operands and therefore
00365          * the operands can be method calls.  The result is used.
00366          */
00367         goto ResultUsed;
00368 
00369 
00370     case AML_CLASS_NAMED_OBJECT:
00371 
00372         if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
00373             (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
00374             (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
00375             (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)  ||
00376             (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
00377             (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) ||
00378             (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP))
00379         {
00380             /*
00381              * These opcodes allow TermArg(s) as operands and therefore
00382              * the operands can be method calls.  The result is used.
00383              */
00384             goto ResultUsed;
00385         }
00386 
00387         goto ResultNotUsed;
00388 
00389 
00390     default:
00391 
00392         /*
00393          * In all other cases. the parent will actually use the return
00394          * object, so keep it.
00395          */
00396         goto ResultUsed;
00397     }
00398 
00399 
00400 ResultUsed:
00401     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
00402         "Result of [%s] used by Parent [%s] Op=%p\n",
00403         AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
00404         AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
00405 
00406     return_UINT8 (TRUE);
00407 
00408 
00409 ResultNotUsed:
00410     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
00411         "Result of [%s] not used by Parent [%s] Op=%p\n",
00412         AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
00413         AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
00414 
00415     return_UINT8 (FALSE);
00416 }
00417 
00418 
00419 /*******************************************************************************
00420  *
00421  * FUNCTION:    AcpiDsDeleteResultIfNotUsed
00422  *
00423  * PARAMETERS:  Op              - Current parse Op
00424  *              ResultObj       - Result of the operation
00425  *              WalkState       - Current state
00426  *
00427  * RETURN:      Status
00428  *
00429  * DESCRIPTION: Used after interpretation of an opcode.  If there is an internal
00430  *              result descriptor, check if the parent opcode will actually use
00431  *              this result.  If not, delete the result now so that it will
00432  *              not become orphaned.
00433  *
00434  ******************************************************************************/
00435 
00436 void
00437 AcpiDsDeleteResultIfNotUsed (
00438     ACPI_PARSE_OBJECT       *Op,
00439     ACPI_OPERAND_OBJECT     *ResultObj,
00440     ACPI_WALK_STATE         *WalkState)
00441 {
00442     ACPI_OPERAND_OBJECT     *ObjDesc;
00443     ACPI_STATUS             Status;
00444 
00445 
00446     ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj);
00447 
00448 
00449     if (!Op)
00450     {
00451         ACPI_ERROR ((AE_INFO, "Null Op"));
00452         return_VOID;
00453     }
00454 
00455     if (!ResultObj)
00456     {
00457         return_VOID;
00458     }
00459 
00460     if (!AcpiDsIsResultUsed (Op, WalkState))
00461     {
00462         /* Must pop the result stack (ObjDesc should be equal to ResultObj) */
00463 
00464         Status = AcpiDsResultPop (&ObjDesc, WalkState);
00465         if (ACPI_SUCCESS (Status))
00466         {
00467             AcpiUtRemoveReference (ResultObj);
00468         }
00469     }
00470 
00471     return_VOID;
00472 }
00473 
00474 
00475 /*******************************************************************************
00476  *
00477  * FUNCTION:    AcpiDsResolveOperands
00478  *
00479  * PARAMETERS:  WalkState           - Current walk state with operands on stack
00480  *
00481  * RETURN:      Status
00482  *
00483  * DESCRIPTION: Resolve all operands to their values.  Used to prepare
00484  *              arguments to a control method invocation (a call from one
00485  *              method to another.)
00486  *
00487  ******************************************************************************/
00488 
00489 ACPI_STATUS
00490 AcpiDsResolveOperands (
00491     ACPI_WALK_STATE         *WalkState)
00492 {
00493     UINT32                  i;
00494     ACPI_STATUS             Status = AE_OK;
00495 
00496 
00497     ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState);
00498 
00499 
00500     /*
00501      * Attempt to resolve each of the valid operands
00502      * Method arguments are passed by reference, not by value.  This means
00503      * that the actual objects are passed, not copies of the objects.
00504      */
00505     for (i = 0; i < WalkState->NumOperands; i++)
00506     {
00507         Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState);
00508         if (ACPI_FAILURE (Status))
00509         {
00510             break;
00511         }
00512     }
00513 
00514     return_ACPI_STATUS (Status);
00515 }
00516 
00517 
00518 /*******************************************************************************
00519  *
00520  * FUNCTION:    AcpiDsClearOperands
00521  *
00522  * PARAMETERS:  WalkState           - Current walk state with operands on stack
00523  *
00524  * RETURN:      None
00525  *
00526  * DESCRIPTION: Clear all operands on the current walk state operand stack.
00527  *
00528  ******************************************************************************/
00529 
00530 void
00531 AcpiDsClearOperands (
00532     ACPI_WALK_STATE         *WalkState)
00533 {
00534     UINT32                  i;
00535 
00536 
00537     ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState);
00538 
00539 
00540     /* Remove a reference on each operand on the stack */
00541 
00542     for (i = 0; i < WalkState->NumOperands; i++)
00543     {
00544         /*
00545          * Remove a reference to all operands, including both
00546          * "Arguments" and "Targets".
00547          */
00548         AcpiUtRemoveReference (WalkState->Operands[i]);
00549         WalkState->Operands[i] = NULL;
00550     }
00551 
00552     WalkState->NumOperands = 0;
00553     return_VOID;
00554 }
00555 #endif
00556 
00557 
00558 /*******************************************************************************
00559  *
00560  * FUNCTION:    AcpiDsCreateOperand
00561  *
00562  * PARAMETERS:  WalkState       - Current walk state
00563  *              Arg             - Parse object for the argument
00564  *              ArgIndex        - Which argument (zero based)
00565  *
00566  * RETURN:      Status
00567  *
00568  * DESCRIPTION: Translate a parse tree object that is an argument to an AML
00569  *              opcode to the equivalent interpreter object.  This may include
00570  *              looking up a name or entering a new name into the internal
00571  *              namespace.
00572  *
00573  ******************************************************************************/
00574 
00575 ACPI_STATUS
00576 AcpiDsCreateOperand (
00577     ACPI_WALK_STATE         *WalkState,
00578     ACPI_PARSE_OBJECT       *Arg,
00579     UINT32                  ArgIndex)
00580 {
00581     ACPI_STATUS             Status = AE_OK;
00582     char                    *NameString;
00583     UINT32                  NameLength;
00584     ACPI_OPERAND_OBJECT     *ObjDesc;
00585     ACPI_PARSE_OBJECT       *ParentOp;
00586     UINT16                  Opcode;
00587     ACPI_INTERPRETER_MODE   InterpreterMode;
00588     const ACPI_OPCODE_INFO  *OpInfo;
00589 
00590 
00591     ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);
00592 
00593 
00594     /* A valid name must be looked up in the namespace */
00595 
00596     if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
00597         (Arg->Common.Value.String) &&
00598         !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
00599     {
00600         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));
00601 
00602         /* Get the entire name string from the AML stream */
00603 
00604         Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer,
00605                         &NameString, &NameLength);
00606 
00607         if (ACPI_FAILURE (Status))
00608         {
00609             return_ACPI_STATUS (Status);
00610         }
00611 
00612         /* All prefixes have been handled, and the name is in NameString */
00613 
00614         /*
00615          * Special handling for BufferField declarations.  This is a deferred
00616          * opcode that unfortunately defines the field name as the last
00617          * parameter instead of the first.  We get here when we are performing
00618          * the deferred execution, so the actual name of the field is already
00619          * in the namespace.  We don't want to attempt to look it up again
00620          * because we may be executing in a different scope than where the
00621          * actual opcode exists.
00622          */
00623         if ((WalkState->DeferredNode) &&
00624             (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
00625             (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
00626         {
00627             ObjDesc = ACPI_CAST_PTR (
00628                         ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
00629             Status = AE_OK;
00630         }
00631         else    /* All other opcodes */
00632         {
00633             /*
00634              * Differentiate between a namespace "create" operation
00635              * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
00636              * IMODE_EXECUTE) in order to support the creation of
00637              * namespace objects during the execution of control methods.
00638              */
00639             ParentOp = Arg->Common.Parent;
00640             OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
00641             if ((OpInfo->Flags & AML_NSNODE) &&
00642                 (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
00643                 (ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
00644                 (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
00645             {
00646                 /* Enter name into namespace if not found */
00647 
00648                 InterpreterMode = ACPI_IMODE_LOAD_PASS2;
00649             }
00650             else
00651             {
00652                 /* Return a failure if name not found */
00653 
00654                 InterpreterMode = ACPI_IMODE_EXECUTE;
00655             }
00656 
00657             Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
00658                         ACPI_TYPE_ANY, InterpreterMode,
00659                         ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
00660                         WalkState,
00661                         ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
00662             /*
00663              * The only case where we pass through (ignore) a NOT_FOUND
00664              * error is for the CondRefOf opcode.
00665              */
00666             if (Status == AE_NOT_FOUND)
00667             {
00668                 if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP)
00669                 {
00670                     /*
00671                      * For the Conditional Reference op, it's OK if
00672                      * the name is not found;  We just need a way to
00673                      * indicate this to the interpreter, set the
00674                      * object to the root
00675                      */
00676                     ObjDesc = ACPI_CAST_PTR (
00677                                 ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
00678                     Status = AE_OK;
00679                 }
00680                 else
00681                 {
00682                     /*
00683                      * We just plain didn't find it -- which is a
00684                      * very serious error at this point
00685                      */
00686                     Status = AE_AML_NAME_NOT_FOUND;
00687                 }
00688             }
00689 
00690             if (ACPI_FAILURE (Status))
00691             {
00692                 ACPI_ERROR_NAMESPACE (NameString, Status);
00693             }
00694         }
00695 
00696         /* Free the namestring created above */
00697 
00698         ACPI_FREE (NameString);
00699 
00700         /* Check status from the lookup */
00701 
00702         if (ACPI_FAILURE (Status))
00703         {
00704             return_ACPI_STATUS (Status);
00705         }
00706 
00707         /* Put the resulting object onto the current object stack */
00708 
00709         Status = AcpiDsObjStackPush (ObjDesc, WalkState);
00710         if (ACPI_FAILURE (Status))
00711         {
00712             return_ACPI_STATUS (Status);
00713         }
00714         ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
00715     }
00716     else
00717     {
00718         /* Check for null name case */
00719 
00720         if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
00721             !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
00722         {
00723             /*
00724              * If the name is null, this means that this is an
00725              * optional result parameter that was not specified
00726              * in the original ASL.  Create a Zero Constant for a
00727              * placeholder.  (Store to a constant is a Noop.)
00728              */
00729             Opcode = AML_ZERO_OP;       /* Has no arguments! */
00730 
00731             ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
00732                 "Null namepath: Arg=%p\n", Arg));
00733         }
00734         else
00735         {
00736             Opcode = Arg->Common.AmlOpcode;
00737         }
00738 
00739         /* Get the object type of the argument */
00740 
00741         OpInfo = AcpiPsGetOpcodeInfo (Opcode);
00742         if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
00743         {
00744             return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
00745         }
00746 
00747         if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
00748         {
00749             ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
00750                 "Argument previously created, already stacked\n"));
00751 
00752             ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (
00753                 WalkState->Operands [WalkState->NumOperands - 1], WalkState));
00754 
00755             /*
00756              * Use value that was already previously returned
00757              * by the evaluation of this argument
00758              */
00759             Status = AcpiDsResultPop (&ObjDesc, WalkState);
00760             if (ACPI_FAILURE (Status))
00761             {
00762                 /*
00763                  * Only error is underflow, and this indicates
00764                  * a missing or null operand!
00765                  */
00766                 ACPI_EXCEPTION ((AE_INFO, Status,
00767                     "Missing or null operand"));
00768                 return_ACPI_STATUS (Status);
00769             }
00770         }
00771         else
00772         {
00773             /* Create an ACPI_INTERNAL_OBJECT for the argument */
00774 
00775             ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
00776             if (!ObjDesc)
00777             {
00778                 return_ACPI_STATUS (AE_NO_MEMORY);
00779             }
00780 
00781             /* Initialize the new object */
00782 
00783             Status = AcpiDsInitObjectFromOp (
00784                         WalkState, Arg, Opcode, &ObjDesc);
00785             if (ACPI_FAILURE (Status))
00786             {
00787                 AcpiUtDeleteObjectDesc (ObjDesc);
00788                 return_ACPI_STATUS (Status);
00789             }
00790         }
00791 
00792         /* Put the operand object on the object stack */
00793 
00794         Status = AcpiDsObjStackPush (ObjDesc, WalkState);
00795         if (ACPI_FAILURE (Status))
00796         {
00797             return_ACPI_STATUS (Status);
00798         }
00799 
00800         ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
00801     }
00802 
00803     return_ACPI_STATUS (AE_OK);
00804 }
00805 
00806 
00807 /*******************************************************************************
00808  *
00809  * FUNCTION:    AcpiDsCreateOperands
00810  *
00811  * PARAMETERS:  WalkState           - Current state
00812  *              FirstArg            - First argument of a parser argument tree
00813  *
00814  * RETURN:      Status
00815  *
00816  * DESCRIPTION: Convert an operator's arguments from a parse tree format to
00817  *              namespace objects and place those argument object on the object
00818  *              stack in preparation for evaluation by the interpreter.
00819  *
00820  ******************************************************************************/
00821 
00822 ACPI_STATUS
00823 AcpiDsCreateOperands (
00824     ACPI_WALK_STATE         *WalkState,
00825     ACPI_PARSE_OBJECT       *FirstArg)
00826 {
00827     ACPI_STATUS             Status = AE_OK;
00828     ACPI_PARSE_OBJECT       *Arg;
00829     ACPI_PARSE_OBJECT       *Arguments[ACPI_OBJ_NUM_OPERANDS];
00830     UINT32                  ArgCount = 0;
00831     UINT32                  Index = WalkState->NumOperands;
00832     UINT32                  i;
00833 
00834 
00835     ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg);
00836 
00837 
00838     /* Get all arguments in the list */
00839 
00840     Arg = FirstArg;
00841     while (Arg)
00842     {
00843         if (Index >= ACPI_OBJ_NUM_OPERANDS)
00844         {
00845             return_ACPI_STATUS (AE_BAD_DATA);
00846         }
00847 
00848         Arguments[Index] = Arg;
00849         WalkState->Operands [Index] = NULL;
00850 
00851         /* Move on to next argument, if any */
00852 
00853         Arg = Arg->Common.Next;
00854         ArgCount++;
00855         Index++;
00856     }
00857 
00858     Index--;
00859 
00860     /* It is the appropriate order to get objects from the Result stack */
00861 
00862     for (i = 0; i < ArgCount; i++)
00863     {
00864         Arg = Arguments[Index];
00865 
00866         /* Force the filling of the operand stack in inverse order */
00867 
00868         WalkState->OperandIndex = (UINT8) Index;
00869 
00870         Status = AcpiDsCreateOperand (WalkState, Arg, Index);
00871         if (ACPI_FAILURE (Status))
00872         {
00873             goto Cleanup;
00874         }
00875 
00876         Index--;
00877 
00878         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%u (%p) done, Arg1=%p\n",
00879             Index, Arg, FirstArg));
00880     }
00881 
00882     return_ACPI_STATUS (Status);
00883 
00884 
00885 Cleanup:
00886     /*
00887      * We must undo everything done above; meaning that we must
00888      * pop everything off of the operand stack and delete those
00889      * objects
00890      */
00891     AcpiDsObjStackPopAndDelete (ArgCount, WalkState);
00892 
00893     ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index));
00894     return_ACPI_STATUS (Status);
00895 }
00896 
00897 
00898 /*****************************************************************************
00899  *
00900  * FUNCTION:    AcpiDsEvaluateNamePath
00901  *
00902  * PARAMETERS:  WalkState       - Current state of the parse tree walk,
00903  *                                the opcode of current operation should be
00904  *                                AML_INT_NAMEPATH_OP
00905  *
00906  * RETURN:      Status
00907  *
00908  * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent
00909  *              interpreter object, convert it to value, if needed, duplicate
00910  *              it, if needed, and push it onto the current result stack.
00911  *
00912  ****************************************************************************/
00913 
00914 ACPI_STATUS
00915 AcpiDsEvaluateNamePath (
00916     ACPI_WALK_STATE         *WalkState)
00917 {
00918     ACPI_STATUS             Status = AE_OK;
00919     ACPI_PARSE_OBJECT       *Op = WalkState->Op;
00920     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
00921     ACPI_OPERAND_OBJECT     *NewObjDesc;
00922     UINT8                   Type;
00923 
00924 
00925     ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState);
00926 
00927 
00928     if (!Op->Common.Parent)
00929     {
00930         /* This happens after certain exception processing */
00931 
00932         goto Exit;
00933     }
00934 
00935     if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
00936         (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) ||
00937         (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP))
00938     {
00939         /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */
00940 
00941         goto Exit;
00942     }
00943 
00944     Status = AcpiDsCreateOperand (WalkState, Op, 0);
00945     if (ACPI_FAILURE (Status))
00946     {
00947         goto Exit;
00948     }
00949 
00950     if (Op->Common.Flags & ACPI_PARSEOP_TARGET)
00951     {
00952         NewObjDesc = *Operand;
00953         goto PushResult;
00954     }
00955 
00956     Type = (*Operand)->Common.Type;
00957 
00958     Status = AcpiExResolveToValue (Operand, WalkState);
00959     if (ACPI_FAILURE (Status))
00960     {
00961         goto Exit;
00962     }
00963 
00964     if (Type == ACPI_TYPE_INTEGER)
00965     {
00966         /* It was incremented by AcpiExResolveToValue */
00967 
00968         AcpiUtRemoveReference (*Operand);
00969 
00970         Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState);
00971         if (ACPI_FAILURE (Status))
00972         {
00973             goto Exit;
00974         }
00975     }
00976     else
00977     {
00978         /*
00979          * The object either was anew created or is
00980          * a Namespace node - don't decrement it.
00981          */
00982         NewObjDesc = *Operand;
00983     }
00984 
00985     /* Cleanup for name-path operand */
00986 
00987     Status = AcpiDsObjStackPop (1, WalkState);
00988     if (ACPI_FAILURE (Status))
00989     {
00990         WalkState->ResultObj = NewObjDesc;
00991         goto Exit;
00992     }
00993 
00994 PushResult:
00995 
00996     WalkState->ResultObj = NewObjDesc;
00997 
00998     Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
00999     if (ACPI_SUCCESS (Status))
01000     {
01001         /* Force to take it from stack */
01002 
01003         Op->Common.Flags |= ACPI_PARSEOP_IN_STACK;
01004     }
01005 
01006 Exit:
01007 
01008     return_ACPI_STATUS (Status);
01009 }

Generated on Mon May 28 2012 04:26:55 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.