REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the NetworkPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
		
			
				
	
	
		
			733 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			733 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Implementation of Mtftp drivers.
 | 
						|
 | 
						|
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Mtftp4Impl.h"
 | 
						|
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL  gMtftp4DriverBinding = {
 | 
						|
  Mtftp4DriverBindingSupported,
 | 
						|
  Mtftp4DriverBindingStart,
 | 
						|
  Mtftp4DriverBindingStop,
 | 
						|
  0xa,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
EFI_SERVICE_BINDING_PROTOCOL  gMtftp4ServiceBindingTemplete = {
 | 
						|
  Mtftp4ServiceBindingCreateChild,
 | 
						|
  Mtftp4ServiceBindingDestroyChild
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  The driver entry point which installs multiple protocols to the ImageHandle.
 | 
						|
 | 
						|
  @param ImageHandle    The MTFTP's image handle.
 | 
						|
  @param SystemTable    The system table.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS  The handles are successfully installed on the image.
 | 
						|
  @retval others       some EFI_ERROR occurred.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Mtftp4DriverEntryPoint (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  return EfiLibInstallDriverBindingComponentName2 (
 | 
						|
           ImageHandle,
 | 
						|
           SystemTable,
 | 
						|
           &gMtftp4DriverBinding,
 | 
						|
           ImageHandle,
 | 
						|
           &gMtftp4ComponentName,
 | 
						|
           &gMtftp4ComponentName2
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Test whether MTFTP driver support this controller.
 | 
						|
 | 
						|
  @param  This                   The MTFTP driver binding instance
 | 
						|
  @param  Controller             The controller to test
 | 
						|
  @param  RemainingDevicePath    The remaining device path
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The controller has UDP service binding protocol
 | 
						|
                                 installed, MTFTP can support it.
 | 
						|
  @retval EFI_ALREADY_STARTED    The device specified by ControllerHandle and
 | 
						|
                                 RemainingDevicePath is already being managed by
 | 
						|
                                 the driver specified by This.
 | 
						|
  @retval EFI_ACCESS_DENIED      The device specified by ControllerHandle and
 | 
						|
                                 RemainingDevicePath is already being managed by a
 | 
						|
                                 different driver or an application that requires
 | 
						|
                                 exclusive access.
 | 
						|
  @retval EFI_UNSUPPORTED        The device specified by ControllerHandle and
 | 
						|
                                 RemainingDevicePath is not supported by the driver
 | 
						|
                                 specified by This.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Mtftp4DriverBindingSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiUdp4ServiceBindingProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | 
						|
                  );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Config a NULL UDP that is used to keep the connection between UDP and MTFTP.
 | 
						|
 | 
						|
  Just leave the Udp child unconfigured. When UDP is unloaded,
 | 
						|
    MTFTP will be informed with DriverBinding Stop.
 | 
						|
 | 
						|
  @param  UdpIo                  The UDP_IO to configure
 | 
						|
  @param  Context                The opaque parameter to the callback
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            It always return EFI_SUCCESS directly.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Mtftp4ConfigNullUdp (
 | 
						|
  IN UDP_IO  *UdpIo,
 | 
						|
  IN VOID    *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create then initialize a MTFTP service binding instance.
 | 
						|
 | 
						|
  @param  Controller             The controller to install the MTFTP service
 | 
						|
                                 binding on
 | 
						|
  @param  Image                  The driver binding image of the MTFTP driver
 | 
						|
  @param  Service                The variable to receive the created service
 | 
						|
                                 binding instance.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create the instance
 | 
						|
  @retval EFI_DEVICE_ERROR       Failed to create a NULL UDP port to keep
 | 
						|
                                 connection  with UDP.
 | 
						|
  @retval EFI_SUCCESS            The service instance is created for the
 | 
						|
                                 controller.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Mtftp4CreateService (
 | 
						|
  IN     EFI_HANDLE   Controller,
 | 
						|
  IN     EFI_HANDLE   Image,
 | 
						|
  OUT MTFTP4_SERVICE  **Service
 | 
						|
  )
 | 
						|
{
 | 
						|
  MTFTP4_SERVICE  *MtftpSb;
 | 
						|
  EFI_STATUS      Status;
 | 
						|
 | 
						|
  *Service = NULL;
 | 
						|
  MtftpSb  = AllocatePool (sizeof (MTFTP4_SERVICE));
 | 
						|
 | 
						|
  if (MtftpSb == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  MtftpSb->Signature      = MTFTP4_SERVICE_SIGNATURE;
 | 
						|
  MtftpSb->ServiceBinding = gMtftp4ServiceBindingTemplete;
 | 
						|
  MtftpSb->ChildrenNum    = 0;
 | 
						|
  InitializeListHead (&MtftpSb->Children);
 | 
						|
 | 
						|
  MtftpSb->Timer            = NULL;
 | 
						|
  MtftpSb->TimerNotifyLevel = NULL;
 | 
						|
  MtftpSb->TimerToGetMap    = NULL;
 | 
						|
  MtftpSb->Controller       = Controller;
 | 
						|
  MtftpSb->Image            = Image;
 | 
						|
  MtftpSb->ConnectUdp       = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Create the timer and a udp to be notified when UDP is uninstalled
 | 
						|
  //
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_SIGNAL | EVT_TIMER,
 | 
						|
                  TPL_CALLBACK,
 | 
						|
                  Mtftp4OnTimerTick,
 | 
						|
                  MtftpSb,
 | 
						|
                  &MtftpSb->Timer
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (MtftpSb);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_SIGNAL | EVT_TIMER,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  Mtftp4OnTimerTickNotifyLevel,
 | 
						|
                  MtftpSb,
 | 
						|
                  &MtftpSb->TimerNotifyLevel
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    gBS->CloseEvent (MtftpSb->Timer);
 | 
						|
    FreePool (MtftpSb);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create the timer used to time out the procedure which is used to
 | 
						|
  // get the default IP address.
 | 
						|
  //
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_TIMER,
 | 
						|
                  TPL_CALLBACK,
 | 
						|
                  NULL,
 | 
						|
                  NULL,
 | 
						|
                  &MtftpSb->TimerToGetMap
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    gBS->CloseEvent (MtftpSb->TimerNotifyLevel);
 | 
						|
    gBS->CloseEvent (MtftpSb->Timer);
 | 
						|
    FreePool (MtftpSb);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  MtftpSb->ConnectUdp = UdpIoCreateIo (
 | 
						|
                          Controller,
 | 
						|
                          Image,
 | 
						|
                          Mtftp4ConfigNullUdp,
 | 
						|
                          UDP_IO_UDP4_VERSION,
 | 
						|
                          NULL
 | 
						|
                          );
 | 
						|
 | 
						|
  if (MtftpSb->ConnectUdp == NULL) {
 | 
						|
    gBS->CloseEvent (MtftpSb->TimerToGetMap);
 | 
						|
    gBS->CloseEvent (MtftpSb->TimerNotifyLevel);
 | 
						|
    gBS->CloseEvent (MtftpSb->Timer);
 | 
						|
    FreePool (MtftpSb);
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  *Service = MtftpSb;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Release all the resource used the MTFTP service binding instance.
 | 
						|
 | 
						|
  @param  MtftpSb                The MTFTP service binding instance.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Mtftp4CleanService (
 | 
						|
  IN MTFTP4_SERVICE  *MtftpSb
 | 
						|
  )
 | 
						|
{
 | 
						|
  UdpIoFreeIo (MtftpSb->ConnectUdp);
 | 
						|
  gBS->CloseEvent (MtftpSb->TimerToGetMap);
 | 
						|
  gBS->CloseEvent (MtftpSb->TimerNotifyLevel);
 | 
						|
  gBS->CloseEvent (MtftpSb->Timer);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Start the MTFTP driver on this controller.
 | 
						|
 | 
						|
  MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported
 | 
						|
  controller, which can be used to create/destroy MTFTP children.
 | 
						|
 | 
						|
  @param  This                   The MTFTP driver binding protocol.
 | 
						|
  @param  Controller             The controller to manage.
 | 
						|
  @param  RemainingDevicePath    Remaining device path.
 | 
						|
 | 
						|
  @retval EFI_ALREADY_STARTED    The MTFTP service binding protocol has been
 | 
						|
                                 started  on the controller.
 | 
						|
  @retval EFI_SUCCESS            The MTFTP service binding is installed on the
 | 
						|
                                 controller.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Mtftp4DriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  MTFTP4_SERVICE  *MtftpSb;
 | 
						|
  EFI_STATUS      Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Directly return if driver is already running.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiMtftp4ServiceBindingProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | 
						|
                  );
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    return EFI_ALREADY_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Mtftp4CreateService (Controller, This->DriverBindingHandle, &MtftpSb);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (MtftpSb != NULL);
 | 
						|
 | 
						|
  Status = gBS->SetTimer (MtftpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->SetTimer (MtftpSb->TimerNotifyLevel, TimerPeriodic, TICKS_PER_SECOND);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Install the Mtftp4ServiceBinding Protocol onto Controller
 | 
						|
  //
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &Controller,
 | 
						|
                  &gEfiMtftp4ServiceBindingProtocolGuid,
 | 
						|
                  &MtftpSb->ServiceBinding,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
ON_ERROR:
 | 
						|
  Mtftp4CleanService (MtftpSb);
 | 
						|
  FreePool (MtftpSb);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
EFIAPI
 | 
						|
Mtftp4DestroyChildEntryInHandleBuffer (
 | 
						|
  IN LIST_ENTRY  *Entry,
 | 
						|
  IN VOID        *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  MTFTP4_PROTOCOL               *Instance;
 | 
						|
  EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
 | 
						|
  UINTN                         NumberOfChildren;
 | 
						|
  EFI_HANDLE                    *ChildHandleBuffer;
 | 
						|
 | 
						|
  if ((Entry == NULL) || (Context == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Instance          = NET_LIST_USER_STRUCT_S (Entry, MTFTP4_PROTOCOL, Link, MTFTP4_PROTOCOL_SIGNATURE);
 | 
						|
  ServiceBinding    = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ServiceBinding;
 | 
						|
  NumberOfChildren  = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->NumberOfChildren;
 | 
						|
  ChildHandleBuffer = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ChildHandleBuffer;
 | 
						|
 | 
						|
  if (!NetIsInHandleBuffer (Instance->Handle, NumberOfChildren, ChildHandleBuffer)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Stop the MTFTP driver on controller. The controller is a UDP
 | 
						|
  child handle.
 | 
						|
 | 
						|
  @param  This                   The MTFTP driver binding protocol
 | 
						|
  @param  Controller             The controller to stop
 | 
						|
  @param  NumberOfChildren       The number of children
 | 
						|
  @param  ChildHandleBuffer      The array of the child handle.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The driver is stopped on the controller.
 | 
						|
  @retval EFI_DEVICE_ERROR       Failed to stop the driver on the controller.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Mtftp4DriverBindingStop (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   Controller,
 | 
						|
  IN UINTN                        NumberOfChildren,
 | 
						|
  IN EFI_HANDLE                   *ChildHandleBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_SERVICE_BINDING_PROTOCOL                *ServiceBinding;
 | 
						|
  MTFTP4_SERVICE                              *MtftpSb;
 | 
						|
  EFI_HANDLE                                  NicHandle;
 | 
						|
  EFI_STATUS                                  Status;
 | 
						|
  LIST_ENTRY                                  *List;
 | 
						|
  MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT  Context;
 | 
						|
 | 
						|
  //
 | 
						|
  // MTFTP driver opens UDP child, So, Controller is a UDP
 | 
						|
  // child handle. Locate the Nic handle first. Then get the
 | 
						|
  // MTFTP private data back.
 | 
						|
  //
 | 
						|
  NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid);
 | 
						|
 | 
						|
  if (NicHandle == NULL) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  NicHandle,
 | 
						|
                  &gEfiMtftp4ServiceBindingProtocolGuid,
 | 
						|
                  (VOID **)&ServiceBinding,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  NicHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                  );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding);
 | 
						|
 | 
						|
  if (!IsListEmpty (&MtftpSb->Children)) {
 | 
						|
    //
 | 
						|
    // Destroy the Mtftp4 child instance in ChildHandleBuffer.
 | 
						|
    //
 | 
						|
    List                      = &MtftpSb->Children;
 | 
						|
    Context.ServiceBinding    = ServiceBinding;
 | 
						|
    Context.NumberOfChildren  = NumberOfChildren;
 | 
						|
    Context.ChildHandleBuffer = ChildHandleBuffer;
 | 
						|
    Status                    = NetDestroyLinkList (
 | 
						|
                                  List,
 | 
						|
                                  Mtftp4DestroyChildEntryInHandleBuffer,
 | 
						|
                                  &Context,
 | 
						|
                                  NULL
 | 
						|
                                  );
 | 
						|
  }
 | 
						|
 | 
						|
  if ((NumberOfChildren == 0) && IsListEmpty (&MtftpSb->Children)) {
 | 
						|
    gBS->UninstallProtocolInterface (
 | 
						|
           NicHandle,
 | 
						|
           &gEfiMtftp4ServiceBindingProtocolGuid,
 | 
						|
           ServiceBinding
 | 
						|
           );
 | 
						|
 | 
						|
    Mtftp4CleanService (MtftpSb);
 | 
						|
    if (gMtftp4ControllerNameTable != NULL) {
 | 
						|
      FreeUnicodeStringTable (gMtftp4ControllerNameTable);
 | 
						|
      gMtftp4ControllerNameTable = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (MtftpSb);
 | 
						|
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize a MTFTP protocol instance which is the child of MtftpSb.
 | 
						|
 | 
						|
  @param  MtftpSb                The MTFTP service binding protocol.
 | 
						|
  @param  Instance               The MTFTP instance to initialize.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Mtftp4InitProtocol (
 | 
						|
  IN     MTFTP4_SERVICE  *MtftpSb,
 | 
						|
  OUT MTFTP4_PROTOCOL    *Instance
 | 
						|
  )
 | 
						|
{
 | 
						|
  ZeroMem (Instance, sizeof (MTFTP4_PROTOCOL));
 | 
						|
 | 
						|
  Instance->Signature = MTFTP4_PROTOCOL_SIGNATURE;
 | 
						|
  InitializeListHead (&Instance->Link);
 | 
						|
  CopyMem (&Instance->Mtftp4, &gMtftp4ProtocolTemplate, sizeof (Instance->Mtftp4));
 | 
						|
  Instance->State   = MTFTP4_STATE_UNCONFIGED;
 | 
						|
  Instance->Service = MtftpSb;
 | 
						|
 | 
						|
  InitializeListHead (&Instance->Blocks);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a MTFTP child for the service binding instance, then
 | 
						|
  install the MTFTP protocol to the ChildHandle.
 | 
						|
 | 
						|
  @param  This                   The MTFTP service binding instance.
 | 
						|
  @param  ChildHandle            The Child handle to install the MTFTP protocol.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  The parameter is invalid.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource for the new child.
 | 
						|
  @retval EFI_SUCCESS            The child is successfully create.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Mtftp4ServiceBindingCreateChild (
 | 
						|
  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                    *ChildHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  MTFTP4_SERVICE   *MtftpSb;
 | 
						|
  MTFTP4_PROTOCOL  *Instance;
 | 
						|
  EFI_STATUS       Status;
 | 
						|
  EFI_TPL          OldTpl;
 | 
						|
  VOID             *Udp4;
 | 
						|
 | 
						|
  if ((This == NULL) || (ChildHandle == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Instance = AllocatePool (sizeof (*Instance));
 | 
						|
 | 
						|
  if (Instance == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);
 | 
						|
 | 
						|
  Mtftp4InitProtocol (MtftpSb, Instance);
 | 
						|
 | 
						|
  Instance->UnicastPort = UdpIoCreateIo (
 | 
						|
                            MtftpSb->Controller,
 | 
						|
                            MtftpSb->Image,
 | 
						|
                            Mtftp4ConfigNullUdp,
 | 
						|
                            UDP_IO_UDP4_VERSION,
 | 
						|
                            Instance
 | 
						|
                            );
 | 
						|
 | 
						|
  if (Instance->UnicastPort == NULL) {
 | 
						|
    FreePool (Instance);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Install the MTFTP protocol onto ChildHandle
 | 
						|
  //
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  ChildHandle,
 | 
						|
                  &gEfiMtftp4ProtocolGuid,
 | 
						|
                  &Instance->Mtftp4,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    UdpIoFreeIo (Instance->UnicastPort);
 | 
						|
    FreePool (Instance);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Instance->Handle = *ChildHandle;
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the Udp4 protocol BY_CHILD.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  MtftpSb->ConnectUdp->UdpHandle,
 | 
						|
                  &gEfiUdp4ProtocolGuid,
 | 
						|
                  (VOID **)&Udp4,
 | 
						|
                  gMtftp4DriverBinding.DriverBindingHandle,
 | 
						|
                  Instance->Handle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the Udp4 protocol by child.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Instance->UnicastPort->UdpHandle,
 | 
						|
                  &gEfiUdp4ProtocolGuid,
 | 
						|
                  (VOID **)&Udp4,
 | 
						|
                  gMtftp4DriverBinding.DriverBindingHandle,
 | 
						|
                  Instance->Handle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Close the Udp4 protocol.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           MtftpSb->ConnectUdp->UdpHandle,
 | 
						|
           &gEfiUdp4ProtocolGuid,
 | 
						|
           gMtftp4DriverBinding.DriverBindingHandle,
 | 
						|
           *ChildHandle
 | 
						|
           );
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add it to the parent's child list.
 | 
						|
  //
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
 | 
						|
  InsertTailList (&MtftpSb->Children, &Instance->Link);
 | 
						|
  MtftpSb->ChildrenNum++;
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
ON_ERROR:
 | 
						|
  if (Instance->Handle != NULL) {
 | 
						|
    gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
           Instance->Handle,
 | 
						|
           &gEfiMtftp4ProtocolGuid,
 | 
						|
           &Instance->Mtftp4,
 | 
						|
           NULL
 | 
						|
           );
 | 
						|
  }
 | 
						|
 | 
						|
  UdpIoFreeIo (Instance->UnicastPort);
 | 
						|
  FreePool (Instance);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Destroy one of the service binding's child.
 | 
						|
 | 
						|
  @param  This                   The service binding instance
 | 
						|
  @param  ChildHandle            The child handle to destroy
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  The parameter is invalid.
 | 
						|
  @retval EFI_UNSUPPORTED        The child may have already been destroyed.
 | 
						|
  @retval EFI_SUCCESS            The child is destroyed and removed from the
 | 
						|
                                 parent's child list.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Mtftp4ServiceBindingDestroyChild (
 | 
						|
  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                    ChildHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  MTFTP4_SERVICE       *MtftpSb;
 | 
						|
  MTFTP4_PROTOCOL      *Instance;
 | 
						|
  EFI_MTFTP4_PROTOCOL  *Mtftp4;
 | 
						|
  EFI_STATUS           Status;
 | 
						|
  EFI_TPL              OldTpl;
 | 
						|
 | 
						|
  if ((This == NULL) || (ChildHandle == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrieve the private context data structures
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  ChildHandle,
 | 
						|
                  &gEfiMtftp4ProtocolGuid,
 | 
						|
                  (VOID **)&Mtftp4,
 | 
						|
                  gMtftp4DriverBinding.DriverBindingHandle,
 | 
						|
                  ChildHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                  );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  Instance = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4);
 | 
						|
  MtftpSb  = MTFTP4_SERVICE_FROM_THIS (This);
 | 
						|
 | 
						|
  if (Instance->Service != MtftpSb) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Instance->InDestroy) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Instance->InDestroy = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Close the Udp4 protocol.
 | 
						|
  //
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         MtftpSb->ConnectUdp->UdpHandle,
 | 
						|
         &gEfiUdp4ProtocolGuid,
 | 
						|
         gMtftp4DriverBinding.DriverBindingHandle,
 | 
						|
         ChildHandle
 | 
						|
         );
 | 
						|
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         Instance->UnicastPort->UdpHandle,
 | 
						|
         &gEfiUdp4ProtocolGuid,
 | 
						|
         gMtftp4DriverBinding.DriverBindingHandle,
 | 
						|
         ChildHandle
 | 
						|
         );
 | 
						|
 | 
						|
  if (Instance->McastUdpPort != NULL) {
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Instance->McastUdpPort->UdpHandle,
 | 
						|
           &gEfiUdp4ProtocolGuid,
 | 
						|
           gMtftp4DriverBinding.DriverBindingHandle,
 | 
						|
           ChildHandle
 | 
						|
           );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Uninstall the MTFTP4 protocol first to enable a top down destruction.
 | 
						|
  //
 | 
						|
  Status = gBS->UninstallProtocolInterface (
 | 
						|
                  ChildHandle,
 | 
						|
                  &gEfiMtftp4ProtocolGuid,
 | 
						|
                  Mtftp4
 | 
						|
                  );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Instance->InDestroy = FALSE;
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
 | 
						|
  Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);
 | 
						|
  UdpIoFreeIo (Instance->UnicastPort);
 | 
						|
 | 
						|
  RemoveEntryList (&Instance->Link);
 | 
						|
  MtftpSb->ChildrenNum--;
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  FreePool (Instance);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |