void AcpiPsCleanupScope ( ACPI_PARSE_STATE *ParserState) { ACPI_GENERIC_STATE *Scope; ACPI_FUNCTION_TRACE_PTR (PsCleanupScope, ParserState); if (!ParserState) { return_VOID; } /* Delete anything on the scope stack */ while (ParserState->Scope) { Scope = AcpiUtPopGenericState (&ParserState->Scope); AcpiUtDeleteGenericState (Scope); } return_VOID; }
static void ACPI_SYSTEM_XFACE AcpiEvNotifyDispatch ( void *Context) { ACPI_GENERIC_STATE *NotifyInfo = (ACPI_GENERIC_STATE *) Context; ACPI_NOTIFY_HANDLER GlobalHandler = NULL; void *GlobalContext = NULL; ACPI_OPERAND_OBJECT *HandlerObj; ACPI_FUNCTION_ENTRY (); /* * We will invoke a global notify handler if installed. This is done * _before_ we invoke the per-device handler attached to the device. */ if (NotifyInfo->Notify.Value <= ACPI_MAX_SYS_NOTIFY) { /* Global system notification handler */ if (AcpiGbl_SystemNotify.Handler) { GlobalHandler = AcpiGbl_SystemNotify.Handler; GlobalContext = AcpiGbl_SystemNotify.Context; } } else { /* Global driver notification handler */ if (AcpiGbl_DeviceNotify.Handler) { GlobalHandler = AcpiGbl_DeviceNotify.Handler; GlobalContext = AcpiGbl_DeviceNotify.Context; } } /* Invoke the system handler first, if present */ if (GlobalHandler) { GlobalHandler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, GlobalContext); } /* Now invoke the per-device handler, if present */ HandlerObj = NotifyInfo->Notify.HandlerObj; if (HandlerObj) { HandlerObj->Notify.Handler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, HandlerObj->Notify.Context); } /* All done with the info object */ AcpiUtDeleteGenericState (NotifyInfo); }
ACPI_STATUS AcpiDsScopeStackPop ( ACPI_WALK_STATE *WalkState) { ACPI_GENERIC_STATE *ScopeInfo; ACPI_GENERIC_STATE *NewScopeInfo; ACPI_FUNCTION_TRACE ("DsScopeStackPop"); /* * Pop scope info object off the stack. */ ScopeInfo = AcpiUtPopGenericState (&WalkState->ScopeInfo); if (!ScopeInfo) { return_ACPI_STATUS (AE_STACK_UNDERFLOW); } WalkState->ScopeDepth--; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%.2d] Popped scope [%4.4s] (%10s), New scope -> ", (UINT32) WalkState->ScopeDepth, ScopeInfo->Scope.Node->Name.Ascii, AcpiUtGetTypeName (ScopeInfo->Common.Value))); NewScopeInfo = WalkState->ScopeInfo; if (NewScopeInfo) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "[%4.4s] (%s)\n", NewScopeInfo->Scope.Node->Name.Ascii, AcpiUtGetTypeName (NewScopeInfo->Common.Value))); } else { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "[\\___] (ROOT)\n")); } AcpiUtDeleteGenericState (ScopeInfo); return_ACPI_STATUS (AE_OK); }
void AcpiPsPopScope ( ACPI_PARSE_STATE *ParserState, ACPI_PARSE_OBJECT **Op, UINT32 *ArgList, UINT32 *ArgCount) { ACPI_GENERIC_STATE *Scope = ParserState->Scope; ACPI_FUNCTION_TRACE (PsPopScope); /* Only pop the scope if there is in fact a next scope */ if (Scope->Common.Next) { Scope = AcpiUtPopGenericState (&ParserState->Scope); /* Return to parsing previous op */ *Op = Scope->ParseScope.Op; *ArgList = Scope->ParseScope.ArgList; *ArgCount = Scope->ParseScope.ArgCount; ParserState->PkgEnd = Scope->ParseScope.PkgEnd; /* All done with this scope state structure */ AcpiUtDeleteGenericState (Scope); } else { /* Empty parse stack, prepare to fetch next opcode */ *Op = NULL; *ArgList = 0; *ArgCount = 0; } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped Op %p Args %X\n", *Op, *ArgCount)); return_VOID; }
void AcpiDsScopeStackClear ( ACPI_WALK_STATE *WalkState) { ACPI_GENERIC_STATE *ScopeInfo; ACPI_FUNCTION_NAME ("DsScopeStackClear"); while (WalkState->ScopeInfo) { /* Pop a scope off the stack */ ScopeInfo = WalkState->ScopeInfo; WalkState->ScopeInfo = ScopeInfo->Scope.Next; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Popped object type (%s)\n", AcpiUtGetTypeName (ScopeInfo->Common.Value))); AcpiUtDeleteGenericState (ScopeInfo); } }
static ACPI_STATUS AcpiDsResultStackPop ( ACPI_WALK_STATE *WalkState) { ACPI_GENERIC_STATE *State; ACPI_FUNCTION_NAME (DsResultStackPop); /* Check for stack underflow */ if (WalkState->Results == NULL) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Result stack underflow - State=%p\n", WalkState)); return (AE_AML_NO_OPERAND); } if (WalkState->ResultSize < ACPI_RESULTS_FRAME_OBJ_NUM) { ACPI_ERROR ((AE_INFO, "Insufficient result stack size")); return (AE_AML_INTERNAL); } State = AcpiUtPopGenericState (&WalkState->Results); AcpiUtDeleteGenericState (State); /* Decrease the length of result stack by the length of frame */ WalkState->ResultSize -= ACPI_RESULTS_FRAME_OBJ_NUM; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Result=%p RemainingResults=%X State=%p\n", State, WalkState->ResultCount, WalkState)); return (AE_OK); }
static void ACPI_SYSTEM_XFACE AcpiEvNotifyDispatch ( void *Context) { ACPI_GENERIC_STATE *Info = (ACPI_GENERIC_STATE *) Context; ACPI_OPERAND_OBJECT *HandlerObj; ACPI_FUNCTION_ENTRY (); /* Invoke a global notify handler if installed */ if (Info->Notify.Global->Handler) { Info->Notify.Global->Handler (Info->Notify.Node, Info->Notify.Value, Info->Notify.Global->Context); } /* Now invoke the local notify handler(s) if any are installed */ HandlerObj = Info->Notify.HandlerListHead; while (HandlerObj) { HandlerObj->Notify.Handler (Info->Notify.Node, Info->Notify.Value, HandlerObj->Notify.Context); HandlerObj = HandlerObj->Notify.Next[Info->Notify.HandlerListId]; } /* All done with the info object */ AcpiUtDeleteGenericState (Info); }
ACPI_STATUS AcpiEvQueueNotifyRequest ( ACPI_NAMESPACE_NODE *Node, UINT32 NotifyValue) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerListHead = NULL; ACPI_GENERIC_STATE *Info; UINT8 HandlerListId = 0; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_NAME (EvQueueNotifyRequest); /* Are Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { return (AE_TYPE); } /* Get the correct notify list type (System or Device) */ if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) { HandlerListId = ACPI_SYSTEM_HANDLER_LIST; } else { HandlerListId = ACPI_DEVICE_HANDLER_LIST; } /* Get the notify object attached to the namespace Node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* We have an attached object, Get the correct handler list */ HandlerListHead = ObjDesc->CommonNotify.NotifyList[HandlerListId]; } /* * If there is no notify handler (Global or Local) * for this object, just ignore the notify */ if (!AcpiGbl_GlobalNotify[HandlerListId].Handler && !HandlerListHead) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); return (AE_OK); } /* Setup notify info and schedule the notify dispatcher */ Info = AcpiUtCreateGenericState (); if (!Info) { return (AE_NO_MEMORY); } Info->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; Info->Notify.Node = Node; Info->Notify.Value = (UINT16) NotifyValue; Info->Notify.HandlerListId = HandlerListId; Info->Notify.HandlerListHead = HandlerListHead; Info->Notify.Global = &AcpiGbl_GlobalNotify[HandlerListId]; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), NotifyValue, AcpiUtGetNotifyName (NotifyValue, ACPI_TYPE_ANY), Node)); Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, Info); if (ACPI_FAILURE (Status)) { AcpiUtDeleteGenericState (Info); } return (Status); }
ACPI_STATUS AcpiPsParseAml ( ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status; ACPI_THREAD_STATE *Thread; ACPI_THREAD_STATE *PrevWalkList = AcpiGbl_CurrentWalkList; ACPI_WALK_STATE *PreviousWalkState; ACPI_FUNCTION_TRACE (PsParseAml); ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Entered with WalkState=%p Aml=%p size=%X\n", WalkState, WalkState->ParserState.Aml, WalkState->ParserState.AmlSize)); if (!WalkState->ParserState.Aml) { return_ACPI_STATUS (AE_NULL_OBJECT); } /* Create and initialize a new thread state */ Thread = AcpiUtCreateThreadState (); if (!Thread) { if (WalkState->MethodDesc) { /* Executing a control method - additional cleanup */ AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); } AcpiDsDeleteWalkState (WalkState); return_ACPI_STATUS (AE_NO_MEMORY); } WalkState->Thread = Thread; /* * If executing a method, the starting SyncLevel is this method's * SyncLevel */ if (WalkState->MethodDesc) { WalkState->Thread->CurrentSyncLevel = WalkState->MethodDesc->Method.SyncLevel; } AcpiDsPushWalkState (WalkState, Thread); /* * This global allows the AML debugger to get a handle to the currently * executing control method. */ AcpiGbl_CurrentWalkList = Thread; /* * Execute the walk loop as long as there is a valid Walk State. This * handles nested control method invocations without recursion. */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState)); Status = AE_OK; while (WalkState) { if (ACPI_SUCCESS (Status)) { /* * The ParseLoop executes AML until the method terminates * or calls another method. */ Status = AcpiPsParseLoop (WalkState); } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Completed one call to walk loop, %s State=%p\n", AcpiFormatException (Status), WalkState)); if (Status == AE_CTRL_TRANSFER) { /* * A method call was detected. * Transfer control to the called control method */ Status = AcpiDsCallControlMethod (Thread, WalkState, NULL); if (ACPI_FAILURE (Status)) { Status = AcpiDsMethodError (Status, WalkState); } /* * If the transfer to the new method method call worked, a new walk * state was created -- get it */ WalkState = AcpiDsGetCurrentWalkState (Thread); continue; } else if (Status == AE_CTRL_TERMINATE) { Status = AE_OK; } else if ((Status != AE_OK) && (WalkState->MethodDesc)) { /* Either the method parse or actual execution failed */ ACPI_ERROR_METHOD ("Method parse/execution failed", WalkState->MethodNode, NULL, Status); /* Check for possible multi-thread reentrancy problem */ if ((Status == AE_ALREADY_EXISTS) && (!(WalkState->MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED))) { /* * Method is not serialized and tried to create an object * twice. The probable cause is that the method cannot * handle reentrancy. Mark as "pending serialized" now, and * then mark "serialized" when the last thread exits. */ WalkState->MethodDesc->Method.InfoFlags |= ACPI_METHOD_SERIALIZED_PENDING; } } /* We are done with this walk, move on to the parent if any */ WalkState = AcpiDsPopWalkState (Thread); /* Reset the current scope to the beginning of scope stack */ AcpiDsScopeStackClear (WalkState); /* * If we just returned from the execution of a control method or if we * encountered an error during the method parse phase, there's lots of * cleanup to do */ if (((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) || (ACPI_FAILURE (Status))) { AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); } /* Delete this walk state and all linked control states */ AcpiPsCleanupScope (&WalkState->ParserState); PreviousWalkState = WalkState; ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "ReturnValue=%p, ImplicitValue=%p State=%p\n", WalkState->ReturnDesc, WalkState->ImplicitReturnObj, WalkState)); /* Check if we have restarted a preempted walk */ WalkState = AcpiDsGetCurrentWalkState (Thread); if (WalkState) { if (ACPI_SUCCESS (Status)) { /* * There is another walk state, restart it. * If the method return value is not used by the parent, * The object is deleted */ if (!PreviousWalkState->ReturnDesc) { /* * In slack mode execution, if there is no return value * we should implicitly return zero (0) as a default value. */ if (AcpiGbl_EnableInterpreterSlack && !PreviousWalkState->ImplicitReturnObj) { PreviousWalkState->ImplicitReturnObj = AcpiUtCreateIntegerObject ((UINT64) 0); if (!PreviousWalkState->ImplicitReturnObj) { return_ACPI_STATUS (AE_NO_MEMORY); } } /* Restart the calling control method */ Status = AcpiDsRestartControlMethod (WalkState, PreviousWalkState->ImplicitReturnObj); } else { /* * We have a valid return value, delete any implicit * return value. */ AcpiDsClearImplicitReturn (PreviousWalkState); Status = AcpiDsRestartControlMethod (WalkState, PreviousWalkState->ReturnDesc); } if (ACPI_SUCCESS (Status)) { WalkState->WalkType |= ACPI_WALK_METHOD_RESTART; } } else { /* On error, delete any return object or implicit return */ AcpiUtRemoveReference (PreviousWalkState->ReturnDesc); AcpiDsClearImplicitReturn (PreviousWalkState); } } /* * Just completed a 1st-level method, save the final internal return * value (if any) */ else if (PreviousWalkState->CallerReturnDesc) { if (PreviousWalkState->ImplicitReturnObj) { *(PreviousWalkState->CallerReturnDesc) = PreviousWalkState->ImplicitReturnObj; } else { /* NULL if no return value */ *(PreviousWalkState->CallerReturnDesc) = PreviousWalkState->ReturnDesc; } } else { if (PreviousWalkState->ReturnDesc) { /* Caller doesn't want it, must delete it */ AcpiUtRemoveReference (PreviousWalkState->ReturnDesc); } if (PreviousWalkState->ImplicitReturnObj) { /* Caller doesn't want it, must delete it */ AcpiUtRemoveReference (PreviousWalkState->ImplicitReturnObj); } } AcpiDsDeleteWalkState (PreviousWalkState); } /* Normal exit */ AcpiExReleaseAllMutexes (Thread); AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread)); AcpiGbl_CurrentWalkList = PrevWalkList; return_ACPI_STATUS (Status); }
void AcpiDsDeleteWalkState ( ACPI_WALK_STATE *WalkState) { ACPI_GENERIC_STATE *State; ACPI_FUNCTION_TRACE_PTR (DsDeleteWalkState, WalkState); if (!WalkState) { return; } if (WalkState->DescriptorType != ACPI_DESC_TYPE_WALK) { ACPI_ERROR ((AE_INFO, "%p is not a valid walk state", WalkState)); return; } /* There should not be any open scopes */ if (WalkState->ParserState.Scope) { ACPI_ERROR ((AE_INFO, "%p walk still has a scope list", WalkState)); AcpiPsCleanupScope (&WalkState->ParserState); } /* Always must free any linked control states */ while (WalkState->ControlState) { State = WalkState->ControlState; WalkState->ControlState = State->Common.Next; AcpiUtDeleteGenericState (State); } /* Always must free any linked parse states */ while (WalkState->ScopeInfo) { State = WalkState->ScopeInfo; WalkState->ScopeInfo = State->Common.Next; AcpiUtDeleteGenericState (State); } /* Always must free any stacked result states */ while (WalkState->Results) { State = WalkState->Results; WalkState->Results = State->Common.Next; AcpiUtDeleteGenericState (State); } ACPI_FREE (WalkState); return_VOID; }
ACPI_STATUS AcpiDsExecEndControlOp ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status = AE_OK; ACPI_GENERIC_STATE *ControlState; ACPI_FUNCTION_NAME (DsExecEndControlOp); switch (Op->Common.AmlOpcode) { case AML_IF_OP: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", Op)); /* * Save the result of the predicate in case there is an * ELSE to come */ WalkState->LastPredicate = (BOOLEAN) WalkState->ControlState->Common.Value; /* * Pop the control state that was created at the start * of the IF and free it */ ControlState = AcpiUtPopGenericState (&WalkState->ControlState); AcpiUtDeleteGenericState (ControlState); break; case AML_ELSE_OP: break; case AML_WHILE_OP: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", Op)); ControlState = WalkState->ControlState; if (ControlState->Common.Value) { /* Predicate was true, the body of the loop was just executed */ /* * This infinite loop detection mechanism allows the interpreter * to escape possibly infinite loops. This can occur in poorly * written AML when the hardware does not respond within a while * loop and the loop does not implement a timeout. */ if (ACPI_TIME_AFTER (AcpiOsGetTimer (), ControlState->Control.LoopTimeout)) { Status = AE_AML_LOOP_TIMEOUT; break; } /* * Go back and evaluate the predicate and maybe execute the loop * another time */ Status = AE_CTRL_PENDING; WalkState->AmlLastWhile = ControlState->Control.AmlPredicateStart; break; } /* Predicate was false, terminate this while loop */ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] termination! Op=%p\n",Op)); /* Pop this control state and free it */ ControlState = AcpiUtPopGenericState (&WalkState->ControlState); AcpiUtDeleteGenericState (ControlState); break; case AML_RETURN_OP: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[RETURN_OP] Op=%p Arg=%p\n",Op, Op->Common.Value.Arg)); /* * One optional operand -- the return value * It can be either an immediate operand or a result that * has been bubbled up the tree */ if (Op->Common.Value.Arg) { /* Since we have a real Return(), delete any implicit return */ AcpiDsClearImplicitReturn (WalkState); /* Return statement has an immediate operand */ Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg); if (ACPI_FAILURE (Status)) { return (Status); } /* * If value being returned is a Reference (such as * an arg or local), resolve it now because it may * cease to exist at the end of the method. */ Status = AcpiExResolveToValue ( &WalkState->Operands [0], WalkState); if (ACPI_FAILURE (Status)) { return (Status); } /* * Get the return value and save as the last result * value. This is the only place where WalkState->ReturnDesc * is set to anything other than zero! */ WalkState->ReturnDesc = WalkState->Operands[0]; } else if (WalkState->ResultCount) { /* Since we have a real Return(), delete any implicit return */ AcpiDsClearImplicitReturn (WalkState); /* * The return value has come from a previous calculation. * * If value being returned is a Reference (such as * an arg or local), resolve it now because it may * cease to exist at the end of the method. * * Allow references created by the Index operator to return * unchanged. */ if ((ACPI_GET_DESCRIPTOR_TYPE (WalkState->Results->Results.ObjDesc[0]) == ACPI_DESC_TYPE_OPERAND) && ((WalkState->Results->Results.ObjDesc [0])->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && ((WalkState->Results->Results.ObjDesc [0])->Reference.Class != ACPI_REFCLASS_INDEX)) { Status = AcpiExResolveToValue ( &WalkState->Results->Results.ObjDesc [0], WalkState); if (ACPI_FAILURE (Status)) { return (Status); } } WalkState->ReturnDesc = WalkState->Results->Results.ObjDesc [0]; } else { /* No return operand */ if (WalkState->NumOperands) { AcpiUtRemoveReference (WalkState->Operands [0]); } WalkState->Operands[0] = NULL; WalkState->NumOperands = 0; WalkState->ReturnDesc = NULL; } ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Completed RETURN_OP State=%p, RetVal=%p\n", WalkState, WalkState->ReturnDesc)); /* End the control method execution right now */ Status = AE_CTRL_TERMINATE; break; case AML_NOOP_OP: /* Just do nothing! */ break; case AML_BREAKPOINT_OP: AcpiDbSignalBreakPoint (WalkState); /* Call to the OSL in case OS wants a piece of the action */ Status = AcpiOsSignal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode"); break; case AML_BREAK_OP: case AML_CONTINUE_OP: /* ACPI 2.0 */ /* Pop and delete control states until we find a while */ while (WalkState->ControlState && (WalkState->ControlState->Control.Opcode != AML_WHILE_OP)) { ControlState = AcpiUtPopGenericState (&WalkState->ControlState); AcpiUtDeleteGenericState (ControlState); } /* No while found? */ if (!WalkState->ControlState) { return (AE_AML_NO_WHILE); } /* Was: WalkState->AmlLastWhile = WalkState->ControlState->Control.AmlPredicateStart; */ WalkState->AmlLastWhile = WalkState->ControlState->Control.PackageEnd; /* Return status depending on opcode */ if (Op->Common.AmlOpcode == AML_BREAK_OP) { Status = AE_CTRL_BREAK; } else { Status = AE_CTRL_CONTINUE; } break; default: ACPI_ERROR ((AE_INFO, "Unknown control opcode=0x%X Op=%p", Op->Common.AmlOpcode, Op)); Status = AE_AML_BAD_OPCODE; break; } return (Status); }
ACPI_STATUS AcpiUtWalkPackageTree ( ACPI_OPERAND_OBJECT *SourceObject, void *TargetObject, ACPI_PKG_CALLBACK WalkCallback, void *Context) { ACPI_STATUS Status = AE_OK; ACPI_GENERIC_STATE *StateList = NULL; ACPI_GENERIC_STATE *State; UINT32 ThisIndex; ACPI_OPERAND_OBJECT *ThisSourceObj; ACPI_FUNCTION_TRACE (UtWalkPackageTree); State = AcpiUtCreatePkgState (SourceObject, TargetObject, 0); if (!State) { return_ACPI_STATUS (AE_NO_MEMORY); } while (State) { /* Get one element of the package */ ThisIndex = State->Pkg.Index; ThisSourceObj = (ACPI_OPERAND_OBJECT *) State->Pkg.SourceObject->Package.Elements[ThisIndex]; /* * Check for: * 1) An uninitialized package element. It is completely * legal to declare a package and leave it uninitialized * 2) Not an internal object - can be a namespace node instead * 3) Any type other than a package. Packages are handled in else * case below. */ if ((!ThisSourceObj) || (ACPI_GET_DESCRIPTOR_TYPE (ThisSourceObj) != ACPI_DESC_TYPE_OPERAND) || (ThisSourceObj->Common.Type != ACPI_TYPE_PACKAGE)) { Status = WalkCallback (ACPI_COPY_TYPE_SIMPLE, ThisSourceObj, State, Context); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } State->Pkg.Index++; while (State->Pkg.Index >= State->Pkg.SourceObject->Package.Count) { /* * We've handled all of the objects at this level, This means * that we have just completed a package. That package may * have contained one or more packages itself. * * Delete this state and pop the previous state (package). */ AcpiUtDeleteGenericState (State); State = AcpiUtPopGenericState (&StateList); /* Finished when there are no more states */ if (!State) { /* * We have handled all of the objects in the top level * package just add the length of the package objects * and exit */ return_ACPI_STATUS (AE_OK); } /* * Go back up a level and move the index past the just * completed package object. */ State->Pkg.Index++; } } else { /* This is a subobject of type package */ Status = WalkCallback (ACPI_COPY_TYPE_PACKAGE, ThisSourceObj, State, Context); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Push the current state and create a new one * The callback above returned a new target package object. */ AcpiUtPushGenericState (&StateList, State); State = AcpiUtCreatePkgState (ThisSourceObj, State->Pkg.ThisTargetObj, 0); if (!State) { /* Free any stacked Update State objects */ while (StateList) { State = AcpiUtPopGenericState (&StateList); AcpiUtDeleteGenericState (State); } return_ACPI_STATUS (AE_NO_MEMORY); } } } /* We should never get here */ return_ACPI_STATUS (AE_AML_INTERNAL); }
ACPI_STATUS AcpiUtUpdateObjectReference ( ACPI_OPERAND_OBJECT *Object, UINT16 Action) { ACPI_STATUS Status = AE_OK; ACPI_GENERIC_STATE *StateList = NULL; ACPI_OPERAND_OBJECT *NextObject = NULL; ACPI_GENERIC_STATE *State; UINT32 i; ACPI_FUNCTION_TRACE_PTR (UtUpdateObjectReference, Object); while (Object) { /* Make sure that this isn't a namespace handle */ if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", Object)); return_ACPI_STATUS (AE_OK); } /* * All sub-objects must have their reference count incremented also. * Different object types have different subobjects. */ switch (Object->Common.Type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: case ACPI_TYPE_THERMAL: /* Update the notify objects for these types (if present) */ AcpiUtUpdateRefCount (Object->CommonNotify.SystemNotify, Action); AcpiUtUpdateRefCount (Object->CommonNotify.DeviceNotify, Action); break; case ACPI_TYPE_PACKAGE: /* * We must update all the sub-objects of the package, * each of whom may have their own sub-objects. */ for (i = 0; i < Object->Package.Count; i++) { /* * Push each element onto the stack for later processing. * Note: There can be null elements within the package, * these are simply ignored */ Status = AcpiUtCreateUpdateStateAndPush ( Object->Package.Elements[i], Action, &StateList); if (ACPI_FAILURE (Status)) { goto ErrorExit; } } break; case ACPI_TYPE_BUFFER_FIELD: NextObject = Object->BufferField.BufferObj; break; case ACPI_TYPE_LOCAL_REGION_FIELD: NextObject = Object->Field.RegionObj; break; case ACPI_TYPE_LOCAL_BANK_FIELD: NextObject = Object->BankField.BankObj; Status = AcpiUtCreateUpdateStateAndPush ( Object->BankField.RegionObj, Action, &StateList); if (ACPI_FAILURE (Status)) { goto ErrorExit; } break; case ACPI_TYPE_LOCAL_INDEX_FIELD: NextObject = Object->IndexField.IndexObj; Status = AcpiUtCreateUpdateStateAndPush ( Object->IndexField.DataObj, Action, &StateList); if (ACPI_FAILURE (Status)) { goto ErrorExit; } break; case ACPI_TYPE_LOCAL_REFERENCE: /* * The target of an Index (a package, string, or buffer) or a named * reference must track changes to the ref count of the index or * target object. */ if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) || (Object->Reference.Class== ACPI_REFCLASS_NAME)) { NextObject = Object->Reference.Object; } break; case ACPI_TYPE_REGION: default: break; /* No subobjects for all other types */ } /* * Now we can update the count in the main object. This can only * happen after we update the sub-objects in case this causes the * main object to be deleted. */ AcpiUtUpdateRefCount (Object, Action); Object = NULL; /* Move on to the next object to be updated */ if (NextObject) { Object = NextObject; NextObject = NULL; } else if (StateList) { State = AcpiUtPopGenericState (&StateList); Object = State->Update.Object; AcpiUtDeleteGenericState (State); } } return_ACPI_STATUS (AE_OK); ErrorExit: ACPI_EXCEPTION ((AE_INFO, Status, "Could not update object reference count")); /* Free any stacked Update State objects */ while (StateList) { State = AcpiUtPopGenericState (&StateList); AcpiUtDeleteGenericState (State); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiEvQueueNotifyRequest ( ACPI_NAMESPACE_NODE *Node, UINT32 NotifyValue) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerObj = NULL; ACPI_GENERIC_STATE *NotifyInfo; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_NAME (EvQueueNotifyRequest); /* * For value 3 (Ejection Request), some device method may need to be run. * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need * to be run. * For value 0x80 (Status Change) on the power button or sleep button, * initiate soft-off or sleep operation? */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", AcpiUtGetNodeName (Node), Node, NotifyValue, AcpiUtGetNotifyName (NotifyValue))); /* Get the notify object attached to the NS Node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* We have the notify object, Get the right handler */ switch (Node->Type) { /* Notify allowed only on these types */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: case ACPI_TYPE_PROCESSOR: if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) { HandlerObj = ObjDesc->CommonNotify.SystemNotify; } else { HandlerObj = ObjDesc->CommonNotify.DeviceNotify; } break; default: /* All other types are not supported */ return (AE_TYPE); } } /* * If there is any handler to run, schedule the dispatcher. * Check for: * 1) Global system notify handler * 2) Global device notify handler * 3) Per-device notify handler */ if ((AcpiGbl_SystemNotify.Handler && (NotifyValue <= ACPI_MAX_SYS_NOTIFY)) || (AcpiGbl_DeviceNotify.Handler && (NotifyValue > ACPI_MAX_SYS_NOTIFY)) || HandlerObj) { NotifyInfo = AcpiUtCreateGenericState (); if (!NotifyInfo) { return (AE_NO_MEMORY); } if (!HandlerObj) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Executing system notify handler for Notify (%4.4s, %X) " "node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); } NotifyInfo->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; NotifyInfo->Notify.Node = Node; NotifyInfo->Notify.Value = (UINT16) NotifyValue; NotifyInfo->Notify.HandlerObj = HandlerObj; Status = AcpiOsExecute ( OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, NotifyInfo); if (ACPI_FAILURE (Status)) { AcpiUtDeleteGenericState (NotifyInfo); } } else { /* There is no notify handler (per-device or system) for this device */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for Notify (%4.4s, %X) node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); } return (Status); }
ACPI_STATUS AcpiUtUpdateObjectReference ( ACPI_OPERAND_OBJECT *Object, UINT16 Action) { ACPI_STATUS Status = AE_OK; ACPI_GENERIC_STATE *StateList = NULL; ACPI_OPERAND_OBJECT *NextObject = NULL; ACPI_OPERAND_OBJECT *PrevObject; ACPI_GENERIC_STATE *State; UINT32 i; ACPI_FUNCTION_NAME (UtUpdateObjectReference); while (Object) { /* Make sure that this isn't a namespace handle */ if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", Object)); return (AE_OK); } /* * All sub-objects must have their reference count incremented also. * Different object types have different subobjects. */ switch (Object->Common.Type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: case ACPI_TYPE_THERMAL: /* * Update the notify objects for these types (if present) * Two lists, system and device notify handlers. */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { PrevObject = Object->CommonNotify.NotifyList[i]; while (PrevObject) { NextObject = PrevObject->Notify.Next[i]; AcpiUtUpdateRefCount (PrevObject, Action); PrevObject = NextObject; } } break; case ACPI_TYPE_PACKAGE: /* * We must update all the sub-objects of the package, * each of whom may have their own sub-objects. */ for (i = 0; i < Object->Package.Count; i++) { /* * Null package elements are legal and can be simply * ignored. */ NextObject = Object->Package.Elements[i]; if (!NextObject) { continue; } switch (NextObject->Common.Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * For these very simple sub-objects, we can just * update the reference count here and continue. * Greatly increases performance of this operation. */ AcpiUtUpdateRefCount (NextObject, Action); break; default: /* * For complex sub-objects, push them onto the stack * for later processing (this eliminates recursion.) */ Status = AcpiUtCreateUpdateStateAndPush ( NextObject, Action, &StateList); if (ACPI_FAILURE (Status)) { goto ErrorExit; } break; } } NextObject = NULL; break; case ACPI_TYPE_BUFFER_FIELD: NextObject = Object->BufferField.BufferObj; break; case ACPI_TYPE_LOCAL_REGION_FIELD: NextObject = Object->Field.RegionObj; break; case ACPI_TYPE_LOCAL_BANK_FIELD: NextObject = Object->BankField.BankObj; Status = AcpiUtCreateUpdateStateAndPush ( Object->BankField.RegionObj, Action, &StateList); if (ACPI_FAILURE (Status)) { goto ErrorExit; } break; case ACPI_TYPE_LOCAL_INDEX_FIELD: NextObject = Object->IndexField.IndexObj; Status = AcpiUtCreateUpdateStateAndPush ( Object->IndexField.DataObj, Action, &StateList); if (ACPI_FAILURE (Status)) { goto ErrorExit; } break; case ACPI_TYPE_LOCAL_REFERENCE: /* * The target of an Index (a package, string, or buffer) or a named * reference must track changes to the ref count of the index or * target object. */ if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) || (Object->Reference.Class== ACPI_REFCLASS_NAME)) { NextObject = Object->Reference.Object; } break; case ACPI_TYPE_REGION: default: break; /* No subobjects for all other types */ } /* * Now we can update the count in the main object. This can only * happen after we update the sub-objects in case this causes the * main object to be deleted. */ AcpiUtUpdateRefCount (Object, Action); Object = NULL; /* Move on to the next object to be updated */ if (NextObject) { Object = NextObject; NextObject = NULL; } else if (StateList) { State = AcpiUtPopGenericState (&StateList); Object = State->Update.Object; AcpiUtDeleteGenericState (State); } } return (AE_OK); ErrorExit: ACPI_EXCEPTION ((AE_INFO, Status, "Could not update object reference count")); /* Free any stacked Update State objects */ while (StateList) { State = AcpiUtPopGenericState (&StateList); AcpiUtDeleteGenericState (State); } return (Status); }
static ACPI_STATUS AcpiPsCompleteOp ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT **Op, ACPI_STATUS Status) { ACPI_STATUS Status2; ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState); /* * Finished one argument of the containing scope */ WalkState->ParserState.Scope->ParseScope.ArgCount--; /* Close this Op (will result in parse subtree deletion) */ Status2 = AcpiPsCompleteThisOp (WalkState, *Op); if (ACPI_FAILURE (Status2)) { return_ACPI_STATUS (Status2); } *Op = NULL; switch (Status) { case AE_OK: break; case AE_CTRL_TRANSFER: /* We are about to transfer to a called method */ WalkState->PrevOp = NULL; WalkState->PrevArgTypes = WalkState->ArgTypes; return_ACPI_STATUS (Status); case AE_CTRL_END: AcpiPsPopScope (&(WalkState->ParserState), Op, &WalkState->ArgTypes, &WalkState->ArgCount); if (*Op) { WalkState->Op = *Op; WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); WalkState->Opcode = (*Op)->Common.AmlOpcode; Status = WalkState->AscendingCallback (WalkState); Status = AcpiPsNextParseState (WalkState, *Op, Status); Status2 = AcpiPsCompleteThisOp (WalkState, *Op); if (ACPI_FAILURE (Status2)) { return_ACPI_STATUS (Status2); } } Status = AE_OK; break; case AE_CTRL_BREAK: case AE_CTRL_CONTINUE: /* Pop off scopes until we find the While */ while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP)) { AcpiPsPopScope (&(WalkState->ParserState), Op, &WalkState->ArgTypes, &WalkState->ArgCount); } /* Close this iteration of the While loop */ WalkState->Op = *Op; WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); WalkState->Opcode = (*Op)->Common.AmlOpcode; Status = WalkState->AscendingCallback (WalkState); Status = AcpiPsNextParseState (WalkState, *Op, Status); Status2 = AcpiPsCompleteThisOp (WalkState, *Op); if (ACPI_FAILURE (Status2)) { return_ACPI_STATUS (Status2); } Status = AE_OK; break; case AE_CTRL_TERMINATE: /* Clean up */ do { if (*Op) { Status2 = AcpiPsCompleteThisOp (WalkState, *Op); if (ACPI_FAILURE (Status2)) { return_ACPI_STATUS (Status2); } AcpiUtDeleteGenericState ( AcpiUtPopGenericState (&WalkState->ControlState)); } AcpiPsPopScope (&(WalkState->ParserState), Op, &WalkState->ArgTypes, &WalkState->ArgCount); } while (*Op); return_ACPI_STATUS (AE_OK); default: /* All other non-AE_OK status */ do { if (*Op) { Status2 = AcpiPsCompleteThisOp (WalkState, *Op); if (ACPI_FAILURE (Status2)) { return_ACPI_STATUS (Status2); } } AcpiPsPopScope (&(WalkState->ParserState), Op, &WalkState->ArgTypes, &WalkState->ArgCount); } while (*Op); #if 0 /* * TBD: Cleanup parse ops on error */ if (*Op == NULL) { AcpiPsPopScope (ParserState, Op, &WalkState->ArgTypes, &WalkState->ArgCount); } #endif WalkState->PrevOp = NULL; WalkState->PrevArgTypes = WalkState->ArgTypes; return_ACPI_STATUS (Status); } /* This scope complete? */ if (AcpiPsHasCompletedScope (&(WalkState->ParserState))) { AcpiPsPopScope (&(WalkState->ParserState), Op, &WalkState->ArgTypes, &WalkState->ArgCount); ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op)); } else { *Op = NULL; } return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiDsExecEndControlOp ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status = AE_OK; ACPI_GENERIC_STATE *ControlState; ACPI_FUNCTION_NAME ("DsExecEndControlOp"); switch (Op->Common.AmlOpcode) { case AML_IF_OP: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", Op)); /* * Save the result of the predicate in case there is an * ELSE to come */ WalkState->LastPredicate = (BOOLEAN) WalkState->ControlState->Common.Value; /* * Pop the control state that was created at the start * of the IF and free it */ ControlState = AcpiUtPopGenericState (&WalkState->ControlState); AcpiUtDeleteGenericState (ControlState); break; case AML_ELSE_OP: break; case AML_WHILE_OP: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", Op)); if (WalkState->ControlState->Common.Value) { /* Predicate was true, go back and evaluate it again! */ Status = AE_CTRL_PENDING; } ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] termination! Op=%p\n", Op)); /* Pop this control state and free it */ ControlState = AcpiUtPopGenericState (&WalkState->ControlState); WalkState->AmlLastWhile = ControlState->Control.AmlPredicateStart; AcpiUtDeleteGenericState (ControlState); break; case AML_RETURN_OP: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[RETURN_OP] Op=%p Arg=%p\n",Op, Op->Common.Value.Arg)); /* * One optional operand -- the return value * It can be either an immediate operand or a result that * has been bubbled up the tree */ if (Op->Common.Value.Arg) { /* Return statement has an immediate operand */ Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg); if (ACPI_FAILURE (Status)) { return (Status); } /* * If value being returned is a Reference (such as * an arg or local), resolve it now because it may * cease to exist at the end of the method. */ Status = AcpiExResolveToValue (&WalkState->Operands [0], WalkState); if (ACPI_FAILURE (Status)) { return (Status); } /* * Get the return value and save as the last result * value. This is the only place where WalkState->ReturnDesc * is set to anything other than zero! */ WalkState->ReturnDesc = WalkState->Operands[0]; } else if ((WalkState->Results) && (WalkState->Results->Results.NumResults > 0)) { /* * The return value has come from a previous calculation. * * If value being returned is a Reference (such as * an arg or local), resolve it now because it may * cease to exist at the end of the method. * * Allow references created by the Index operator to return unchanged. */ if ((ACPI_GET_DESCRIPTOR_TYPE (WalkState->Results->Results.ObjDesc[0]) == ACPI_DESC_TYPE_OPERAND) && (ACPI_GET_OBJECT_TYPE (WalkState->Results->Results.ObjDesc [0]) == ACPI_TYPE_LOCAL_REFERENCE) && ((WalkState->Results->Results.ObjDesc [0])->Reference.Opcode != AML_INDEX_OP)) { Status = AcpiExResolveToValue (&WalkState->Results->Results.ObjDesc [0], WalkState); if (ACPI_FAILURE (Status)) { return (Status); } } WalkState->ReturnDesc = WalkState->Results->Results.ObjDesc [0]; } else { /* No return operand */ if (WalkState->NumOperands) { AcpiUtRemoveReference (WalkState->Operands [0]); } WalkState->Operands [0] = NULL; WalkState->NumOperands = 0; WalkState->ReturnDesc = NULL; } ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Completed RETURN_OP State=%p, RetVal=%p\n", WalkState, WalkState->ReturnDesc)); /* End the control method execution right now */ Status = AE_CTRL_TERMINATE; break; case AML_NOOP_OP: /* Just do nothing! */ break; case AML_BREAK_POINT_OP: /* Call up to the OS service layer to handle this */ Status = AcpiOsSignal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode"); /* If and when it returns, all done. */ break; case AML_BREAK_OP: case AML_CONTINUE_OP: /* ACPI 2.0 */ /* Pop and delete control states until we find a while */ while (WalkState->ControlState && (WalkState->ControlState->Control.Opcode != AML_WHILE_OP)) { ControlState = AcpiUtPopGenericState (&WalkState->ControlState); AcpiUtDeleteGenericState (ControlState); } /* No while found? */ if (!WalkState->ControlState) { return (AE_AML_NO_WHILE); } /* Was: WalkState->AmlLastWhile = WalkState->ControlState->Control.AmlPredicateStart; */ WalkState->AmlLastWhile = WalkState->ControlState->Control.PackageEnd; /* Return status depending on opcode */ if (Op->Common.AmlOpcode == AML_BREAK_OP) { Status = AE_CTRL_BREAK; } else { Status = AE_CTRL_CONTINUE; } break; default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown control opcode=%X Op=%p\n", Op->Common.AmlOpcode, Op)); Status = AE_AML_BAD_OPCODE; break; } return (Status); }