X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FDhcp4Dxe%2FDhcp4Driver.c;h=e891b68883070733d0e419a97c8e7e32c5c2c202;hp=08d6076bda4f2c4b1aa1de54a5758358d7b22369;hb=c0fd7f734e2d33e22215899b40a47b843129541d;hpb=772db4bb33ae66fa20e39f786b5f80d107d450a5 diff --git a/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Driver.c b/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Driver.c index 08d6076bda..e891b68883 100644 --- a/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Driver.c +++ b/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Driver.c @@ -1,21 +1,7 @@ /** @file -Copyright (c) 2006 - 2007, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - -Module Name: - - Dhcp4Driver.c - -Abstract: - +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -31,59 +17,59 @@ EFI_DRIVER_BINDING_PROTOCOL gDhcp4DriverBinding = { NULL }; -EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplete = { +EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplate = { Dhcp4ServiceBindingCreateChild, Dhcp4ServiceBindingDestroyChild }; -//@MT: EFI_DRIVER_ENTRY_POINT (Dhcp4DriverEntryPoint) +/** + 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 ) -/*++ - -Routine Description: - - Entry point of the DHCP driver to install various protocols. - -Arguments: - - ImageHandle - The driver's image handle - SystemTable - The system table - -Returns: - - EFI_SUCCESS - All the related protocols are installed. - Others - Failed to install the protocols. - ---*/ { - return NetLibInstallAllDriverProtocols ( + return EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, &gDhcp4DriverBinding, ImageHandle, &gDhcp4ComponentName, - NULL, - NULL + &gDhcp4ComponentName2 ); } /** - Test to see if DHCP driver supports the ControllerHandle. - - @param This Protocol instance pointer. - @param ControllerHandle Handle of device to test - @param RemainingDevicePath Optional parameter use to pick a specific child - device to start. - - @retval EFI_SUCCES This driver supports this device - @retval other This driver does not support this device + 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 @@ -114,16 +100,17 @@ Dhcp4DriverBindingSupported ( Configure the default UDP child to receive all the DHCP traffics on this network interface. - @param UdpIo The UDP IO port to configure - @param Context The context to the function + @param[in] UdpIo The UDP IO to configure + @param[in] Context The context to the function - @retval EFI_SUCCESS The UDP IO port is successfully configured. + @retval EFI_SUCCESS The UDP IO is successfully configured. @retval Others Failed to configure the UDP child. **/ EFI_STATUS +EFIAPI DhcpConfigUdpIo ( - IN UDP_IO_PORT *UdpIo, + IN UDP_IO *UdpIo, IN VOID *Context ) { @@ -143,23 +130,23 @@ DhcpConfigUdpIo ( UdpConfigData.StationPort = DHCP_CLIENT_PORT; UdpConfigData.RemotePort = DHCP_SERVER_PORT; - NetZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS)); - NetZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS)); - NetZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS)); + ZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS)); + ZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS)); + ZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS)); - return UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfigData);; + return UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData);; } /** - Destory the DHCP service. The Dhcp4 service may be partly initialized, - or partly destoried. If a resource is destoried, it is marked as so in - case the destory failed and being called again later. + 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 DhcpSb The DHCP service instance to destory. + @param[in] DhcpSb The DHCP service instance to destroy. - @retval EFI_SUCCESS The DHCP service is successfully closed. + @retval EFI_SUCCESS Always return success. **/ EFI_STATUS @@ -170,7 +157,7 @@ Dhcp4CloseService ( DhcpCleanLease (DhcpSb); if (DhcpSb->UdpIo != NULL) { - UdpIoFreePort (DhcpSb->UdpIo); + UdpIoFreeIo (DhcpSb->UdpIo); DhcpSb->UdpIo = NULL; } @@ -189,14 +176,15 @@ Dhcp4CloseService ( /** Create a new DHCP service binding instance for the controller. - @param Controller The controller to install DHCP service binding - protocol onto - @param ImageHandle The driver's image handle - @param Service The variable to receive the created DHCP service - instance. + @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 @@ -210,22 +198,24 @@ Dhcp4CreateService ( EFI_STATUS Status; *Service = NULL; - DhcpSb = NetAllocateZeroPool (sizeof (DHCP_SERVICE)); + DhcpSb = AllocateZeroPool (sizeof (DHCP_SERVICE)); if (DhcpSb == NULL) { return EFI_OUT_OF_RESOURCES; } DhcpSb->Signature = DHCP_SERVICE_SIGNATURE; - DhcpSb->ServiceBinding = mDhcp4ServiceBindingTemplete; DhcpSb->ServiceState = DHCP_UNCONFIGED; - DhcpSb->InDestory = FALSE; DhcpSb->Controller = Controller; DhcpSb->Image = ImageHandle; - NetListInit (&DhcpSb->Children); + 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 // @@ -241,7 +231,13 @@ Dhcp4CreateService ( goto ON_ERROR; } - DhcpSb->UdpIo = UdpIoCreatePort (Controller, ImageHandle, DhcpConfigUdpIo, NULL); + DhcpSb->UdpIo = UdpIoCreateIo ( + Controller, + ImageHandle, + DhcpConfigUdpIo, + UDP_IO_UDP4_VERSION, + NULL + ); if (DhcpSb->UdpIo == NULL) { Status = EFI_OUT_OF_RESOURCES; @@ -250,30 +246,35 @@ Dhcp4CreateService ( DhcpSb->HwLen = (UINT8) DhcpSb->UdpIo->SnpMode.HwAddressSize; DhcpSb->HwType = DhcpSb->UdpIo->SnpMode.IfType; - CopyMem (&DhcpSb->Mac, &DhcpSb->UdpIo->SnpMode.CurrentAddress, sizeof (EFI_MAC_ADDRESS)); + CopyMem (&DhcpSb->Mac, &DhcpSb->UdpIo->SnpMode.CurrentAddress, sizeof (DhcpSb->Mac)); *Service = DhcpSb; return EFI_SUCCESS; ON_ERROR: Dhcp4CloseService (DhcpSb); - NetFreePool (DhcpSb); + FreePool (DhcpSb); return Status; } /** - Start this driver on ControllerHandle. - - @param This Protocol instance pointer. - @param ControllerHandle Handle of device to bind driver to - @param RemainingDevicePath Optional parameter use to pick a specific child - device to start. - - @retval EFI_SUCCES 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 + 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 @@ -308,7 +309,16 @@ Dhcp4DriverBindingStart ( 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)) { @@ -333,22 +343,57 @@ Dhcp4DriverBindingStart ( ON_ERROR: Dhcp4CloseService (DhcpSb); - NetFreePool (DhcpSb); + FreePool (DhcpSb); return Status; } - /** - Stop this driver on ControllerHandle. + 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; + } - @param This Protocol instance pointer. - @param ControllerHandle Handle of device to stop driver on - @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number - of children is zero stop the entire bus driver. - @param ChildHandleBuffer List of Child Handles to Stop. + Instance = NET_LIST_USER_STRUCT_S (Entry, DHCP_PROTOCOL, Link, DHCP_PROTOCOL_SIGNATURE); + ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *) Context; - @retval EFI_SUCCES This driver is removed ControllerHandle - @retval other This driver was not removed from this device + 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 @@ -362,10 +407,10 @@ Dhcp4DriverBindingStop ( { EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; DHCP_SERVICE *DhcpSb; - DHCP_PROTOCOL *Instance; EFI_HANDLE NicHandle; EFI_STATUS Status; - EFI_TPL OldTpl; + LIST_ENTRY *List; + UINTN ListLength; // // DHCP driver opens UDP child, So, the ControllerHandle is the @@ -391,93 +436,98 @@ Dhcp4DriverBindingStop ( } DhcpSb = DHCP_SERVICE_FROM_THIS (ServiceBinding); - - if (DhcpSb->InDestory) { - return EFI_SUCCESS; + if (!IsListEmpty (&DhcpSb->Children)) { + // + // Destroy all the children instances before destory the service. + // + List = &DhcpSb->Children; + Status = NetDestroyLinkList ( + List, + Dhcp4DestroyChildEntry, + ServiceBinding, + &ListLength + ); + if (EFI_ERROR (Status) || ListLength != 0) { + Status = EFI_DEVICE_ERROR; + } } - OldTpl = NET_RAISE_TPL (NET_TPL_LOCK); - DhcpSb->InDestory = TRUE; - - // - // Don't use NET_LIST_FOR_EACH_SAFE here, Dhcp4ServiceBindingDestoryChild - // may cause other child to be deleted. - // - while (!NetListIsEmpty (&DhcpSb->Children)) { - Instance = NET_LIST_HEAD (&DhcpSb->Children, DHCP_PROTOCOL, Link); - Dhcp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle); - } - - if (DhcpSb->NumChildren != 0) { + if (NumberOfChildren == 0 && !IsListEmpty (&DhcpSb->Children)) { Status = EFI_DEVICE_ERROR; - goto ON_ERROR; } - DhcpSb->ServiceState = DHCP_DESTORY; + if (NumberOfChildren == 0 && IsListEmpty (&DhcpSb->Children)) { + // + // Destroy the service itself if no child instance left. + // + DhcpSb->ServiceState = DHCP_DESTROY; - Status = gBS->UninstallProtocolInterface ( - NicHandle, - &gEfiDhcp4ServiceBindingProtocolGuid, - ServiceBinding - ); + gBS->UninstallProtocolInterface ( + NicHandle, + &gEfiDhcp4ServiceBindingProtocolGuid, + ServiceBinding + ); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } + Dhcp4CloseService (DhcpSb); - Dhcp4CloseService (DhcpSb); - NET_RESTORE_TPL (OldTpl); + if (gDhcpControllerNameTable != NULL) { + FreeUnicodeStringTable (gDhcpControllerNameTable); + gDhcpControllerNameTable = NULL; + } + FreePool (DhcpSb); - NetFreePool (DhcpSb); - return EFI_SUCCESS; + Status = EFI_SUCCESS; + } -ON_ERROR: - DhcpSb->InDestory = FALSE; - NET_RESTORE_TPL (OldTpl); return Status; } /** - Initialize a new DHCP child + Initialize a new DHCP instance. @param DhcpSb The dhcp service instance @param Instance The dhcp instance to initialize - @return None - **/ VOID DhcpInitProtocol ( - IN DHCP_SERVICE *DhcpSb, - IN DHCP_PROTOCOL *Instance + IN DHCP_SERVICE *DhcpSb, + IN OUT DHCP_PROTOCOL *Instance ) { Instance->Signature = DHCP_PROTOCOL_SIGNATURE; - CopyMem (&Instance->Dhcp4Protocol, &mDhcp4ProtocolTemplate, sizeof (EFI_DHCP4_PROTOCOL)); - NetListInit (&Instance->Link); + CopyMem (&Instance->Dhcp4Protocol, &mDhcp4ProtocolTemplate, sizeof (Instance->Dhcp4Protocol)); + InitializeListHead (&Instance->Link); Instance->Handle = NULL; Instance->Service = DhcpSb; - Instance->InDestory = FALSE; + 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 with a set of DHCP4 services. + Creates a child handle and installs a protocol. - @param This Protocol instance pointer. - @param ChildHandle Pointer to the handle of the child to create. If - it is NULL, then a new handle is created. If it - is not NULL, then the DHCP4 services are added to - the existing child handle. + 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. - @retval EFI_SUCCES The child handle was created with the DHCP4 - services - @retval EFI_OUT_OF_RESOURCES There are not enough resources to create the child - @retval other The child handle was not created + @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_SUCCES 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 @@ -497,7 +547,7 @@ Dhcp4ServiceBindingCreateChild ( return EFI_INVALID_PARAMETER; } - Instance = NetAllocatePool (sizeof (*Instance)); + Instance = AllocatePool (sizeof (*Instance)); if (Instance == NULL) { return EFI_OUT_OF_RESOURCES; @@ -517,7 +567,7 @@ Dhcp4ServiceBindingCreateChild ( ); if (EFI_ERROR (Status)) { - NetFreePool (Instance); + FreePool (Instance); return Status; } @@ -542,34 +592,37 @@ Dhcp4ServiceBindingCreateChild ( NULL ); - NetFreePool (Instance); + FreePool (Instance); return Status; } - OldTpl = NET_RAISE_TPL (NET_TPL_LOCK); + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - NetListInsertTail (&DhcpSb->Children, &Instance->Link); + InsertTailList (&DhcpSb->Children, &Instance->Link); DhcpSb->NumChildren++; - NET_RESTORE_TPL (OldTpl); + gBS->RestoreTPL (OldTpl); return EFI_SUCCESS; } /** - Destroys a child handle with a set of DHCP4 services. + 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 Protocol instance pointer. - @param ChildHandle Handle of the child to destroy + @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. + @param ChildHandle Handle of the child to destroy - @retval EFI_SUCCES The DHCP4 service is removed from the child handle - @retval EFI_UNSUPPORTED The child handle does not support the DHCP4 - service - @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle. - @retval EFI_ACCESS_DENIED The child handle could not be destroyed because - its DHCP4 services are being used. - @retval other The child handle was not destroyed + @retval EFI_SUCCES 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 @@ -613,17 +666,17 @@ Dhcp4ServiceBindingDestroyChild ( } // - // A child can be destoried more than once. For example, - // Dhcp4DriverBindingStop will destory all of its children. - // when caller driver is being stopped, it will destory the + // 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->InDestory) { + if (Instance->InDestroy) { return EFI_SUCCESS; } - OldTpl = NET_RAISE_TPL (NET_TPL_LOCK); - Instance->InDestory = TRUE; + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + Instance->InDestroy = TRUE; // // Close the Udp4 protocol. @@ -638,16 +691,17 @@ Dhcp4ServiceBindingDestroyChild ( // // 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->InDestory = FALSE; + Instance->InDestroy = FALSE; - NET_RESTORE_TPL (OldTpl); + gBS->RestoreTPL (OldTpl); return Status; } @@ -655,11 +709,24 @@ Dhcp4ServiceBindingDestroyChild ( DhcpYieldControl (DhcpSb); } - NetListRemoveEntry (&Instance->Link); + RemoveEntryList (&Instance->Link); DhcpSb->NumChildren--; - NET_RESTORE_TPL (OldTpl); + 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); - NetFreePool (Instance); + FreePool (Instance); return EFI_SUCCESS; }