void AcpiNsDeleteNode ( ACPI_NAMESPACE_NODE *Node) { ACPI_NAMESPACE_NODE *ParentNode; ACPI_NAMESPACE_NODE *PrevNode; ACPI_NAMESPACE_NODE *NextNode; ACPI_FUNCTION_TRACE_PTR (NsDeleteNode, Node); ParentNode = AcpiNsGetParentNode (Node); PrevNode = NULL; NextNode = ParentNode->Child; /* Find the node that is the previous peer in the parent's child list */ while (NextNode != Node) { PrevNode = NextNode; NextNode = PrevNode->Peer; } if (PrevNode) { /* Node is not first child, unlink it */ PrevNode->Peer = NextNode->Peer; if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST) { PrevNode->Flags |= ANOBJ_END_OF_PEER_LIST; } } else { /* Node is first child (has no previous peer) */ if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST) { /* No peers at all */ ParentNode->Child = NULL; } else { /* Link peer list to parent */ ParentNode->Child = NextNode->Peer; } } ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++); /* Detach an object if there is one, then delete the node */ AcpiNsDetachObject (Node); (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, Node); return_VOID; }
void AcpiNsTerminate ( void) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_TRACE (NsTerminate); /* * 1) Free the entire namespace -- all nodes and objects * * Delete all object descriptors attached to namepsace nodes */ AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); /* Detach any objects attached to the root */ ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode); if (ObjDesc) { AcpiNsDetachObject (AcpiGbl_RootNode); } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); return_VOID; }
void AcpiDsMethodDataDeleteAll ( ACPI_WALK_STATE *WalkState) { UINT32 Index; ACPI_FUNCTION_TRACE (DsMethodDataDeleteAll); /* Detach the locals */ for (Index = 0; Index < ACPI_METHOD_NUM_LOCALS; Index++) { if (WalkState->LocalVariables[Index].Object) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Local%d=%p\n", Index, WalkState->LocalVariables[Index].Object)); /* Detach object (if present) and remove a reference */ AcpiNsDetachObject (&WalkState->LocalVariables[Index]); } } /* Detach the arguments */ for (Index = 0; Index < ACPI_METHOD_NUM_ARGS; Index++) { if (WalkState->Arguments[Index].Object) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Arg%d=%p\n", Index, WalkState->Arguments[Index].Object)); /* Detach object (if present) and remove a reference */ AcpiNsDetachObject (&WalkState->Arguments[Index]); } } #if 0 AcpiDsClearImplicitReturn (WalkState); #endif return_VOID; }
void AcpiNsDeleteNode ( ACPI_NAMESPACE_NODE *Node) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *NextDesc; ACPI_FUNCTION_NAME (NsDeleteNode); /* Detach an object if there is one */ AcpiNsDetachObject (Node); /* * Delete an attached data object list if present (objects that were * attached via AcpiAttachData). Note: After any normal object is * detached above, the only possible remaining object(s) are data * objects, in a linked list. */ ObjDesc = Node->Object; while (ObjDesc && (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA)) { /* Invoke the attached data deletion handler if present */ if (ObjDesc->Data.Handler) { ObjDesc->Data.Handler (Node, ObjDesc->Data.Pointer); } NextDesc = ObjDesc->Common.NextObject; AcpiUtRemoveReference (ObjDesc); ObjDesc = NextDesc; } /* Special case for the statically allocated root node */ if (Node == AcpiGbl_RootNode) { return; } /* Now we can delete the node */ (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, Node); ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++); ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n", Node, AcpiGbl_CurrentNodeCount)); }
void AcpiNsDeleteNode ( ACPI_NAMESPACE_NODE *Node) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_NAME (NsDeleteNode); /* Detach an object if there is one */ AcpiNsDetachObject (Node); /* * Delete an attached data object if present (an object that was created * and attached via AcpiAttachData). Note: After any normal object is * detached above, the only possible remaining object is a data object. */ ObjDesc = Node->Object; if (ObjDesc && (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA)) { /* Invoke the attached data deletion handler if present */ if (ObjDesc->Data.Handler) { ObjDesc->Data.Handler (Node, ObjDesc->Data.Pointer); } AcpiUtRemoveReference (ObjDesc); } /* Now we can delete the node */ (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, Node); ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++); ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n", Node, AcpiGbl_CurrentNodeCount)); }
void AcpiNsDeleteNamespaceByOwner ( ACPI_OWNER_ID OwnerId) { ACPI_NAMESPACE_NODE *ChildNode; ACPI_NAMESPACE_NODE *DeletionNode; ACPI_NAMESPACE_NODE *ParentNode; UINT32 Level; ACPI_STATUS Status; ACPI_FUNCTION_TRACE_U32 (NsDeleteNamespaceByOwner, OwnerId); if (OwnerId == 0) { return_VOID; } /* Lock namespace for possible update */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_VOID; } DeletionNode = NULL; ParentNode = AcpiGbl_RootNode; ChildNode = NULL; Level = 1; /* * Traverse the tree of nodes until we bubble back up * to where we started. */ while (Level > 0) { /* * Get the next child of this parent node. When ChildNode is NULL, * the first child of the parent is returned */ ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); if (DeletionNode) { AcpiNsDeleteChildren (DeletionNode); AcpiNsRemoveNode (DeletionNode); DeletionNode = NULL; } if (ChildNode) { if (ChildNode->OwnerId == OwnerId) { /* Found a matching child node - detach any attached object */ AcpiNsDetachObject (ChildNode); } /* Check if this node has any children */ if (ChildNode->Child) { /* * There is at least one child of this node, * visit the node */ Level++; ParentNode = ChildNode; ChildNode = NULL; } else if (ChildNode->OwnerId == OwnerId) { DeletionNode = ChildNode; } } else { /* * No more children of this parent node. * Move up to the grandparent. */ Level--; if (Level != 0) { if (ParentNode->OwnerId == OwnerId) { DeletionNode = ParentNode; } } /* New "last child" is this parent node */ ChildNode = ParentNode; /* Move up the tree to the grandparent */ ParentNode = ParentNode->Parent; } } (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_VOID; }
void AcpiNsDeleteNamespaceSubtree ( ACPI_NAMESPACE_NODE *ParentNode) { ACPI_NAMESPACE_NODE *ChildNode = NULL; UINT32 Level = 1; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree); if (!ParentNode) { return_VOID; } /* Lock namespace for possible update */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_VOID; } /* * Traverse the tree of objects until we bubble back up * to where we started. */ while (Level > 0) { /* Get the next node in this scope (NULL if none) */ ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); if (ChildNode) { /* Found a child node - detach any attached object */ AcpiNsDetachObject (ChildNode); /* Check if this node has any children */ if (ChildNode->Child) { /* * There is at least one child of this node, * visit the node */ Level++; ParentNode = ChildNode; ChildNode = NULL; } } else { /* * No more children of this parent node. * Move up to the grandparent. */ Level--; /* * Now delete all of the children of this parent * all at the same time. */ AcpiNsDeleteChildren (ParentNode); /* New "last child" is this parent node */ ChildNode = ParentNode; /* Move up the tree to the grandparent */ ParentNode = ParentNode->Parent; } } (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_VOID; }
void AcpiNsDeleteNamespaceSubtree ( ACPI_NAMESPACE_NODE *ParentNode) { ACPI_NAMESPACE_NODE *ChildNode = NULL; UINT32 Level = 1; ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree); if (!ParentNode) { return_VOID; } /* * Traverse the tree of objects until we bubble back up * to where we started. */ while (Level > 0) { /* Get the next node in this scope (NULL if none) */ ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode, ChildNode); if (ChildNode) { /* Found a child node - detach any attached object */ AcpiNsDetachObject (ChildNode); /* Check if this node has any children */ if (AcpiNsGetNextNode (ACPI_TYPE_ANY, ChildNode, NULL)) { /* * There is at least one child of this node, * visit the node */ Level++; ParentNode = ChildNode; ChildNode = NULL; } } else { /* * No more children of this parent node. * Move up to the grandparent. */ Level--; /* * Now delete all of the children of this parent * all at the same time. */ AcpiNsDeleteChildren (ParentNode); /* New "last child" is this parent node */ ChildNode = ParentNode; /* Move up the tree to the grandparent */ ParentNode = AcpiNsGetParentNode (ParentNode); } } return_VOID; }
void AcpiNsDeleteChildren ( ACPI_NAMESPACE_NODE *ParentNode) { ACPI_NAMESPACE_NODE *ChildNode; ACPI_NAMESPACE_NODE *NextNode; UINT8 Flags; ACPI_FUNCTION_TRACE_PTR (NsDeleteChildren, ParentNode); if (!ParentNode) { return_VOID; } /* If no children, all done! */ ChildNode = ParentNode->Child; if (!ChildNode) { return_VOID; } /* * Deallocate all children at this level */ do { /* Get the things we need */ NextNode = ChildNode->Peer; Flags = ChildNode->Flags; /* Grandchildren should have all been deleted already */ if (ChildNode->Child) { ACPI_ERROR ((AE_INFO, "Found a grandchild! P=%p C=%p", ParentNode, ChildNode)); } /* Now we can free this child object */ ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++); ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p, Remaining %X\n", ChildNode, AcpiGbl_CurrentNodeCount)); /* * Detach an object if there is one, then free the child node */ AcpiNsDetachObject (ChildNode); /* Now we can delete the node */ (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, ChildNode); /* And move on to the next child in the list */ ChildNode = NextNode; } while (!(Flags & ANOBJ_END_OF_PEER_LIST)); /* Clear the parent's child pointer */ ParentNode->Child = NULL; return_VOID; }
ACPI_STATUS AcpiNsAttachObject ( ACPI_NAMESPACE_NODE *Node, ACPI_OPERAND_OBJECT *Object, ACPI_OBJECT_TYPE Type) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *LastObjDesc; ACPI_OBJECT_TYPE ObjectType = ACPI_TYPE_ANY; ACPI_FUNCTION_TRACE (NsAttachObject); /* * Parameter validation */ if (!Node) { /* Invalid handle */ ACPI_ERROR ((AE_INFO, "Null NamedObj handle")); return_ACPI_STATUS (AE_BAD_PARAMETER); } if (!Object && (ACPI_TYPE_ANY != Type)) { /* Null object */ ACPI_ERROR ((AE_INFO, "Null object, but type not ACPI_TYPE_ANY")); return_ACPI_STATUS (AE_BAD_PARAMETER); } if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) { /* Not a name handle */ ACPI_ERROR ((AE_INFO, "Invalid handle %p [%s]", Node, AcpiUtGetDescriptorName (Node))); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Check if this object is already attached */ if (Node->Object == Object) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj %p already installed in NameObj %p\n", Object, Node)); return_ACPI_STATUS (AE_OK); } /* If null object, we will just install it */ if (!Object) { ObjDesc = NULL; ObjectType = ACPI_TYPE_ANY; } /* * If the source object is a namespace Node with an attached object, * we will use that (attached) object */ else if ((ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) && ((ACPI_NAMESPACE_NODE *) Object)->Object) { /* * Value passed is a name handle and that name has a * non-null value. Use that name's value and type. */ ObjDesc = ((ACPI_NAMESPACE_NODE *) Object)->Object; ObjectType = ((ACPI_NAMESPACE_NODE *) Object)->Type; } /* * Otherwise, we will use the parameter object, but we must type * it first */ else { ObjDesc = (ACPI_OPERAND_OBJECT *) Object; /* Use the given type */ ObjectType = Type; } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n", ObjDesc, Node, AcpiUtGetNodeName (Node))); /* Detach an existing attached object if present */ if (Node->Object) { AcpiNsDetachObject (Node); } if (ObjDesc) { /* * Must increment the new value's reference count * (if it is an internal object) */ AcpiUtAddReference (ObjDesc); /* * Handle objects with multiple descriptors - walk * to the end of the descriptor list */ LastObjDesc = ObjDesc; while (LastObjDesc->Common.NextObject) { LastObjDesc = LastObjDesc->Common.NextObject; } /* Install the object at the front of the object list */ LastObjDesc->Common.NextObject = Node->Object; } Node->Type = (UINT8) ObjectType; Node->Object = ObjDesc; return_ACPI_STATUS (AE_OK); }
static void AcpiNsExecModuleCode ( ACPI_OPERAND_OBJECT *MethodObj, ACPI_EVALUATE_INFO *Info) { ACPI_OPERAND_OBJECT *ParentObj; ACPI_NAMESPACE_NODE *ParentNode; ACPI_OBJECT_TYPE Type; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (NsExecModuleCode); /* * Get the parent node. We cheat by using the NextObject field * of the method object descriptor. */ ParentNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, MethodObj->Method.NextObject); Type = AcpiNsGetType (ParentNode); /* * Get the region handler and save it in the method object. We may need * this if an operation region declaration causes a _REG method to be run. * * We can't do this in AcpiPsLinkModuleCode because * AcpiGbl_RootNode->Object is NULL at PASS1. */ if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object) { MethodObj->Method.Dispatch.Handler = ParentNode->Object->Device.Handler; } /* Must clear NextObject (AcpiNsAttachObject needs the field) */ MethodObj->Method.NextObject = NULL; /* Initialize the evaluation information block */ ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO)); Info->PrefixNode = ParentNode; /* * Get the currently attached parent object. Add a reference, because the * ref count will be decreased when the method object is installed to * the parent node. */ ParentObj = AcpiNsGetAttachedObject (ParentNode); if (ParentObj) { AcpiUtAddReference (ParentObj); } /* Install the method (module-level code) in the parent node */ Status = AcpiNsAttachObject (ParentNode, MethodObj, ACPI_TYPE_METHOD); if (ACPI_FAILURE (Status)) { goto Exit; } /* Execute the parent node as a control method */ Status = AcpiNsEvaluate (Info); ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Executed module-level code at %p\n", MethodObj->Method.AmlStart)); /* Delete a possible implicit return value (in slack mode) */ if (Info->ReturnObject) { AcpiUtRemoveReference (Info->ReturnObject); } /* Detach the temporary method object */ AcpiNsDetachObject (ParentNode); /* Restore the original parent object */ if (ParentObj) { Status = AcpiNsAttachObject (ParentNode, ParentObj, Type); } else { ParentNode->Type = (UINT8) Type; } Exit: if (ParentObj) { AcpiUtRemoveReference (ParentObj); } return_VOID; }
ACPI_STATUS AcpiDsStoreObjectToLocal ( UINT16 Opcode, UINT32 Index, ACPI_OPERAND_OBJECT *SrcDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT **Entry; FUNCTION_TRACE ("DsMethodDataSetValue"); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode=%d Idx=%d Obj=%p\n", Opcode, Index, SrcDesc)); /* Parameter validation */ if (!SrcDesc) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Get a pointer to the requested method stack entry */ Status = AcpiDsMethodDataGetEntry (Opcode, Index, WalkState, &Entry); if (ACPI_FAILURE (Status)) { goto Cleanup; } if (*Entry == SrcDesc) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n", SrcDesc)); goto Cleanup; } /* * If there is an object already in this slot, we either * have to delete it, or if this is an argument and there * is an object reference stored there, we have to do * an indirect store! */ if (*Entry) { /* * Check for an indirect store if an argument * contains an object reference (stored as an Node). * We don't allow this automatic dereferencing for * locals, since a store to a local should overwrite * anything there, including an object reference. * * If both Arg0 and Local0 contain RefOf (Local4): * * Store (1, Arg0) - Causes indirect store to local4 * Store (1, Local0) - Stores 1 in local0, overwriting * the reference to local4 * Store (1, DeRefof (Local0)) - Causes indirect store to local4 * * Weird, but true. */ if ((Opcode == AML_ARG_OP) && (VALID_DESCRIPTOR_TYPE (*Entry, ACPI_DESC_TYPE_NAMED))) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Arg (%p) is an ObjRef(Node), storing in %p\n", SrcDesc, *Entry)); /* Detach an existing object from the Node */ AcpiNsDetachObject ((ACPI_NAMESPACE_NODE *) *Entry); /* * Store this object into the Node * (do the indirect store) */ Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) *Entry, SrcDesc, SrcDesc->Common.Type); return_ACPI_STATUS (Status); } #ifdef ACPI_ENABLE_IMPLICIT_CONVERSION /* * Perform "Implicit conversion" of the new object to the type of the * existing object */ Status = AcpiExConvertToTargetType ((*Entry)->Common.Type, &SrcDesc, WalkState); if (ACPI_FAILURE (Status)) { goto Cleanup; } #endif /* * Delete the existing object * before storing the new one */ AcpiDsMethodDataDeleteValue (Opcode, Index, WalkState); } /* * Install the ObjStack descriptor (*SrcDesc) into * the descriptor for the Arg or Local. * Install the new object in the stack entry * (increments the object reference count by one) */ Status = AcpiDsMethodDataSetEntry (Opcode, Index, SrcDesc, WalkState); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Normal exit */ return_ACPI_STATUS (AE_OK); /* Error exit */ Cleanup: return_ACPI_STATUS (Status); }