3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 The driver binding and service binding protocol for IP4 driver.
25 EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding
= {
26 Ip4DriverBindingSupported
,
27 Ip4DriverBindingStart
,
35 This is the declaration of an EFI image entry point. This entry point is
36 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
37 both device drivers and bus drivers.
39 The entry point for IP4 driver which install the driver
40 binding and component name protocol on its image.
42 @param ImageHandle The firmware allocated handle for the UEFI image.
43 @param SystemTable A pointer to the EFI System Table.
45 @retval EFI_SUCCESS The operation completed successfully.
46 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
52 IN EFI_HANDLE ImageHandle
,
53 IN EFI_SYSTEM_TABLE
*SystemTable
56 return EfiLibInstallDriverBindingComponentName2 (
67 Test to see if this driver supports ControllerHandle. This service
68 is called by the EFI boot service ConnectController(). In
69 order to make drivers as small as possible, there are a few calling
70 restrictions for this service. ConnectController() must
71 follow these calling restrictions. If any other agent wishes to call
72 Supported() it must also follow these calling restrictions.
74 @param This Protocol instance pointer.
75 @param ControllerHandle Handle of device to test
76 @param RemainingDevicePath Optional parameter use to pick a specific child
79 @retval EFI_SUCCESS This driver supports this device
80 @retval EFI_ALREADY_STARTED This driver is already running on this device
81 @retval other This driver does not support this device
86 Ip4DriverBindingSupported (
87 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
88 IN EFI_HANDLE ControllerHandle
,
89 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
95 // Test for the MNP service binding Protocol
97 Status
= gBS
->OpenProtocol (
99 &gEfiManagedNetworkServiceBindingProtocolGuid
,
101 This
->DriverBindingHandle
,
103 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
106 if (EFI_ERROR (Status
)) {
111 // Test for the Arp service binding Protocol
113 Status
= gBS
->OpenProtocol (
115 &gEfiArpServiceBindingProtocolGuid
,
117 This
->DriverBindingHandle
,
119 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
132 Create a new IP4 driver service binding private instance.
134 @param Controller The controller that has MNP service binding
136 @param ImageHandle The IP4 driver's image handle
137 @param Service The variable to receive the newly created IP4
140 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource
141 @retval EFI_SUCCESS A new IP4 service binding private is created.
142 @retval other Other error occurs.
147 IN EFI_HANDLE Controller
,
148 IN EFI_HANDLE ImageHandle
,
149 OUT IP4_SERVICE
**Service
155 ASSERT (Service
!= NULL
);
160 // allocate a service private data then initialize all the filed to
161 // empty resources, so if any thing goes wrong when allocating
162 // resources, Ip4CleanService can be called to clean it up.
164 IpSb
= AllocatePool (sizeof (IP4_SERVICE
));
167 return EFI_OUT_OF_RESOURCES
;
170 IpSb
->Signature
= IP4_SERVICE_SIGNATURE
;
171 IpSb
->ServiceBinding
.CreateChild
= Ip4ServiceBindingCreateChild
;
172 IpSb
->ServiceBinding
.DestroyChild
= Ip4ServiceBindingDestroyChild
;
173 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
174 IpSb
->InDestory
= FALSE
;
176 IpSb
->NumChildren
= 0;
177 InitializeListHead (&IpSb
->Children
);
179 InitializeListHead (&IpSb
->Interfaces
);
180 IpSb
->DefaultInterface
= NULL
;
181 IpSb
->DefaultRouteTable
= NULL
;
183 Ip4InitAssembleTable (&IpSb
->Assemble
);
185 IpSb
->IgmpCtrl
.Igmpv1QuerySeen
= 0;
186 InitializeListHead (&IpSb
->IgmpCtrl
.Groups
);
188 IpSb
->Image
= ImageHandle
;
189 IpSb
->Controller
= Controller
;
191 IpSb
->MnpChildHandle
= NULL
;
194 IpSb
->MnpConfigData
.ReceivedQueueTimeoutValue
= 0;
195 IpSb
->MnpConfigData
.TransmitQueueTimeoutValue
= 0;
196 IpSb
->MnpConfigData
.ProtocolTypeFilter
= IP4_ETHER_PROTO
;
197 IpSb
->MnpConfigData
.EnableUnicastReceive
= TRUE
;
198 IpSb
->MnpConfigData
.EnableMulticastReceive
= TRUE
;
199 IpSb
->MnpConfigData
.EnableBroadcastReceive
= TRUE
;
200 IpSb
->MnpConfigData
.EnablePromiscuousReceive
= FALSE
;
201 IpSb
->MnpConfigData
.FlushQueuesOnReset
= TRUE
;
202 IpSb
->MnpConfigData
.EnableReceiveTimestamps
= FALSE
;
203 IpSb
->MnpConfigData
.DisableBackgroundPolling
= FALSE
;
205 ZeroMem (&IpSb
->SnpMode
, sizeof (EFI_SIMPLE_NETWORK_MODE
));
208 IpSb
->Ip4Config
= NULL
;
209 IpSb
->DoneEvent
= NULL
;
210 IpSb
->ReconfigEvent
= NULL
;
211 IpSb
->ActiveEvent
= NULL
;
214 // Create various resources. First create the route table, timer
215 // event and MNP child. IGMP, interface's initialization depend
218 IpSb
->DefaultRouteTable
= Ip4CreateRouteTable ();
220 if (IpSb
->DefaultRouteTable
== NULL
) {
221 Status
= EFI_OUT_OF_RESOURCES
;
225 Status
= gBS
->CreateEvent (
226 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
233 if (EFI_ERROR (Status
)) {
237 Status
= NetLibCreateServiceChild (
240 &gEfiManagedNetworkServiceBindingProtocolGuid
,
241 &IpSb
->MnpChildHandle
244 if (EFI_ERROR (Status
)) {
248 Status
= gBS
->OpenProtocol (
249 IpSb
->MnpChildHandle
,
250 &gEfiManagedNetworkProtocolGuid
,
251 (VOID
**) &IpSb
->Mnp
,
254 EFI_OPEN_PROTOCOL_BY_DRIVER
257 if (EFI_ERROR (Status
)) {
261 Status
= Ip4ServiceConfigMnp (IpSb
, TRUE
);
263 if (EFI_ERROR (Status
)) {
267 Status
= IpSb
->Mnp
->GetModeData (IpSb
->Mnp
, NULL
, &IpSb
->SnpMode
);
269 if (EFI_ERROR (Status
)) {
273 Status
= Ip4InitIgmp (IpSb
);
275 if (EFI_ERROR (Status
)) {
279 IpSb
->DefaultInterface
= Ip4CreateInterface (IpSb
->Mnp
, Controller
, ImageHandle
);
281 if (IpSb
->DefaultInterface
== NULL
) {
282 Status
= EFI_OUT_OF_RESOURCES
;
286 InsertHeadList (&IpSb
->Interfaces
, &IpSb
->DefaultInterface
->Link
);
288 IpSb
->MacString
= NULL
;
294 Ip4CleanService (IpSb
);
295 gBS
->FreePool (IpSb
);
302 Clean up a IP4 service binding instance. It will release all
303 the resource allocated by the instance. The instance may be
304 partly initialized, or partly destroyed. If a resource is
305 destroyed, it is marked as that in case the destory failed and
306 being called again later.
308 @param IpSb The IP4 serviceing binding instance to clean up
310 @retval EFI_SUCCESS The resource used by the instance are cleaned up
311 @retval other Failed to clean up some of the resources.
321 if (IpSb
->DefaultInterface
!= NULL
) {
322 Status
= Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
324 if (EFI_ERROR (Status
)) {
328 IpSb
->DefaultInterface
= NULL
;
331 if (IpSb
->DefaultRouteTable
!= NULL
) {
332 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
333 IpSb
->DefaultRouteTable
= NULL
;
336 Ip4CleanAssembleTable (&IpSb
->Assemble
);
338 if (IpSb
->MnpChildHandle
!= NULL
) {
339 if (IpSb
->Mnp
!= NULL
) {
341 IpSb
->MnpChildHandle
,
342 &gEfiManagedNetworkProtocolGuid
,
350 NetLibDestroyServiceChild (
353 &gEfiManagedNetworkServiceBindingProtocolGuid
,
357 IpSb
->MnpChildHandle
= NULL
;
360 if (IpSb
->Timer
!= NULL
) {
361 gBS
->SetTimer (IpSb
->Timer
, TimerCancel
, 0);
362 gBS
->CloseEvent (IpSb
->Timer
);
367 if (IpSb
->Ip4Config
!= NULL
) {
368 IpSb
->Ip4Config
->Stop (IpSb
->Ip4Config
);
372 &gEfiIp4ConfigProtocolGuid
,
377 gBS
->CloseEvent (IpSb
->DoneEvent
);
378 gBS
->CloseEvent (IpSb
->ReconfigEvent
);
379 IpSb
->ActiveEvent
= NULL
;
380 IpSb
->Ip4Config
= NULL
;
388 Start this driver on ControllerHandle. This service is called by the
389 EFI boot service ConnectController(). In order to make
390 drivers as small as possible, there are a few calling restrictions for
391 this service. ConnectController() must follow these
392 calling restrictions. If any other agent wishes to call Start() it
393 must also follow these calling restrictions.
395 @param This Protocol instance pointer.
396 @param ControllerHandle Handle of device to bind driver to
397 @param RemainingDevicePath Optional parameter use to pick a specific child
400 @retval EFI_SUCCESS This driver is added to ControllerHandle
401 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
402 @retval other This driver does not support this device
407 Ip4DriverBindingStart (
408 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
409 IN EFI_HANDLE ControllerHandle
,
410 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
417 // Test for the Ip4 service binding protocol
419 Status
= gBS
->OpenProtocol (
421 &gEfiIp4ServiceBindingProtocolGuid
,
423 This
->DriverBindingHandle
,
425 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
428 if (Status
== EFI_SUCCESS
) {
429 return EFI_ALREADY_STARTED
;
432 Status
= Ip4CreateService (ControllerHandle
, This
->DriverBindingHandle
, &IpSb
);
434 if (EFI_ERROR (Status
)) {
439 // Install the Ip4ServiceBinding Protocol onto ControlerHandle
441 Status
= gBS
->InstallMultipleProtocolInterfaces (
443 &gEfiIp4ServiceBindingProtocolGuid
,
444 &IpSb
->ServiceBinding
,
448 if (EFI_ERROR (Status
)) {
453 // ready to go: start the receiving and timer
455 Status
= Ip4ReceiveFrame (IpSb
->DefaultInterface
, NULL
, Ip4AccpetFrame
, IpSb
);
457 if (EFI_ERROR (Status
)) {
458 goto UNINSTALL_PROTOCOL
;
461 Status
= gBS
->SetTimer (IpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
463 if (EFI_ERROR (Status
)) {
464 goto UNINSTALL_PROTOCOL
;
468 // Initialize the IP4 ID
470 mIp4Id
= (UINT16
)NET_RANDOM (NetRandomInitSeed ());
472 Ip4SetVariableData (IpSb
);
477 gBS
->UninstallProtocolInterface (
479 &gEfiIp4ServiceBindingProtocolGuid
,
480 &IpSb
->ServiceBinding
484 Ip4CleanService (IpSb
);
485 gBS
->FreePool (IpSb
);
492 Stop this driver on ControllerHandle. This service is called by the
493 EFI boot service DisconnectController(). In order to
494 make drivers as small as possible, there are a few calling
495 restrictions for this service. DisconnectController()
496 must follow these calling restrictions. If any other agent wishes
497 to call Stop() it must also follow these calling restrictions.
499 @param This Protocol instance pointer.
500 @param ControllerHandle Handle of device to stop driver on
501 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
502 children is zero stop the entire bus driver.
503 @param ChildHandleBuffer List of Child Handles to Stop.
505 @retval EFI_SUCCESS This driver is removed ControllerHandle
506 @retval other This driver was not removed from this device
511 Ip4DriverBindingStop (
512 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
513 IN EFI_HANDLE ControllerHandle
,
514 IN UINTN NumberOfChildren
,
515 IN EFI_HANDLE
*ChildHandleBuffer
518 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
520 IP4_PROTOCOL
*IpInstance
;
521 EFI_HANDLE NicHandle
;
528 // IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol
529 // by driver. So the ControllerHandle may be the MNP child handle, ARP child
530 // handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed
531 // in the NIC handle.
534 // First, check whether it is the IP4_CONFIG protocol being uninstalled.
535 // IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary
536 // to clean up the default configuration if IP4_CONFIG is being stopped.
538 Status
= gBS
->OpenProtocol (
540 &gEfiIp4ConfigProtocolGuid
,
542 This
->DriverBindingHandle
,
544 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
547 if (Status
== EFI_SUCCESS
) {
549 // Retrieve the IP4 service binding protocol. If failed, it is
550 // likely that Ip4 ServiceBinding is uninstalled already. In this
551 // case, return immediately.
553 Status
= gBS
->OpenProtocol (
555 &gEfiIp4ServiceBindingProtocolGuid
,
556 (VOID
**) &ServiceBinding
,
557 This
->DriverBindingHandle
,
559 EFI_OPEN_PROTOCOL_GET_PROTOCOL
562 if (EFI_ERROR (Status
)) {
563 return EFI_DEVICE_ERROR
;
566 IpSb
= IP4_SERVICE_FROM_PROTOCOL (ServiceBinding
);
568 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
570 if (IpSb
->Ip4Config
!= NULL
&& (IpSb
->State
!= IP4_SERVICE_DESTORY
)) {
572 IpSb
->Ip4Config
->Stop (IpSb
->Ip4Config
);
574 Status
= gBS
->CloseProtocol (
576 &gEfiIp4ConfigProtocolGuid
,
581 if (EFI_ERROR (Status
)) {
582 gBS
->RestoreTPL (OldTpl
);
587 // If the auto configure hasn't complete, mark it as not started.
589 if (IpSb
->State
== IP4_SERVICE_STARTED
) {
590 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
593 IpSb
->Ip4Config
= NULL
;
594 gBS
->CloseEvent (IpSb
->DoneEvent
);
595 gBS
->CloseEvent (IpSb
->ReconfigEvent
);
598 gBS
->RestoreTPL (OldTpl
);
603 // Either MNP or ARP protocol is being uninstalled. The controller
604 // handle is either the MNP child or ARP child. But, the IP4's
605 // service binding is installed on the NIC handle. So, need to open
606 // the protocol info to find the NIC handle.
609 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiManagedNetworkProtocolGuid
);
611 if (NicHandle
== NULL
) {
612 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiArpProtocolGuid
);
616 if (NicHandle
== NULL
) {
617 return EFI_DEVICE_ERROR
;
621 // Retrieve the IP4 service binding protocol
623 Status
= gBS
->OpenProtocol (
625 &gEfiIp4ServiceBindingProtocolGuid
,
626 (VOID
**) &ServiceBinding
,
627 This
->DriverBindingHandle
,
629 EFI_OPEN_PROTOCOL_GET_PROTOCOL
632 if (EFI_ERROR (Status
)) {
633 return EFI_DEVICE_ERROR
;
636 IpSb
= IP4_SERVICE_FROM_PROTOCOL (ServiceBinding
);
638 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
640 if (IpSb
->InDestory
) {
641 gBS
->RestoreTPL (OldTpl
);
646 while (!IsListEmpty (&IpSb
->Children
)) {
647 IpInstance
= NET_LIST_HEAD (&IpSb
->Children
, IP4_PROTOCOL
, Link
);
649 ServiceBinding
->DestroyChild (ServiceBinding
, IpInstance
->Handle
);
652 if (IpSb
->NumChildren
!= 0) {
653 Status
= EFI_DEVICE_ERROR
;
657 IpSb
->InDestory
= TRUE
;
660 IpSb
->State
= IP4_SERVICE_DESTORY
;
663 // Clear the variable data.
665 Ip4ClearVariableData (IpSb
);
668 // OK, clean other resources then uninstall the service binding protocol.
670 Status
= Ip4CleanService (IpSb
);
672 if (EFI_ERROR (Status
)) {
677 gBS
->UninstallProtocolInterface (
679 &gEfiIp4ServiceBindingProtocolGuid
,
683 gBS
->FreePool (IpSb
);
684 } else if (NumberOfChildren
== 0) {
685 IpSb
->InDestory
= TRUE
;
688 IpSb
->State
= IP4_SERVICE_DESTORY
;
691 // Clear the variable data.
693 Ip4ClearVariableData (IpSb
);
696 // OK, clean other resources then uninstall the service binding protocol.
698 Status
= Ip4CleanService (IpSb
);
700 if (EFI_ERROR (Status
)) {
705 gBS
->UninstallProtocolInterface (
707 &gEfiIp4ServiceBindingProtocolGuid
,
711 gBS
->FreePool (IpSb
);
714 while (!IsListEmpty (&IpSb
->Children
)) {
715 IpInstance
= NET_LIST_HEAD (&IpSb
->Children
, IP4_PROTOCOL
, Link
);
717 ServiceBinding
->DestroyChild (ServiceBinding
, IpInstance
->Handle
);
720 if (IpSb
->NumChildren
!= 0) {
721 Status
= EFI_DEVICE_ERROR
;
727 gBS
->RestoreTPL (OldTpl
);
733 Creates a child handle with a set of I/O services.
735 @param This Protocol instance pointer.
736 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,
737 then a new handle is created. If it is not NULL, then the
738 I/O services are added to the existing child handle.
740 @retval EFI_SUCCES The child handle was created with the I/O services
741 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
742 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
744 @retval other The child handle was not created
749 Ip4ServiceBindingCreateChild (
750 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
751 IN OUT EFI_HANDLE
*ChildHandle
755 IP4_PROTOCOL
*IpInstance
;
760 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
761 return EFI_INVALID_PARAMETER
;
764 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
765 IpInstance
= AllocatePool (sizeof (IP4_PROTOCOL
));
767 if (IpInstance
== NULL
) {
768 return EFI_OUT_OF_RESOURCES
;
771 Ip4InitProtocol (IpSb
, IpInstance
);
774 // Install Ip4 onto ChildHandle
776 Status
= gBS
->InstallMultipleProtocolInterfaces (
778 &gEfiIp4ProtocolGuid
,
779 &IpInstance
->Ip4Proto
,
783 if (EFI_ERROR (Status
)) {
787 IpInstance
->Handle
= *ChildHandle
;
790 // Open the Managed Network protocol BY_CHILD.
792 Status
= gBS
->OpenProtocol (
793 IpSb
->MnpChildHandle
,
794 &gEfiManagedNetworkProtocolGuid
,
796 gIp4DriverBinding
.DriverBindingHandle
,
798 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
800 if (EFI_ERROR (Status
)) {
801 gBS
->UninstallMultipleProtocolInterfaces (
803 &gEfiIp4ProtocolGuid
,
804 &IpInstance
->Ip4Proto
,
812 // Insert it into the service binding instance.
814 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
816 InsertTailList (&IpSb
->Children
, &IpInstance
->Link
);
819 gBS
->RestoreTPL (OldTpl
);
823 if (EFI_ERROR (Status
)) {
825 Ip4CleanProtocol (IpInstance
);
827 gBS
->FreePool (IpInstance
);
835 Destroys a child handle with a set of I/O services.
837 @param This Protocol instance pointer.
838 @param ChildHandle Handle of the child to destroy
840 @retval EFI_SUCCES The I/O services were removed from the child handle
841 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
842 that are being removed.
843 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
844 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because its
845 I/O services are being used.
846 @retval other The child handle was not destroyed
851 Ip4ServiceBindingDestroyChild (
852 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
853 IN EFI_HANDLE ChildHandle
858 IP4_PROTOCOL
*IpInstance
;
859 EFI_IP4_PROTOCOL
*Ip4
;
863 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
864 return EFI_INVALID_PARAMETER
;
868 // Retrieve the private context data structures
870 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
872 Status
= gBS
->OpenProtocol (
874 &gEfiIp4ProtocolGuid
,
876 gIp4DriverBinding
.DriverBindingHandle
,
878 EFI_OPEN_PROTOCOL_GET_PROTOCOL
881 if (EFI_ERROR (Status
)) {
882 return EFI_UNSUPPORTED
;
885 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (Ip4
);
887 if (IpInstance
->Service
!= IpSb
) {
888 return EFI_INVALID_PARAMETER
;
891 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
894 // A child can be destoried more than once. For example,
895 // Ip4DriverBindingStop will destory all of its children.
896 // when UDP driver is being stopped, it will destory all
897 // the IP child it opens.
899 if (IpInstance
->State
== IP4_STATE_DESTORY
) {
900 gBS
->RestoreTPL (OldTpl
);
904 State
= IpInstance
->State
;
905 IpInstance
->State
= IP4_STATE_DESTORY
;
908 // Close the Managed Network protocol.
911 IpSb
->MnpChildHandle
,
912 &gEfiManagedNetworkProtocolGuid
,
913 gIp4DriverBinding
.DriverBindingHandle
,
918 // Uninstall the IP4 protocol first. Many thing happens during
920 // 1. The consumer of the IP4 protocol will be stopped if it
921 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
922 // stopped, IP driver's stop function will be called, and uninstall
923 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This
924 // makes it possible to create the network stack bottom up, and
926 // 2. the upper layer will recycle the received packet. The recycle
927 // event's TPL is higher than this function. The recycle events
928 // will be called back before preceeding. If any packets not recycled,
929 // that means there is a resource leak.
931 Status
= gBS
->UninstallProtocolInterface (
933 &gEfiIp4ProtocolGuid
,
934 &IpInstance
->Ip4Proto
937 if (EFI_ERROR (Status
)) {
941 Status
= Ip4CleanProtocol (IpInstance
);
943 Ip4SetVariableData (IpSb
);
945 if (EFI_ERROR (Status
)) {
946 gBS
->InstallMultipleProtocolInterfaces (
948 &gEfiIp4ProtocolGuid
,
956 RemoveEntryList (&IpInstance
->Link
);
959 gBS
->RestoreTPL (OldTpl
);
961 gBS
->FreePool (IpInstance
);
965 IpInstance
->State
= State
;
966 gBS
->RestoreTPL (OldTpl
);