ACPI_STATUS AcpiPsxExecute ( ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT **Params, ACPI_OPERAND_OBJECT **ReturnObjDesc) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; UINT32 i; ACPI_PARSE_OBJECT *Op; ACPI_WALK_STATE *WalkState; ACPI_FUNCTION_TRACE ("PsxExecute"); /* Validate the Node and get the attached object */ if (!MethodNode) { return_ACPI_STATUS (AE_NULL_ENTRY); } ObjDesc = AcpiNsGetAttachedObject (MethodNode); if (!ObjDesc) { return_ACPI_STATUS (AE_NULL_OBJECT); } /* Init for new method, wait on concurrency semaphore */ Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc, NULL); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (Params) { /* * The caller "owns" the parameters, so give each one an extra * reference */ for (i = 0; Params[i]; i++) { AcpiUtAddReference (Params[i]); } } /* * 1) Perform the first pass parse of the method to enter any * named objects that it creates into the namespace */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Parse **** Entry=%p obj=%p\n", MethodNode, ObjDesc)); /* Create and init a Root Node */ Op = AcpiPsCreateScopeOp (); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); } /* * Get a new OwnerId for objects created by this method. Namespace * objects (such as Operation Regions) can be created during the * first pass parse. */ ObjDesc->Method.OwningId = AcpiUtAllocateOwnerId (ACPI_OWNER_TYPE_METHOD); /* Create and initialize a new walk state */ WalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwningId, NULL, NULL, NULL); if (!WalkState) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiDsInitAmlWalk (WalkState, Op, MethodNode, ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, NULL, NULL, 1); if (ACPI_FAILURE (Status)) { AcpiDsDeleteWalkState (WalkState); return_ACPI_STATUS (Status); } /* Parse the AML */ Status = AcpiPsParseAml (WalkState); AcpiPsDeleteParseTree (Op); /* * 2) Execute the method. Performs second pass parse simultaneously */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Execution **** Entry=%p obj=%p\n", MethodNode, ObjDesc)); /* Create and init a Root Node */ Op = AcpiPsCreateScopeOp (); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Init new op with the method name and pointer back to the NS node */ AcpiPsSetName (Op, MethodNode->Name.Integer); Op->Common.Node = MethodNode; /* Create and initialize a new walk state */ WalkState = AcpiDsCreateWalkState (TABLE_ID_DSDT, NULL, NULL, NULL); if (!WalkState) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiDsInitAmlWalk (WalkState, Op, MethodNode, ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, Params, ReturnObjDesc, 3); if (ACPI_FAILURE (Status)) { AcpiDsDeleteWalkState (WalkState); return_ACPI_STATUS (Status); } /* * The walk of the parse tree is where we actually execute the method */ Status = AcpiPsParseAml (WalkState); AcpiPsDeleteParseTree (Op); if (Params) { /* Take away the extra reference that we gave the parameters above */ for (i = 0; Params[i]; i++) { /* Ignore errors, just do them all */ (void) AcpiUtUpdateObjectReference (Params[i], REF_DECREMENT); } } /* * If the method has returned an object, signal this to the caller with * a control exception code */ if (*ReturnObjDesc) { ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n", *ReturnObjDesc)); ACPI_DUMP_STACK_ENTRY (*ReturnObjDesc); Status = AE_CTRL_RETURN_VALUE; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiDsCallControlMethod ( ACPI_THREAD_STATE *Thread, ACPI_WALK_STATE *ThisWalkState, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *MethodNode; ACPI_WALK_STATE *NextWalkState = NULL; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_EVALUATE_INFO *Info; UINT32 i; ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n", ThisWalkState->PrevOp, ThisWalkState)); /* * Get the namespace entry for the control method we are about to call */ MethodNode = ThisWalkState->MethodCallNode; if (!MethodNode) { return_ACPI_STATUS (AE_NULL_ENTRY); } ObjDesc = AcpiNsGetAttachedObject (MethodNode); if (!ObjDesc) { return_ACPI_STATUS (AE_NULL_OBJECT); } /* Init for new method, possibly wait on method mutex */ Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc, ThisWalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Begin method parse/execution. Create a new walk state */ NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId, NULL, ObjDesc, Thread); if (!NextWalkState) { Status = AE_NO_MEMORY; goto Cleanup; } /* * The resolved arguments were put on the previous walk state's operand * stack. Operands on the previous walk state stack always * start at index 0. Also, null terminate the list of arguments */ ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL; /* * Allocate and initialize the evaluation information block * TBD: this is somewhat inefficient, should change interface to * DsInitAmlWalk. For now, keeps this struct off the CPU stack */ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); if (!Info) { return_ACPI_STATUS (AE_NO_MEMORY); } Info->Parameters = &ThisWalkState->Operands[0]; Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode, ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, Info, ACPI_IMODE_EXECUTE); ACPI_FREE (Info); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* * Delete the operands on the previous walkstate operand stack * (they were copied to new objects) */ for (i = 0; i < ObjDesc->Method.ParamCount; i++) { AcpiUtRemoveReference (ThisWalkState->Operands [i]); ThisWalkState->Operands [i] = NULL; } /* Clear the operand stack */ ThisWalkState->NumOperands = 0; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", MethodNode->Name.Ascii, NextWalkState)); /* Invoke an internal method if necessary */ if (ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY) { Status = ObjDesc->Method.Dispatch.Implementation (NextWalkState); if (Status == AE_OK) { Status = AE_CTRL_TERMINATE; } } return_ACPI_STATUS (Status); Cleanup: /* On error, we must terminate the method properly */ AcpiDsTerminateControlMethod (ObjDesc, NextWalkState); if (NextWalkState) { AcpiDsDeleteWalkState (NextWalkState); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiPsExecuteMethod ( ACPI_EVALUATE_INFO *Info) { ACPI_STATUS Status; ACPI_PARSE_OBJECT *Op; ACPI_WALK_STATE *WalkState; ACPI_FUNCTION_TRACE (PsExecuteMethod); /* Quick validation of DSDT header */ AcpiTbCheckDsdtHeader (); /* Validate the Info and method Node */ if (!Info || !Info->Node) { return_ACPI_STATUS (AE_NULL_ENTRY); } /* Init for new method, wait on concurrency semaphore */ Status = AcpiDsBeginMethodExecution (Info->Node, Info->ObjDesc, NULL); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * The caller "owns" the parameters, so give each one an extra reference */ AcpiPsUpdateParameterList (Info, REF_INCREMENT); /* * Execute the method. Performs parse simultaneously */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", Info->Node->Name.Ascii, Info->Node, Info->ObjDesc)); /* Create and init a Root Node */ Op = AcpiPsCreateScopeOp (Info->ObjDesc->Method.AmlStart); if (!Op) { Status = AE_NO_MEMORY; goto Cleanup; } /* Create and initialize a new walk state */ Info->PassNumber = ACPI_IMODE_EXECUTE; WalkState = AcpiDsCreateWalkState ( Info->ObjDesc->Method.OwnerId, NULL, NULL, NULL); if (!WalkState) { Status = AE_NO_MEMORY; goto Cleanup; } Status = AcpiDsInitAmlWalk (WalkState, Op, Info->Node, Info->ObjDesc->Method.AmlStart, Info->ObjDesc->Method.AmlLength, Info, Info->PassNumber); if (ACPI_FAILURE (Status)) { AcpiDsDeleteWalkState (WalkState); goto Cleanup; } if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) { WalkState->ParseFlags |= ACPI_PARSE_MODULE_LEVEL; } /* Invoke an internal method if necessary */ if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY) { Status = Info->ObjDesc->Method.Dispatch.Implementation (WalkState); Info->ReturnObject = WalkState->ReturnDesc; /* Cleanup states */ AcpiDsScopeStackClear (WalkState); AcpiPsCleanupScope (&WalkState->ParserState); AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); AcpiDsDeleteWalkState (WalkState); goto Cleanup; } /* * Start method evaluation with an implicit return of zero. * This is done for Windows compatibility. */ if (AcpiGbl_EnableInterpreterSlack) { WalkState->ImplicitReturnObj = AcpiUtCreateIntegerObject ((UINT64) 0); if (!WalkState->ImplicitReturnObj) { Status = AE_NO_MEMORY; AcpiDsDeleteWalkState (WalkState); goto Cleanup; } } /* Parse the AML */ Status = AcpiPsParseAml (WalkState); /* WalkState was deleted by ParseAml */ Cleanup: AcpiPsDeleteParseTree (Op); /* Take away the extra reference that we gave the parameters above */ AcpiPsUpdateParameterList (Info, REF_DECREMENT); /* Exit now if error above */ if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * If the method has returned an object, signal this to the caller with * a control exception code */ if (Info->ReturnObject) { ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n", Info->ReturnObject)); ACPI_DUMP_STACK_ENTRY (Info->ReturnObject); Status = AE_CTRL_RETURN_VALUE; } return_ACPI_STATUS (Status); }