+++ /dev/null
-/** @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