X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FIp4Dxe%2FIp4Driver.c;h=5a84837a444805a6b9e94ae68f269c6f838be67e;hp=4ce85a3f51823d86d2ac12d000b84d9c683b7d11;hb=216f79703b8cb8dc65abdd768bedb2bcdbc1a1f8;hpb=906e1cb7f7f178f5cb2a3bebbac59f6aa8c273a4 diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c index 4ce85a3f51..5a84837a44 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c @@ -176,7 +176,6 @@ Ip4CreateService ( IpSb->ServiceBinding.CreateChild = Ip4ServiceBindingCreateChild; IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild; IpSb->State = IP4_SERVICE_UNSTARTED; - IpSb->InDestroy = FALSE; IpSb->NumChildren = 0; InitializeListHead (&IpSb->Children); @@ -396,6 +395,42 @@ Ip4CleanService ( return EFI_SUCCESS; } +/** + Callback function which provided by user to remove one node in NetDestroyLinkList process. + + @param[in] Entry The entry to be removed. + @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList. + + @retval EFI_SUCCESS The entry has been removed successfully. + @retval Others Fail to remove the entry. + +**/ +EFI_STATUS +Ip4DestroyChildEntryInHandleBuffer ( + IN LIST_ENTRY *Entry, + IN VOID *Context +) +{ + IP4_PROTOCOL *IpInstance; + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; + UINTN NumberOfChildren; + EFI_HANDLE *ChildHandleBuffer; + + if (Entry == NULL || Context == NULL) { + return EFI_INVALID_PARAMETER; + } + + IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE); + ServiceBinding = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding; + NumberOfChildren = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren; + ChildHandleBuffer = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer; + + if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) { + return EFI_SUCCESS; + } + + return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle); +} /** Start this driver on ControllerHandle. This service is called by the @@ -529,14 +564,13 @@ Ip4DriverBindingStop ( IN EFI_HANDLE *ChildHandleBuffer ) { - EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; - IP4_SERVICE *IpSb; - IP4_PROTOCOL *IpInstance; - EFI_HANDLE NicHandle; - EFI_STATUS Status; - EFI_TPL OldTpl; - INTN State; - BOOLEAN IsArp; + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; + IP4_SERVICE *IpSb; + EFI_HANDLE NicHandle; + EFI_STATUS Status; + INTN State; + LIST_ENTRY *List; + IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context; // // IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol @@ -557,7 +591,6 @@ Ip4DriverBindingStop ( ControllerHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); - if (Status == EFI_SUCCESS) { // // Retrieve the IP4 service binding protocol. If failed, it is @@ -572,15 +605,11 @@ Ip4DriverBindingStop ( ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); - if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding); - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - if (IpSb->Ip4Config != NULL && (IpSb->State != IP4_SERVICE_DESTROY)) { IpSb->Ip4Config->Stop (IpSb->Ip4Config); @@ -591,9 +620,7 @@ Ip4DriverBindingStop ( IpSb->Image, ControllerHandle ); - if (EFI_ERROR (Status)) { - gBS->RestoreTPL (OldTpl); return Status; } @@ -609,7 +636,6 @@ Ip4DriverBindingStop ( gBS->CloseEvent (IpSb->ReconfigEvent); } - gBS->RestoreTPL (OldTpl); return EFI_SUCCESS; } @@ -619,16 +645,12 @@ Ip4DriverBindingStop ( // service binding is installed on the NIC handle. So, need to open // the protocol info to find the NIC handle. // - IsArp = FALSE; NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid); - if (NicHandle == NULL) { NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid); - IsArp = TRUE; - } - - if (NicHandle == NULL) { - return EFI_DEVICE_ERROR; + if (NicHandle == NULL) { + return EFI_SUCCESS; + } } // @@ -642,34 +664,23 @@ Ip4DriverBindingStop ( NicHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); - if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding); - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - if (IpSb->InDestroy) { - gBS->RestoreTPL (OldTpl); - return EFI_SUCCESS; - } - - if (IsArp) { - while (!IsListEmpty (&IpSb->Children)) { - IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link); - - ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle); - } - - if (IpSb->NumChildren != 0) { - Status = EFI_DEVICE_ERROR; - goto ON_ERROR; - } - - IpSb->InDestroy = TRUE; - + if (NumberOfChildren != 0) { + List = &IpSb->Children; + Context.ServiceBinding = ServiceBinding; + Context.NumberOfChildren = NumberOfChildren; + Context.ChildHandleBuffer = ChildHandleBuffer; + Status = NetDestroyLinkList ( + List, + Ip4DestroyChildEntryInHandleBuffer, + &Context, + NULL + ); + } else if (IsListEmpty (&IpSb->Children)) { State = IpSb->State; IpSb->State = IP4_SERVICE_DESTROY; @@ -682,7 +693,6 @@ Ip4DriverBindingStop ( // OK, clean other resources then uninstall the service binding protocol. // Status = Ip4CleanService (IpSb); - if (EFI_ERROR (Status)) { IpSb->State = State; goto ON_ERROR; @@ -693,52 +703,15 @@ Ip4DriverBindingStop ( &gEfiIp4ServiceBindingProtocolGuid, ServiceBinding ); - - FreePool (IpSb); - } else if (NumberOfChildren == 0) { - IpSb->InDestroy = TRUE; - - State = IpSb->State; - IpSb->State = IP4_SERVICE_DESTROY; - - // - // Clear the variable data. - // - Ip4ClearVariableData (IpSb); - - // - // OK, clean other resources then uninstall the service binding protocol. - // - Status = Ip4CleanService (IpSb); - - if (EFI_ERROR (Status)) { - IpSb->State = State; - goto ON_ERROR; + + if (gIp4ControllerNameTable != NULL) { + FreeUnicodeStringTable (gIp4ControllerNameTable); + gIp4ControllerNameTable = NULL; } - - gBS->UninstallProtocolInterface ( - NicHandle, - &gEfiIp4ServiceBindingProtocolGuid, - ServiceBinding - ); - FreePool (IpSb); - } else { - - while (!IsListEmpty (&IpSb->Children)) { - IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link); - - ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle); - } - - if (IpSb->NumChildren != 0) { - Status = EFI_DEVICE_ERROR; - } } ON_ERROR: - - gBS->RestoreTPL (OldTpl); return Status; } @@ -935,6 +908,15 @@ Ip4ServiceBindingDestroyChild ( ChildHandle ); + if (IpInstance->Interface != NULL && IpInstance->Interface->Arp != NULL) { + gBS->CloseProtocol ( + IpInstance->Interface->ArpHandle, + &gEfiArpProtocolGuid, + gIp4DriverBinding.DriverBindingHandle, + ChildHandle + ); + } + // // Uninstall the IP4 protocol first. Many thing happens during // this: @@ -949,12 +931,13 @@ Ip4ServiceBindingDestroyChild ( // will be called back before preceeding. If any packets not recycled, // that means there is a resource leak. // + gBS->RestoreTPL (OldTpl); Status = gBS->UninstallProtocolInterface ( ChildHandle, &gEfiIp4ProtocolGuid, &IpInstance->Ip4Proto ); - + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); if (EFI_ERROR (Status)) { goto ON_ERROR; }