]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.c
NetworkPkg: Move Network library and drivers from MdeModulePkg to NetworkPkg
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Mtftp4Dxe / Mtftp4Driver.c
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.c b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.c
deleted file mode 100644 (file)
index ae9e655..0000000
+++ /dev/null
@@ -1,739 +0,0 @@
-/** @file\r
-  Implementation of Mtftp drivers.\r
-\r
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Mtftp4Impl.h"\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL   gMtftp4DriverBinding = {\r
-  Mtftp4DriverBindingSupported,\r
-  Mtftp4DriverBindingStart,\r
-  Mtftp4DriverBindingStop,\r
-  0xa,\r
-  NULL,\r
-  NULL\r
-};\r
-\r
-EFI_SERVICE_BINDING_PROTOCOL  gMtftp4ServiceBindingTemplete = {\r
-  Mtftp4ServiceBindingCreateChild,\r
-  Mtftp4ServiceBindingDestroyChild\r
-};\r
-\r
-\r
-/**\r
-  The driver entry point which installs multiple protocols to the ImageHandle.\r
-\r
-  @param ImageHandle    The MTFTP's image handle.\r
-  @param SystemTable    The system table.\r
-\r
-  @retval EFI_SUCCESS  The handles are successfully installed on the image.\r
-  @retval others       some EFI_ERROR occured.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Mtftp4DriverEntryPoint (\r
-  IN EFI_HANDLE             ImageHandle,\r
-  IN EFI_SYSTEM_TABLE       *SystemTable\r
-  )\r
-{\r
-  return EfiLibInstallDriverBindingComponentName2 (\r
-           ImageHandle,\r
-           SystemTable,\r
-           &gMtftp4DriverBinding,\r
-           ImageHandle,\r
-           &gMtftp4ComponentName,\r
-           &gMtftp4ComponentName2\r
-           );\r
-}\r
-\r
-\r
-/**\r
-  Test whether MTFTP driver support this controller.\r
-\r
-  @param  This                   The MTFTP driver binding instance\r
-  @param  Controller             The controller to test\r
-  @param  RemainingDevicePath    The remaining device path\r
-\r
-  @retval EFI_SUCCESS            The controller has UDP service binding protocol\r
-                                 installed, MTFTP can support it.\r
-  @retval EFI_ALREADY_STARTED    The device specified by ControllerHandle and\r
-                                 RemainingDevicePath is already being managed by\r
-                                 the driver specified by This.\r
-  @retval EFI_ACCESS_DENIED      The device specified by ControllerHandle and\r
-                                 RemainingDevicePath is already being managed by a\r
-                                 different driver or an application that requires\r
-                                 exclusive access.\r
-  @retval EFI_UNSUPPORTED        The device specified by ControllerHandle and\r
-                                 RemainingDevicePath is not supported by the driver\r
-                                 specified by This.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Mtftp4DriverBindingSupported (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
-  IN EFI_HANDLE                     Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiUdp4ServiceBindingProtocolGuid,\r
-                  NULL,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                  );\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Config a NULL UDP that is used to keep the connection between UDP and MTFTP.\r
-\r
-  Just leave the Udp child unconfigured. When UDP is unloaded,\r
-    MTFTP will be informed with DriverBinding Stop.\r
-\r
-  @param  UdpIo                  The UDP_IO to configure\r
-  @param  Context                The opaque parameter to the callback\r
-\r
-  @retval EFI_SUCCESS            It always return EFI_SUCCESS directly.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Mtftp4ConfigNullUdp (\r
-  IN UDP_IO                 *UdpIo,\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Create then initialize a MTFTP service binding instance.\r
-\r
-  @param  Controller             The controller to install the MTFTP service\r
-                                 binding on\r
-  @param  Image                  The driver binding image of the MTFTP driver\r
-  @param  Service                The variable to receive the created service\r
-                                 binding instance.\r
-\r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create the instance\r
-  @retval EFI_DEVICE_ERROR       Failed to create a NULL UDP port to keep\r
-                                 connection  with UDP.\r
-  @retval EFI_SUCCESS            The service instance is created for the\r
-                                 controller.\r
-\r
-**/\r
-EFI_STATUS\r
-Mtftp4CreateService (\r
-  IN     EFI_HANDLE            Controller,\r
-  IN     EFI_HANDLE            Image,\r
-     OUT MTFTP4_SERVICE        **Service\r
-  )\r
-{\r
-  MTFTP4_SERVICE            *MtftpSb;\r
-  EFI_STATUS                Status;\r
-\r
-  *Service  = NULL;\r
-  MtftpSb   = AllocatePool (sizeof (MTFTP4_SERVICE));\r
-\r
-  if (MtftpSb == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  MtftpSb->Signature      = MTFTP4_SERVICE_SIGNATURE;\r
-  MtftpSb->ServiceBinding = gMtftp4ServiceBindingTemplete;\r
-  MtftpSb->ChildrenNum    = 0;\r
-  InitializeListHead (&MtftpSb->Children);\r
-\r
-  MtftpSb->Timer            = NULL;\r
-  MtftpSb->TimerNotifyLevel = NULL;\r
-  MtftpSb->TimerToGetMap    = NULL;\r
-  MtftpSb->Controller       = Controller;\r
-  MtftpSb->Image            = Image;\r
-  MtftpSb->ConnectUdp       = NULL;\r
-\r
-  //\r
-  // Create the timer and a udp to be notified when UDP is uninstalled\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
-                  TPL_CALLBACK,\r
-                  Mtftp4OnTimerTick,\r
-                  MtftpSb,\r
-                  &MtftpSb->Timer\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (MtftpSb);\r
-    return Status;\r
-  }\r
-\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
-                  TPL_NOTIFY,\r
-                  Mtftp4OnTimerTickNotifyLevel,\r
-                  MtftpSb,\r
-                  &MtftpSb->TimerNotifyLevel\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    gBS->CloseEvent (MtftpSb->Timer);\r
-    FreePool (MtftpSb);\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Create the timer used to time out the procedure which is used to\r
-  // get the default IP address.\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_TIMER,\r
-                  TPL_CALLBACK,\r
-                  NULL,\r
-                  NULL,\r
-                  &MtftpSb->TimerToGetMap\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    gBS->CloseEvent (MtftpSb->TimerNotifyLevel);\r
-    gBS->CloseEvent (MtftpSb->Timer);\r
-    FreePool (MtftpSb);\r
-    return Status;\r
-  }\r
-\r
-  MtftpSb->ConnectUdp = UdpIoCreateIo (\r
-                          Controller,\r
-                          Image,\r
-                          Mtftp4ConfigNullUdp,\r
-                          UDP_IO_UDP4_VERSION,\r
-                          NULL\r
-                          );\r
-\r
-  if (MtftpSb->ConnectUdp == NULL) {\r
-    gBS->CloseEvent (MtftpSb->TimerToGetMap);\r
-    gBS->CloseEvent (MtftpSb->TimerNotifyLevel);\r
-    gBS->CloseEvent (MtftpSb->Timer);\r
-    FreePool (MtftpSb);\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  *Service = MtftpSb;\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Release all the resource used the MTFTP service binding instance.\r
-\r
-  @param  MtftpSb                The MTFTP service binding instance.\r
-\r
-**/\r
-VOID\r
-Mtftp4CleanService (\r
-  IN MTFTP4_SERVICE     *MtftpSb\r
-  )\r
-{\r
-  UdpIoFreeIo (MtftpSb->ConnectUdp);\r
-  gBS->CloseEvent (MtftpSb->TimerToGetMap);\r
-  gBS->CloseEvent (MtftpSb->TimerNotifyLevel);\r
-  gBS->CloseEvent (MtftpSb->Timer);\r
-}\r
-\r
-\r
-/**\r
-  Start the MTFTP driver on this controller.\r
-\r
-  MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported\r
-  controller, which can be used to create/destroy MTFTP children.\r
-\r
-  @param  This                   The MTFTP driver binding protocol.\r
-  @param  Controller             The controller to manage.\r
-  @param  RemainingDevicePath    Remaining device path.\r
-\r
-  @retval EFI_ALREADY_STARTED    The MTFTP service binding protocol has been\r
-                                 started  on the controller.\r
-  @retval EFI_SUCCESS            The MTFTP service binding is installed on the\r
-                                 controller.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Mtftp4DriverBindingStart (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
-  IN EFI_HANDLE                   Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
-  )\r
-{\r
-  MTFTP4_SERVICE            *MtftpSb;\r
-  EFI_STATUS                Status;\r
-\r
-  //\r
-  // Directly return if driver is already running.\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiMtftp4ServiceBindingProtocolGuid,\r
-                  NULL,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                  );\r
-\r
-  if (Status == EFI_SUCCESS) {\r
-    return EFI_ALREADY_STARTED;\r
-  }\r
-\r
-  Status = Mtftp4CreateService (Controller, This->DriverBindingHandle, &MtftpSb);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  ASSERT (MtftpSb != NULL);\r
-\r
-  Status = gBS->SetTimer (MtftpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  Status = gBS->SetTimer (MtftpSb->TimerNotifyLevel, TimerPeriodic, TICKS_PER_SECOND);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  //\r
-  // Install the Mtftp4ServiceBinding Protocol onto Controller\r
-  //\r
-  Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  &Controller,\r
-                  &gEfiMtftp4ServiceBindingProtocolGuid,\r
-                  &MtftpSb->ServiceBinding,\r
-                  NULL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
-  Mtftp4CleanService (MtftpSb);\r
-  FreePool (MtftpSb);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
-\r
-  @param[in]    Entry           The entry to be removed.\r
-  @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
-\r
-  @retval EFI_SUCCESS           The entry has been removed successfully.\r
-  @retval Others                Fail to remove the entry.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Mtftp4DestroyChildEntryInHandleBuffer (\r
-  IN LIST_ENTRY         *Entry,\r
-  IN VOID               *Context\r
-  )\r
-{\r
-  MTFTP4_PROTOCOL               *Instance;\r
-  EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
-  UINTN                         NumberOfChildren;\r
-  EFI_HANDLE                    *ChildHandleBuffer;\r
-\r
-  if (Entry == NULL || Context == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Instance = NET_LIST_USER_STRUCT_S (Entry, MTFTP4_PROTOCOL, Link, MTFTP4_PROTOCOL_SIGNATURE);\r
-  ServiceBinding    = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
-  NumberOfChildren  = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
-  ChildHandleBuffer = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
-\r
-  if (!NetIsInHandleBuffer (Instance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
-}\r
-\r
-/**\r
-  Stop the MTFTP driver on controller. The controller is a UDP\r
-  child handle.\r
-\r
-  @param  This                   The MTFTP driver binding protocol\r
-  @param  Controller             The controller to stop\r
-  @param  NumberOfChildren       The number of children\r
-  @param  ChildHandleBuffer      The array of the child handle.\r
-\r
-  @retval EFI_SUCCESS            The driver is stopped on the controller.\r
-  @retval EFI_DEVICE_ERROR       Failed to stop the driver on the controller.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Mtftp4DriverBindingStop (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
-  IN EFI_HANDLE                  Controller,\r
-  IN UINTN                       NumberOfChildren,\r
-  IN EFI_HANDLE                  *ChildHandleBuffer\r
-  )\r
-{\r
-  EFI_SERVICE_BINDING_PROTOCOL               *ServiceBinding;\r
-  MTFTP4_SERVICE                             *MtftpSb;\r
-  EFI_HANDLE                                 NicHandle;\r
-  EFI_STATUS                                 Status;\r
-  LIST_ENTRY                                 *List;\r
-  MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
-\r
-  //\r
-  // MTFTP driver opens UDP child, So, Controller is a UDP\r
-  // child handle. Locate the Nic handle first. Then get the\r
-  // MTFTP private data back.\r
-  //\r
-  NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid);\r
-\r
-  if (NicHandle == NULL) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  Status = gBS->OpenProtocol (\r
-                  NicHandle,\r
-                  &gEfiMtftp4ServiceBindingProtocolGuid,\r
-                  (VOID **) &ServiceBinding,\r
-                  This->DriverBindingHandle,\r
-                  NicHandle,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding);\r
-\r
-  if (!IsListEmpty (&MtftpSb->Children)) {\r
-    //\r
-    // Destroy the Mtftp4 child instance in ChildHandleBuffer.\r
-    //\r
-    List = &MtftpSb->Children;\r
-    Context.ServiceBinding    = ServiceBinding;\r
-    Context.NumberOfChildren  = NumberOfChildren;\r
-    Context.ChildHandleBuffer = ChildHandleBuffer;\r
-    Status = NetDestroyLinkList (\r
-               List,\r
-               Mtftp4DestroyChildEntryInHandleBuffer,\r
-               &Context,\r
-               NULL\r
-               );\r
-  }\r
-\r
-  if (NumberOfChildren == 0 && IsListEmpty (&MtftpSb->Children)) {\r
-    gBS->UninstallProtocolInterface (\r
-           NicHandle,\r
-           &gEfiMtftp4ServiceBindingProtocolGuid,\r
-           ServiceBinding\r
-           );\r
-\r
-    Mtftp4CleanService (MtftpSb);\r
-    if (gMtftp4ControllerNameTable != NULL) {\r
-      FreeUnicodeStringTable (gMtftp4ControllerNameTable);\r
-      gMtftp4ControllerNameTable = NULL;\r
-    }\r
-    FreePool (MtftpSb);\r
-\r
-    Status = EFI_SUCCESS;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Initialize a MTFTP protocol instance which is the child of MtftpSb.\r
-\r
-  @param  MtftpSb                The MTFTP service binding protocol.\r
-  @param  Instance               The MTFTP instance to initialize.\r
-\r
-**/\r
-VOID\r
-Mtftp4InitProtocol (\r
-  IN     MTFTP4_SERVICE         *MtftpSb,\r
-     OUT MTFTP4_PROTOCOL        *Instance\r
-  )\r
-{\r
-  ZeroMem (Instance, sizeof (MTFTP4_PROTOCOL));\r
-\r
-  Instance->Signature = MTFTP4_PROTOCOL_SIGNATURE;\r
-  InitializeListHead (&Instance->Link);\r
-  CopyMem (&Instance->Mtftp4, &gMtftp4ProtocolTemplate, sizeof (Instance->Mtftp4));\r
-  Instance->State     = MTFTP4_STATE_UNCONFIGED;\r
-  Instance->Service   = MtftpSb;\r
-\r
-  InitializeListHead (&Instance->Blocks);\r
-}\r
-\r
-\r
-/**\r
-  Create a MTFTP child for the service binding instance, then\r
-  install the MTFTP protocol to the ChildHandle.\r
-\r
-  @param  This                   The MTFTP service binding instance.\r
-  @param  ChildHandle            The Child handle to install the MTFTP protocol.\r
-\r
-  @retval EFI_INVALID_PARAMETER  The parameter is invalid.\r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource for the new child.\r
-  @retval EFI_SUCCESS            The child is successfully create.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Mtftp4ServiceBindingCreateChild (\r
-  IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
-  IN EFI_HANDLE                *ChildHandle\r
-  )\r
-{\r
-  MTFTP4_SERVICE            *MtftpSb;\r
-  MTFTP4_PROTOCOL           *Instance;\r
-  EFI_STATUS                Status;\r
-  EFI_TPL                   OldTpl;\r
-  VOID                      *Udp4;\r
-\r
-  if ((This == NULL) || (ChildHandle == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Instance = AllocatePool (sizeof (*Instance));\r
-\r
-  if (Instance == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);\r
-\r
-  Mtftp4InitProtocol (MtftpSb, Instance);\r
-\r
-  Instance->UnicastPort = UdpIoCreateIo (\r
-                            MtftpSb->Controller,\r
-                            MtftpSb->Image,\r
-                            Mtftp4ConfigNullUdp,\r
-                            UDP_IO_UDP4_VERSION,\r
-                            Instance\r
-                            );\r
-\r
-  if (Instance->UnicastPort == NULL) {\r
-    FreePool (Instance);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  //\r
-  // Install the MTFTP protocol onto ChildHandle\r
-  //\r
-  Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  ChildHandle,\r
-                  &gEfiMtftp4ProtocolGuid,\r
-                  &Instance->Mtftp4,\r
-                  NULL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    UdpIoFreeIo (Instance->UnicastPort);\r
-    FreePool (Instance);\r
-    return Status;\r
-  }\r
-\r
-  Instance->Handle  = *ChildHandle;\r
-\r
-  //\r
-  // Open the Udp4 protocol BY_CHILD.\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  MtftpSb->ConnectUdp->UdpHandle,\r
-                  &gEfiUdp4ProtocolGuid,\r
-                  (VOID **) &Udp4,\r
-                  gMtftp4DriverBinding.DriverBindingHandle,\r
-                  Instance->Handle,\r
-                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  //\r
-  // Open the Udp4 protocol by child.\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Instance->UnicastPort->UdpHandle,\r
-                  &gEfiUdp4ProtocolGuid,\r
-                  (VOID **) &Udp4,\r
-                  gMtftp4DriverBinding.DriverBindingHandle,\r
-                  Instance->Handle,\r
-                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // Close the Udp4 protocol.\r
-    //\r
-    gBS->CloseProtocol (\r
-           MtftpSb->ConnectUdp->UdpHandle,\r
-           &gEfiUdp4ProtocolGuid,\r
-           gMtftp4DriverBinding.DriverBindingHandle,\r
-           ChildHandle\r
-           );\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  //\r
-  // Add it to the parent's child list.\r
-  //\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  InsertTailList (&MtftpSb->Children, &Instance->Link);\r
-  MtftpSb->ChildrenNum++;\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
-  if (Instance->Handle != NULL) {\r
-    gBS->UninstallMultipleProtocolInterfaces (\r
-           Instance->Handle,\r
-           &gEfiMtftp4ProtocolGuid,\r
-           &Instance->Mtftp4,\r
-           NULL\r
-           );\r
-  }\r
-\r
-  UdpIoFreeIo (Instance->UnicastPort);\r
-  FreePool (Instance);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Destroy one of the service binding's child.\r
-\r
-  @param  This                   The service binding instance\r
-  @param  ChildHandle            The child handle to destroy\r
-\r
-  @retval EFI_INVALID_PARAMETER  The parameter is invaid.\r
-  @retval EFI_UNSUPPORTED        The child may have already been destroyed.\r
-  @retval EFI_SUCCESS            The child is destroyed and removed from the\r
-                                 parent's child list.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Mtftp4ServiceBindingDestroyChild (\r
-  IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
-  IN EFI_HANDLE                   ChildHandle\r
-  )\r
-{\r
-  MTFTP4_SERVICE            *MtftpSb;\r
-  MTFTP4_PROTOCOL           *Instance;\r
-  EFI_MTFTP4_PROTOCOL       *Mtftp4;\r
-  EFI_STATUS                Status;\r
-  EFI_TPL                   OldTpl;\r
-\r
-  if ((This == NULL) || (ChildHandle == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // Retrieve the private context data structures\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  ChildHandle,\r
-                  &gEfiMtftp4ProtocolGuid,\r
-                  (VOID **) &Mtftp4,\r
-                  gMtftp4DriverBinding.DriverBindingHandle,\r
-                  ChildHandle,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  Instance  = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4);\r
-  MtftpSb   = MTFTP4_SERVICE_FROM_THIS (This);\r
-\r
-  if (Instance->Service != MtftpSb) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (Instance->InDestroy) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  Instance->InDestroy = TRUE;\r
-\r
-  //\r
-  // Close the Udp4 protocol.\r
-  //\r
-  gBS->CloseProtocol (\r
-         MtftpSb->ConnectUdp->UdpHandle,\r
-         &gEfiUdp4ProtocolGuid,\r
-         gMtftp4DriverBinding.DriverBindingHandle,\r
-         ChildHandle\r
-         );\r
-\r
-  gBS->CloseProtocol (\r
-         Instance->UnicastPort->UdpHandle,\r
-         &gEfiUdp4ProtocolGuid,\r
-         gMtftp4DriverBinding.DriverBindingHandle,\r
-         ChildHandle\r
-         );\r
-\r
-  if (Instance->McastUdpPort != NULL) {\r
-    gBS->CloseProtocol (\r
-           Instance->McastUdpPort->UdpHandle,\r
-           &gEfiUdp4ProtocolGuid,\r
-           gMtftp4DriverBinding.DriverBindingHandle,\r
-           ChildHandle\r
-           );\r
-  }\r
-\r
-  //\r
-  // Uninstall the MTFTP4 protocol first to enable a top down destruction.\r
-  //\r
-  Status = gBS->UninstallProtocolInterface (\r
-                  ChildHandle,\r
-                  &gEfiMtftp4ProtocolGuid,\r
-                  Mtftp4\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    Instance->InDestroy = FALSE;\r
-    return Status;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);\r
-  UdpIoFreeIo (Instance->UnicastPort);\r
-\r
-  RemoveEntryList (&Instance->Link);\r
-  MtftpSb->ChildrenNum--;\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  FreePool (Instance);\r
-  return EFI_SUCCESS;\r
-}\r