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>
		
			
				
	
	
		
			724 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			724 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
| Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "Dhcp4Impl.h"
 | |
| #include "Dhcp4Driver.h"
 | |
| 
 | |
| EFI_DRIVER_BINDING_PROTOCOL  gDhcp4DriverBinding = {
 | |
|   Dhcp4DriverBindingSupported,
 | |
|   Dhcp4DriverBindingStart,
 | |
|   Dhcp4DriverBindingStop,
 | |
|   0xa,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| EFI_SERVICE_BINDING_PROTOCOL  mDhcp4ServiceBindingTemplate = {
 | |
|   Dhcp4ServiceBindingCreateChild,
 | |
|   Dhcp4ServiceBindingDestroyChild
 | |
| };
 | |
| 
 | |
| /**
 | |
|   This is the declaration of an EFI image entry point. This entry point is
 | |
|   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
 | |
|   both device drivers and bus drivers.
 | |
| 
 | |
|   Entry point of the DHCP driver to install various protocols.
 | |
| 
 | |
|   @param[in]  ImageHandle           The firmware allocated handle for the UEFI image.
 | |
|   @param[in]  SystemTable           A pointer to the EFI System Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The operation completed successfully.
 | |
|   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Dhcp4DriverEntryPoint (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   return EfiLibInstallDriverBindingComponentName2 (
 | |
|            ImageHandle,
 | |
|            SystemTable,
 | |
|            &gDhcp4DriverBinding,
 | |
|            ImageHandle,
 | |
|            &gDhcp4ComponentName,
 | |
|            &gDhcp4ComponentName2
 | |
|            );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Test to see if this driver supports ControllerHandle. This service
 | |
|   is called by the EFI boot service ConnectController(). In
 | |
|   order to make drivers as small as possible, there are a few calling
 | |
|   restrictions for this service. ConnectController() must
 | |
|   follow these calling restrictions. If any other agent wishes to call
 | |
|   Supported() it must also follow these calling restrictions.
 | |
| 
 | |
|   @param[in]  This                Protocol instance pointer.
 | |
|   @param[in]  ControllerHandle    Handle of device to test
 | |
|   @param[in]  RemainingDevicePath Optional parameter use to pick a specific child
 | |
|                                   device to start.
 | |
| 
 | |
|   @retval EFI_SUCCESS         This driver supports this device
 | |
|   @retval EFI_ALREADY_STARTED This driver is already running on this device
 | |
|   @retval other               This driver does not support this device
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Dhcp4DriverBindingSupported (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | |
|   IN EFI_HANDLE                   ControllerHandle,
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   ControllerHandle,
 | |
|                   &gEfiUdp4ServiceBindingProtocolGuid,
 | |
|                   NULL,
 | |
|                   This->DriverBindingHandle,
 | |
|                   ControllerHandle,
 | |
|                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | |
|                   );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Configure the default UDP child to receive all the DHCP traffics
 | |
|   on this network interface.
 | |
| 
 | |
|   @param[in]  UdpIo                  The UDP IO to configure
 | |
|   @param[in]  Context                The context to the function
 | |
| 
 | |
|   @retval EFI_SUCCESS            The UDP IO is successfully configured.
 | |
|   @retval Others                 Failed to configure the UDP child.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| DhcpConfigUdpIo (
 | |
|   IN UDP_IO  *UdpIo,
 | |
|   IN VOID    *Context
 | |
|   )
 | |
| {
 | |
|   EFI_UDP4_CONFIG_DATA  UdpConfigData;
 | |
| 
 | |
|   UdpConfigData.AcceptBroadcast    = TRUE;
 | |
|   UdpConfigData.AcceptPromiscuous  = FALSE;
 | |
|   UdpConfigData.AcceptAnyPort      = FALSE;
 | |
|   UdpConfigData.AllowDuplicatePort = TRUE;
 | |
|   UdpConfigData.TypeOfService      = 0;
 | |
|   UdpConfigData.TimeToLive         = 64;
 | |
|   UdpConfigData.DoNotFragment      = FALSE;
 | |
|   UdpConfigData.ReceiveTimeout     = 0;
 | |
|   UdpConfigData.TransmitTimeout    = 0;
 | |
| 
 | |
|   UdpConfigData.UseDefaultAddress = FALSE;
 | |
|   UdpConfigData.StationPort       = DHCP_CLIENT_PORT;
 | |
|   UdpConfigData.RemotePort        = DHCP_SERVER_PORT;
 | |
| 
 | |
|   ZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));
 | |
|   ZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
 | |
|   ZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));
 | |
| 
 | |
|   return UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Destroy the DHCP service. The Dhcp4 service may be partly initialized,
 | |
|   or partly destroyed. If a resource is destroyed, it is marked as so in
 | |
|   case the destroy failed and being called again later.
 | |
| 
 | |
|   @param[in]  DhcpSb                 The DHCP service instance to destroy.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Always return success.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Dhcp4CloseService (
 | |
|   IN DHCP_SERVICE  *DhcpSb
 | |
|   )
 | |
| {
 | |
|   DhcpCleanLease (DhcpSb);
 | |
| 
 | |
|   if (DhcpSb->UdpIo != NULL) {
 | |
|     UdpIoFreeIo (DhcpSb->UdpIo);
 | |
|     DhcpSb->UdpIo = NULL;
 | |
|   }
 | |
| 
 | |
|   if (DhcpSb->Timer != NULL) {
 | |
|     gBS->SetTimer (DhcpSb->Timer, TimerCancel, 0);
 | |
|     gBS->CloseEvent (DhcpSb->Timer);
 | |
| 
 | |
|     DhcpSb->Timer = NULL;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create a new DHCP service binding instance for the controller.
 | |
| 
 | |
|   @param[in]  Controller             The controller to install DHCP service binding
 | |
|                                      protocol onto
 | |
|   @param[in]  ImageHandle            The driver's image handle
 | |
|   @param[out] Service                The variable to receive the created DHCP service
 | |
|                                      instance.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource .
 | |
|   @retval EFI_SUCCESS            The DHCP service instance is created.
 | |
|   @retval other                  Other error occurs.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Dhcp4CreateService (
 | |
|   IN  EFI_HANDLE    Controller,
 | |
|   IN  EFI_HANDLE    ImageHandle,
 | |
|   OUT DHCP_SERVICE  **Service
 | |
|   )
 | |
| {
 | |
|   DHCP_SERVICE  *DhcpSb;
 | |
|   EFI_STATUS    Status;
 | |
| 
 | |
|   *Service = NULL;
 | |
|   DhcpSb   = AllocateZeroPool (sizeof (DHCP_SERVICE));
 | |
| 
 | |
|   if (DhcpSb == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   DhcpSb->Signature    = DHCP_SERVICE_SIGNATURE;
 | |
|   DhcpSb->ServiceState = DHCP_UNCONFIGED;
 | |
|   DhcpSb->Controller   = Controller;
 | |
|   DhcpSb->Image        = ImageHandle;
 | |
|   InitializeListHead (&DhcpSb->Children);
 | |
|   DhcpSb->DhcpState = Dhcp4Stopped;
 | |
|   DhcpSb->Xid       = NET_RANDOM (NetRandomInitSeed ());
 | |
|   CopyMem (
 | |
|     &DhcpSb->ServiceBinding,
 | |
|     &mDhcp4ServiceBindingTemplate,
 | |
|     sizeof (EFI_SERVICE_BINDING_PROTOCOL)
 | |
|     );
 | |
|   //
 | |
|   // Create various resources, UdpIo, Timer, and get Mac address
 | |
|   //
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_SIGNAL | EVT_TIMER,
 | |
|                   TPL_CALLBACK,
 | |
|                   DhcpOnTimerTick,
 | |
|                   DhcpSb,
 | |
|                   &DhcpSb->Timer
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   DhcpSb->UdpIo = UdpIoCreateIo (
 | |
|                     Controller,
 | |
|                     ImageHandle,
 | |
|                     DhcpConfigUdpIo,
 | |
|                     UDP_IO_UDP4_VERSION,
 | |
|                     NULL
 | |
|                     );
 | |
| 
 | |
|   if (DhcpSb->UdpIo == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   DhcpSb->HwLen  = (UINT8)DhcpSb->UdpIo->SnpMode.HwAddressSize;
 | |
|   DhcpSb->HwType = DhcpSb->UdpIo->SnpMode.IfType;
 | |
|   CopyMem (&DhcpSb->Mac, &DhcpSb->UdpIo->SnpMode.CurrentAddress, sizeof (DhcpSb->Mac));
 | |
| 
 | |
|   *Service = DhcpSb;
 | |
|   return EFI_SUCCESS;
 | |
| 
 | |
| ON_ERROR:
 | |
|   Dhcp4CloseService (DhcpSb);
 | |
|   FreePool (DhcpSb);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Start this driver on ControllerHandle. This service is called by the
 | |
|   EFI boot service ConnectController(). In order to make
 | |
|   drivers as small as possible, there are a few calling restrictions for
 | |
|   this service. ConnectController() must follow these
 | |
|   calling restrictions. If any other agent wishes to call Start() it
 | |
|   must also follow these calling restrictions.
 | |
| 
 | |
|   @param[in]  This                 Protocol instance pointer.
 | |
|   @param[in]  ControllerHandle     Handle of device to bind driver to
 | |
|   @param[in]  RemainingDevicePath  Optional parameter use to pick a specific child
 | |
|                                    device to start.
 | |
| 
 | |
|   @retval EFI_SUCCESS          This driver is added to ControllerHandle
 | |
|   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
 | |
|   @retval other                This driver does not support this device
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Dhcp4DriverBindingStart (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | |
|   IN EFI_HANDLE                   ControllerHandle,
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
 | |
|   )
 | |
| {
 | |
|   DHCP_SERVICE  *DhcpSb;
 | |
|   EFI_STATUS    Status;
 | |
| 
 | |
|   //
 | |
|   // First: test for the DHCP4 Protocol
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   ControllerHandle,
 | |
|                   &gEfiDhcp4ServiceBindingProtocolGuid,
 | |
|                   NULL,
 | |
|                   This->DriverBindingHandle,
 | |
|                   ControllerHandle,
 | |
|                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | |
|                   );
 | |
| 
 | |
|   if (Status == EFI_SUCCESS) {
 | |
|     return EFI_ALREADY_STARTED;
 | |
|   }
 | |
| 
 | |
|   Status = Dhcp4CreateService (ControllerHandle, This->DriverBindingHandle, &DhcpSb);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   ASSERT (DhcpSb != NULL);
 | |
| 
 | |
|   //
 | |
|   // Start the receiving
 | |
|   //
 | |
|   Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->SetTimer (DhcpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Install the Dhcp4ServiceBinding Protocol onto ControllerHandle
 | |
|   //
 | |
|   Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                   &ControllerHandle,
 | |
|                   &gEfiDhcp4ServiceBindingProtocolGuid,
 | |
|                   &DhcpSb->ServiceBinding,
 | |
|                   NULL
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| 
 | |
| ON_ERROR:
 | |
|   Dhcp4CloseService (DhcpSb);
 | |
|   FreePool (DhcpSb);
 | |
|   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
 | |
| Dhcp4DestroyChildEntry (
 | |
|   IN LIST_ENTRY  *Entry,
 | |
|   IN VOID        *Context
 | |
|   )
 | |
| {
 | |
|   DHCP_PROTOCOL                 *Instance;
 | |
|   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
 | |
| 
 | |
|   if ((Entry == NULL) || (Context == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Instance       = NET_LIST_USER_STRUCT_S (Entry, DHCP_PROTOCOL, Link, DHCP_PROTOCOL_SIGNATURE);
 | |
|   ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *)Context;
 | |
| 
 | |
|   return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Stop this driver on ControllerHandle. This service is called by the
 | |
|   EFI boot service DisconnectController(). In order to
 | |
|   make drivers as small as possible, there are a few calling
 | |
|   restrictions for this service. DisconnectController()
 | |
|   must follow these calling restrictions. If any other agent wishes
 | |
|   to call Stop() it must also follow these calling restrictions.
 | |
| 
 | |
|   @param[in]  This              Protocol instance pointer.
 | |
|   @param[in]  ControllerHandle  Handle of device to stop driver on
 | |
|   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
 | |
|                                 children is zero stop the entire bus driver.
 | |
|   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
 | |
| 
 | |
|   @retval EFI_SUCCESS       This driver is removed ControllerHandle
 | |
|   @retval other             This driver was not removed from this device
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Dhcp4DriverBindingStop (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
 | |
|   IN  EFI_HANDLE                   ControllerHandle,
 | |
|   IN  UINTN                        NumberOfChildren,
 | |
|   IN  EFI_HANDLE                   *ChildHandleBuffer
 | |
|   )
 | |
| {
 | |
|   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
 | |
|   DHCP_SERVICE                  *DhcpSb;
 | |
|   EFI_HANDLE                    NicHandle;
 | |
|   EFI_STATUS                    Status;
 | |
|   LIST_ENTRY                    *List;
 | |
|   UINTN                         ListLength;
 | |
| 
 | |
|   //
 | |
|   // DHCP driver opens UDP child, So, the ControllerHandle is the
 | |
|   // UDP child handle. locate the Nic handle first.
 | |
|   //
 | |
|   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
 | |
| 
 | |
|   if (NicHandle == NULL) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   NicHandle,
 | |
|                   &gEfiDhcp4ServiceBindingProtocolGuid,
 | |
|                   (VOID **)&ServiceBinding,
 | |
|                   This->DriverBindingHandle,
 | |
|                   NicHandle,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   DhcpSb = DHCP_SERVICE_FROM_THIS (ServiceBinding);
 | |
|   if (!IsListEmpty (&DhcpSb->Children)) {
 | |
|     //
 | |
|     // Destroy all the children instances before destroy the service.
 | |
|     //
 | |
|     List   = &DhcpSb->Children;
 | |
|     Status = NetDestroyLinkList (
 | |
|                List,
 | |
|                Dhcp4DestroyChildEntry,
 | |
|                ServiceBinding,
 | |
|                &ListLength
 | |
|                );
 | |
|     if (EFI_ERROR (Status) || (ListLength != 0)) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((NumberOfChildren == 0) && !IsListEmpty (&DhcpSb->Children)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   if ((NumberOfChildren == 0) && IsListEmpty (&DhcpSb->Children)) {
 | |
|     //
 | |
|     // Destroy the service itself if no child instance left.
 | |
|     //
 | |
|     DhcpSb->ServiceState = DHCP_DESTROY;
 | |
| 
 | |
|     gBS->UninstallProtocolInterface (
 | |
|            NicHandle,
 | |
|            &gEfiDhcp4ServiceBindingProtocolGuid,
 | |
|            ServiceBinding
 | |
|            );
 | |
| 
 | |
|     Dhcp4CloseService (DhcpSb);
 | |
| 
 | |
|     if (gDhcpControllerNameTable != NULL) {
 | |
|       FreeUnicodeStringTable (gDhcpControllerNameTable);
 | |
|       gDhcpControllerNameTable = NULL;
 | |
|     }
 | |
| 
 | |
|     FreePool (DhcpSb);
 | |
| 
 | |
|     Status = EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Initialize a new DHCP instance.
 | |
| 
 | |
|   @param  DhcpSb                 The dhcp service instance
 | |
|   @param  Instance               The dhcp instance to initialize
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DhcpInitProtocol (
 | |
|   IN     DHCP_SERVICE   *DhcpSb,
 | |
|   IN OUT DHCP_PROTOCOL  *Instance
 | |
|   )
 | |
| {
 | |
|   Instance->Signature = DHCP_PROTOCOL_SIGNATURE;
 | |
|   CopyMem (&Instance->Dhcp4Protocol, &mDhcp4ProtocolTemplate, sizeof (Instance->Dhcp4Protocol));
 | |
|   InitializeListHead (&Instance->Link);
 | |
|   Instance->Handle           = NULL;
 | |
|   Instance->Service          = DhcpSb;
 | |
|   Instance->InDestroy        = FALSE;
 | |
|   Instance->CompletionEvent  = NULL;
 | |
|   Instance->RenewRebindEvent = NULL;
 | |
|   Instance->Token            = NULL;
 | |
|   Instance->UdpIo            = NULL;
 | |
|   Instance->ElaspedTime      = 0;
 | |
|   NetbufQueInit (&Instance->ResponseQueue);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Creates a child handle and installs a protocol.
 | |
| 
 | |
|   The CreateChild() function installs a protocol on ChildHandle.
 | |
|   If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
 | |
|   If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
 | |
| 
 | |
|   @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
 | |
|   @param  ChildHandle Pointer to the handle of the child to create. If it is NULL,
 | |
|                       then a new handle is created. If it is a pointer to an existing UEFI handle,
 | |
|                       then the protocol is added to the existing UEFI handle.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The protocol was added to ChildHandle.
 | |
|   @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
 | |
|   @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create
 | |
|                                 the child
 | |
|   @retval other                 The child handle was not created
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Dhcp4ServiceBindingCreateChild (
 | |
|   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
 | |
|   IN EFI_HANDLE                    *ChildHandle
 | |
|   )
 | |
| {
 | |
|   DHCP_SERVICE   *DhcpSb;
 | |
|   DHCP_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;
 | |
|   }
 | |
| 
 | |
|   DhcpSb = DHCP_SERVICE_FROM_THIS (This);
 | |
|   DhcpInitProtocol (DhcpSb, Instance);
 | |
| 
 | |
|   //
 | |
|   // Install DHCP4 onto ChildHandle
 | |
|   //
 | |
|   Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                   ChildHandle,
 | |
|                   &gEfiDhcp4ProtocolGuid,
 | |
|                   &Instance->Dhcp4Protocol,
 | |
|                   NULL
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     FreePool (Instance);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Instance->Handle = *ChildHandle;
 | |
| 
 | |
|   //
 | |
|   // Open the Udp4 protocol BY_CHILD.
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   DhcpSb->UdpIo->UdpHandle,
 | |
|                   &gEfiUdp4ProtocolGuid,
 | |
|                   (VOID **)&Udp4,
 | |
|                   gDhcp4DriverBinding.DriverBindingHandle,
 | |
|                   Instance->Handle,
 | |
|                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->UninstallMultipleProtocolInterfaces (
 | |
|            Instance->Handle,
 | |
|            &gEfiDhcp4ProtocolGuid,
 | |
|            &Instance->Dhcp4Protocol,
 | |
|            NULL
 | |
|            );
 | |
| 
 | |
|     FreePool (Instance);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
| 
 | |
|   InsertTailList (&DhcpSb->Children, &Instance->Link);
 | |
|   DhcpSb->NumChildren++;
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Destroys a child handle with a protocol installed on it.
 | |
| 
 | |
|   The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
 | |
|   that was installed by CreateChild() from ChildHandle. If the removed protocol is the
 | |
|   last protocol on ChildHandle, then ChildHandle is destroyed.
 | |
| 
 | |
|   @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
 | |
|   @param  ChildHandle Handle of the child to destroy
 | |
| 
 | |
|   @retval EFI_SUCCESS           The protocol was removed from ChildHandle.
 | |
|   @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.
 | |
|   @retval EFI_INVALID_PARAMETER Child handle is NULL.
 | |
|   @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle
 | |
|                                 because its services are being used.
 | |
|   @retval other                 The child handle was not destroyed
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Dhcp4ServiceBindingDestroyChild (
 | |
|   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
 | |
|   IN EFI_HANDLE                    ChildHandle
 | |
|   )
 | |
| {
 | |
|   DHCP_SERVICE        *DhcpSb;
 | |
|   DHCP_PROTOCOL       *Instance;
 | |
|   EFI_DHCP4_PROTOCOL  *Dhcp;
 | |
|   EFI_TPL             OldTpl;
 | |
|   EFI_STATUS          Status;
 | |
| 
 | |
|   if ((This == NULL) || (ChildHandle == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrieve the private context data structures
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   ChildHandle,
 | |
|                   &gEfiDhcp4ProtocolGuid,
 | |
|                   (VOID **)&Dhcp,
 | |
|                   gDhcp4DriverBinding.DriverBindingHandle,
 | |
|                   ChildHandle,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   Instance = DHCP_INSTANCE_FROM_THIS (Dhcp);
 | |
|   DhcpSb   = DHCP_SERVICE_FROM_THIS (This);
 | |
| 
 | |
|   if (Instance->Service != DhcpSb) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // A child can be destroyed more than once. For example,
 | |
|   // Dhcp4DriverBindingStop will destroy all of its children.
 | |
|   // when caller driver is being stopped, it will destroy the
 | |
|   // dhcp child it opens.
 | |
|   //
 | |
|   if (Instance->InDestroy) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   OldTpl              = gBS->RaiseTPL (TPL_CALLBACK);
 | |
|   Instance->InDestroy = TRUE;
 | |
| 
 | |
|   //
 | |
|   // Close the Udp4 protocol.
 | |
|   //
 | |
|   gBS->CloseProtocol (
 | |
|          DhcpSb->UdpIo->UdpHandle,
 | |
|          &gEfiUdp4ProtocolGuid,
 | |
|          gDhcp4DriverBinding.DriverBindingHandle,
 | |
|          ChildHandle
 | |
|          );
 | |
| 
 | |
|   //
 | |
|   // Uninstall the DHCP4 protocol first to enable a top down destruction.
 | |
|   //
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   Status = gBS->UninstallProtocolInterface (
 | |
|                   ChildHandle,
 | |
|                   &gEfiDhcp4ProtocolGuid,
 | |
|                   Dhcp
 | |
|                   );
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Instance->InDestroy = FALSE;
 | |
| 
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (DhcpSb->ActiveChild == Instance) {
 | |
|     DhcpYieldControl (DhcpSb);
 | |
|   }
 | |
| 
 | |
|   RemoveEntryList (&Instance->Link);
 | |
|   DhcpSb->NumChildren--;
 | |
| 
 | |
|   if (Instance->UdpIo != NULL) {
 | |
|     UdpIoCleanIo (Instance->UdpIo);
 | |
|     gBS->CloseProtocol (
 | |
|            Instance->UdpIo->UdpHandle,
 | |
|            &gEfiUdp4ProtocolGuid,
 | |
|            Instance->Service->Image,
 | |
|            Instance->Handle
 | |
|            );
 | |
|     UdpIoFreeIo (Instance->UdpIo);
 | |
|     Instance->UdpIo = NULL;
 | |
|     Instance->Token = NULL;
 | |
|   }
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   FreePool (Instance);
 | |
|   return EFI_SUCCESS;
 | |
| }
 |