2 The driver binding and service binding protocol for IP4 driver.
4 Copyright (c) 2005 - 2019, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding
= {
20 Ip4DriverBindingSupported
,
21 Ip4DriverBindingStart
,
28 BOOLEAN mIpSec2Installed
= FALSE
;
31 Callback function for IpSec2 Protocol install.
33 @param[in] Event Event whose notification function is being invoked
34 @param[in] Context Pointer to the notification function's context
39 IpSec2InstalledCallback (
46 // Test if protocol was even found.
47 // Notification function will be called at least once.
49 Status
= gBS
->LocateProtocol (&gEfiIpSec2ProtocolGuid
, NULL
, (VOID
**)&mIpSec
);
50 if (Status
== EFI_SUCCESS
&& mIpSec
!= NULL
) {
52 // Close the event so it does not get called again.
54 gBS
->CloseEvent (Event
);
56 mIpSec2Installed
= TRUE
;
61 This is the declaration of an EFI image entry point. This entry point is
62 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
63 both device drivers and bus drivers.
65 The entry point for IP4 driver which install the driver
66 binding and component name protocol on its image.
68 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
69 @param[in] SystemTable A pointer to the EFI System Table.
71 @retval EFI_SUCCESS The operation completed successfully.
72 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
78 IN EFI_HANDLE ImageHandle
,
79 IN EFI_SYSTEM_TABLE
*SystemTable
84 EfiCreateProtocolNotifyEvent (
85 &gEfiIpSec2ProtocolGuid
,
87 IpSec2InstalledCallback
,
92 return EfiLibInstallDriverBindingComponentName2 (
103 Test to see if this driver supports ControllerHandle. This service
104 is called by the EFI boot service ConnectController(). In
105 order to make drivers as small as possible, there are a few calling
106 restrictions for this service. ConnectController() must
107 follow these calling restrictions. If any other agent wishes to call
108 Supported() it must also follow these calling restrictions.
110 @param[in] This Protocol instance pointer.
111 @param[in] ControllerHandle Handle of device to test
112 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
115 @retval EFI_SUCCESS This driver supports this device
116 @retval EFI_ALREADY_STARTED This driver is already running on this device
117 @retval other This driver does not support this device
122 Ip4DriverBindingSupported (
123 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
124 IN EFI_HANDLE ControllerHandle
,
125 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
131 // Test for the MNP service binding Protocol
133 Status
= gBS
->OpenProtocol (
135 &gEfiManagedNetworkServiceBindingProtocolGuid
,
137 This
->DriverBindingHandle
,
139 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
142 if (EFI_ERROR (Status
)) {
147 // Test for the Arp service binding Protocol
149 Status
= gBS
->OpenProtocol (
151 &gEfiArpServiceBindingProtocolGuid
,
153 This
->DriverBindingHandle
,
155 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
162 Clean up a IP4 service binding instance. It will release all
163 the resource allocated by the instance. The instance may be
164 partly initialized, or partly destroyed. If a resource is
165 destroyed, it is marked as that in case the destroy failed and
166 being called again later.
168 @param[in] IpSb The IP4 service binding instance to clean up
170 @retval EFI_SUCCESS The resource used by the instance are cleaned up
171 @retval other Failed to clean up some of the resources.
181 Create a new IP4 driver service binding private instance.
183 @param Controller The controller that has MNP service binding
185 @param ImageHandle The IP4 driver's image handle
186 @param Service The variable to receive the newly created IP4
189 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource
190 @retval EFI_SUCCESS A new IP4 service binding private is created.
191 @retval other Other error occurs.
196 IN EFI_HANDLE Controller
,
197 IN EFI_HANDLE ImageHandle
,
198 OUT IP4_SERVICE
**Service
204 ASSERT (Service
!= NULL
);
209 // allocate a service private data then initialize all the filed to
210 // empty resources, so if any thing goes wrong when allocating
211 // resources, Ip4CleanService can be called to clean it up.
213 IpSb
= AllocateZeroPool (sizeof (IP4_SERVICE
));
216 return EFI_OUT_OF_RESOURCES
;
219 IpSb
->Signature
= IP4_SERVICE_SIGNATURE
;
220 IpSb
->ServiceBinding
.CreateChild
= Ip4ServiceBindingCreateChild
;
221 IpSb
->ServiceBinding
.DestroyChild
= Ip4ServiceBindingDestroyChild
;
222 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
224 IpSb
->NumChildren
= 0;
225 InitializeListHead (&IpSb
->Children
);
227 InitializeListHead (&IpSb
->Interfaces
);
228 IpSb
->DefaultInterface
= NULL
;
229 IpSb
->DefaultRouteTable
= NULL
;
231 Ip4InitAssembleTable (&IpSb
->Assemble
);
233 IpSb
->IgmpCtrl
.Igmpv1QuerySeen
= 0;
234 InitializeListHead (&IpSb
->IgmpCtrl
.Groups
);
236 IpSb
->Image
= ImageHandle
;
237 IpSb
->Controller
= Controller
;
239 IpSb
->MnpChildHandle
= NULL
;
242 IpSb
->MnpConfigData
.ReceivedQueueTimeoutValue
= 0;
243 IpSb
->MnpConfigData
.TransmitQueueTimeoutValue
= 0;
244 IpSb
->MnpConfigData
.ProtocolTypeFilter
= IP4_ETHER_PROTO
;
245 IpSb
->MnpConfigData
.EnableUnicastReceive
= TRUE
;
246 IpSb
->MnpConfigData
.EnableMulticastReceive
= TRUE
;
247 IpSb
->MnpConfigData
.EnableBroadcastReceive
= TRUE
;
248 IpSb
->MnpConfigData
.EnablePromiscuousReceive
= FALSE
;
249 IpSb
->MnpConfigData
.FlushQueuesOnReset
= TRUE
;
250 IpSb
->MnpConfigData
.EnableReceiveTimestamps
= FALSE
;
251 IpSb
->MnpConfigData
.DisableBackgroundPolling
= FALSE
;
253 ZeroMem (&IpSb
->SnpMode
, sizeof (EFI_SIMPLE_NETWORK_MODE
));
256 IpSb
->ReconfigCheckTimer
= NULL
;
258 IpSb
->ReconfigEvent
= NULL
;
260 IpSb
->Reconfig
= FALSE
;
262 IpSb
->MediaPresent
= TRUE
;
265 // Create various resources. First create the route table, timer
266 // event, ReconfigEvent and MNP child. IGMP, interface's initialization depend
269 IpSb
->DefaultRouteTable
= Ip4CreateRouteTable ();
271 if (IpSb
->DefaultRouteTable
== NULL
) {
272 Status
= EFI_OUT_OF_RESOURCES
;
276 Status
= gBS
->CreateEvent (
277 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
284 if (EFI_ERROR (Status
)) {
288 Status
= gBS
->CreateEvent (
289 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
291 Ip4TimerReconfigChecking
,
293 &IpSb
->ReconfigCheckTimer
296 if (EFI_ERROR (Status
)) {
300 Status
= gBS
->CreateEvent (
303 Ip4AutoReconfigCallBack
,
307 if (EFI_ERROR (Status
)) {
311 Status
= NetLibCreateServiceChild (
314 &gEfiManagedNetworkServiceBindingProtocolGuid
,
315 &IpSb
->MnpChildHandle
318 if (EFI_ERROR (Status
)) {
322 Status
= gBS
->OpenProtocol (
323 IpSb
->MnpChildHandle
,
324 &gEfiManagedNetworkProtocolGuid
,
325 (VOID
**) &IpSb
->Mnp
,
328 EFI_OPEN_PROTOCOL_BY_DRIVER
331 if (EFI_ERROR (Status
)) {
335 Status
= Ip4ServiceConfigMnp (IpSb
, TRUE
);
337 if (EFI_ERROR (Status
)) {
341 Status
= IpSb
->Mnp
->GetModeData (IpSb
->Mnp
, NULL
, &IpSb
->SnpMode
);
343 if (EFI_ERROR (Status
)) {
347 Status
= Ip4InitIgmp (IpSb
);
349 if (EFI_ERROR (Status
)) {
353 IpSb
->MacString
= NULL
;
354 Status
= NetLibGetMacString (IpSb
->Controller
, IpSb
->Image
, &IpSb
->MacString
);
356 if (EFI_ERROR (Status
)) {
360 IpSb
->DefaultInterface
= Ip4CreateInterface (IpSb
->Mnp
, Controller
, ImageHandle
);
362 if (IpSb
->DefaultInterface
== NULL
) {
363 Status
= EFI_OUT_OF_RESOURCES
;
367 InsertHeadList (&IpSb
->Interfaces
, &IpSb
->DefaultInterface
->Link
);
369 ZeroMem (&IpSb
->Ip4Config2Instance
, sizeof (IP4_CONFIG2_INSTANCE
));
371 Status
= Ip4Config2InitInstance (&IpSb
->Ip4Config2Instance
);
373 if (EFI_ERROR (Status
)) {
377 IpSb
->MaxPacketSize
= IpSb
->SnpMode
.MaxPacketSize
- sizeof (IP4_HEAD
);
378 if (NetLibGetVlanId (IpSb
->Controller
) != 0) {
380 // This is a VLAN device, reduce MTU by VLAN tag length
382 IpSb
->MaxPacketSize
-= NET_VLAN_TAG_LEN
;
384 IpSb
->OldMaxPacketSize
= IpSb
->MaxPacketSize
;
390 Ip4CleanService (IpSb
);
398 Clean up a IP4 service binding instance. It will release all
399 the resource allocated by the instance. The instance may be
400 partly initialized, or partly destroyed. If a resource is
401 destroyed, it is marked as that in case the destroy failed and
402 being called again later.
404 @param[in] IpSb The IP4 service binding instance to clean up
406 @retval EFI_SUCCESS The resource used by the instance are cleaned up
407 @retval other Failed to clean up some of the resources.
417 IpSb
->State
= IP4_SERVICE_DESTROY
;
419 if (IpSb
->Timer
!= NULL
) {
420 gBS
->SetTimer (IpSb
->Timer
, TimerCancel
, 0);
421 gBS
->CloseEvent (IpSb
->Timer
);
426 if (IpSb
->ReconfigCheckTimer
!= NULL
) {
427 gBS
->SetTimer (IpSb
->ReconfigCheckTimer
, TimerCancel
, 0);
428 gBS
->CloseEvent (IpSb
->ReconfigCheckTimer
);
430 IpSb
->ReconfigCheckTimer
= NULL
;
433 if (IpSb
->DefaultInterface
!= NULL
) {
434 Status
= Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
436 if (EFI_ERROR (Status
)) {
440 IpSb
->DefaultInterface
= NULL
;
443 if (IpSb
->DefaultRouteTable
!= NULL
) {
444 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
445 IpSb
->DefaultRouteTable
= NULL
;
448 Ip4CleanAssembleTable (&IpSb
->Assemble
);
450 if (IpSb
->MnpChildHandle
!= NULL
) {
451 if (IpSb
->Mnp
!= NULL
) {
453 IpSb
->MnpChildHandle
,
454 &gEfiManagedNetworkProtocolGuid
,
462 NetLibDestroyServiceChild (
465 &gEfiManagedNetworkServiceBindingProtocolGuid
,
469 IpSb
->MnpChildHandle
= NULL
;
472 if (IpSb
->ReconfigEvent
!= NULL
) {
473 gBS
->CloseEvent (IpSb
->ReconfigEvent
);
475 IpSb
->ReconfigEvent
= NULL
;
478 IpSb
->Reconfig
= FALSE
;
480 if (IpSb
->MacString
!= NULL
) {
481 FreePool (IpSb
->MacString
);
484 Ip4Config2CleanInstance (&IpSb
->Ip4Config2Instance
);
490 Callback function which provided by user to remove one node in NetDestroyLinkList process.
492 @param[in] Entry The entry to be removed.
493 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
495 @retval EFI_SUCCESS The entry has been removed successfully.
496 @retval Others Fail to remove the entry.
501 Ip4DestroyChildEntryInHandleBuffer (
502 IN LIST_ENTRY
*Entry
,
506 IP4_PROTOCOL
*IpInstance
;
507 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
508 UINTN NumberOfChildren
;
509 EFI_HANDLE
*ChildHandleBuffer
;
511 if (Entry
== NULL
|| Context
== NULL
) {
512 return EFI_INVALID_PARAMETER
;
515 IpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP4_PROTOCOL
, Link
, IP4_PROTOCOL_SIGNATURE
);
516 ServiceBinding
= ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
517 NumberOfChildren
= ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
518 ChildHandleBuffer
= ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
520 if (!NetIsInHandleBuffer (IpInstance
->Handle
, NumberOfChildren
, ChildHandleBuffer
)) {
524 return ServiceBinding
->DestroyChild (ServiceBinding
, IpInstance
->Handle
);
528 Start this driver on ControllerHandle. This service is called by the
529 EFI boot service ConnectController(). In order to make
530 drivers as small as possible, there are a few calling restrictions for
531 this service. ConnectController() must follow these
532 calling restrictions. If any other agent wishes to call Start() it
533 must also follow these calling restrictions.
535 @param[in] This Protocol instance pointer.
536 @param[in] ControllerHandle Handle of device to bind driver to
537 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
540 @retval EFI_SUCCESS This driver is added to ControllerHandle
541 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
542 @retval other This driver does not support this device
547 Ip4DriverBindingStart (
548 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
549 IN EFI_HANDLE ControllerHandle
,
550 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
555 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Cfg2
;
557 IP4_CONFIG2_DATA_ITEM
*DataItem
;
564 // Test for the Ip4 service binding protocol
566 Status
= gBS
->OpenProtocol (
568 &gEfiIp4ServiceBindingProtocolGuid
,
570 This
->DriverBindingHandle
,
572 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
575 if (Status
== EFI_SUCCESS
) {
576 return EFI_ALREADY_STARTED
;
579 Status
= Ip4CreateService (ControllerHandle
, This
->DriverBindingHandle
, &IpSb
);
581 if (EFI_ERROR (Status
)) {
585 ASSERT (IpSb
!= NULL
);
587 Ip4Cfg2
= &IpSb
->Ip4Config2Instance
.Ip4Config2
;
590 // Install the Ip4ServiceBinding Protocol onto ControlerHandle
592 Status
= gBS
->InstallMultipleProtocolInterfaces (
594 &gEfiIp4ServiceBindingProtocolGuid
,
595 &IpSb
->ServiceBinding
,
596 &gEfiIp4Config2ProtocolGuid
,
601 if (EFI_ERROR (Status
)) {
606 // Read the config data from NV variable again.
607 // The default data can be changed by other drivers.
609 Status
= Ip4Config2ReadConfigData (IpSb
->MacString
, &IpSb
->Ip4Config2Instance
);
610 if (EFI_ERROR (Status
)) {
611 goto UNINSTALL_PROTOCOL
;
615 // Consume the installed EFI_IP4_CONFIG2_PROTOCOL to set the default data items.
617 for (Index
= Ip4Config2DataTypePolicy
; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
618 DataItem
= &IpSb
->Ip4Config2Instance
.DataItem
[Index
];
619 if (DataItem
->Data
.Ptr
!= NULL
) {
620 Status
= Ip4Cfg2
->SetData (
626 if (EFI_ERROR(Status
)) {
627 goto UNINSTALL_PROTOCOL
;
630 if (Index
== Ip4Config2DataTypePolicy
&& (*(DataItem
->Data
.Policy
) == Ip4Config2PolicyDhcp
)) {
637 // Ready to go: start the receiving and timer.
638 // Ip4Config2SetPolicy maybe call Ip4ReceiveFrame() to set the default interface's RecvRequest first after
639 // Ip4Config2 instance is initialized. So, EFI_ALREADY_STARTED is the allowed return status.
641 Status
= Ip4ReceiveFrame (IpSb
->DefaultInterface
, NULL
, Ip4AccpetFrame
, IpSb
);
643 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
644 goto UNINSTALL_PROTOCOL
;
647 Status
= gBS
->SetTimer (IpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
649 if (EFI_ERROR (Status
)) {
650 goto UNINSTALL_PROTOCOL
;
653 Status
= gBS
->SetTimer (IpSb
->ReconfigCheckTimer
, TimerPeriodic
, 500 * TICKS_PER_MS
);
655 if (EFI_ERROR (Status
)) {
656 goto UNINSTALL_PROTOCOL
;
660 // Initialize the IP4 ID
662 mIp4Id
= (UINT16
)NET_RANDOM (NetRandomInitSeed ());
667 gBS
->UninstallMultipleProtocolInterfaces (
669 &gEfiIp4ServiceBindingProtocolGuid
,
670 &IpSb
->ServiceBinding
,
671 &gEfiIp4Config2ProtocolGuid
,
677 Ip4CleanService (IpSb
);
684 Stop this driver on ControllerHandle. This service is called by the
685 EFI boot service DisconnectController(). In order to
686 make drivers as small as possible, there are a few calling
687 restrictions for this service. DisconnectController()
688 must follow these calling restrictions. If any other agent wishes
689 to call Stop() it must also follow these calling restrictions.
691 @param[in] This Protocol instance pointer.
692 @param[in] ControllerHandle Handle of device to stop driver on
693 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
694 of children is zero stop the entire bus driver.
695 @param[in] ChildHandleBuffer List of Child Handles to Stop.
697 @retval EFI_SUCCESS This driver is removed ControllerHandle
698 @retval other This driver was not removed from this device
703 Ip4DriverBindingStop (
704 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
705 IN EFI_HANDLE ControllerHandle
,
706 IN UINTN NumberOfChildren
,
707 IN EFI_HANDLE
*ChildHandleBuffer
710 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
712 EFI_HANDLE NicHandle
;
716 IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
718 IP4_ROUTE_TABLE
*RouteTable
;
724 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiManagedNetworkProtocolGuid
);
725 if (NicHandle
== NULL
) {
726 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiArpProtocolGuid
);
727 if (NicHandle
== NULL
) {
728 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiDhcp4ProtocolGuid
);
729 if (NicHandle
!= NULL
) {
737 Status
= gBS
->OpenProtocol (
739 &gEfiIp4ServiceBindingProtocolGuid
,
740 (VOID
**) &ServiceBinding
,
741 This
->DriverBindingHandle
,
743 EFI_OPEN_PROTOCOL_GET_PROTOCOL
745 if (EFI_ERROR (Status
)) {
746 return EFI_DEVICE_ERROR
;
749 IpSb
= IP4_SERVICE_FROM_PROTOCOL (ServiceBinding
);
752 Status
= Ip4Config2DestroyDhcp4 (&IpSb
->Ip4Config2Instance
);
753 gBS
->CloseEvent (IpSb
->Ip4Config2Instance
.Dhcp4Event
);
754 IpSb
->Ip4Config2Instance
.Dhcp4Event
= NULL
;
755 } else if (NumberOfChildren
!= 0) {
756 List
= &IpSb
->Children
;
757 Context
.ServiceBinding
= ServiceBinding
;
758 Context
.NumberOfChildren
= NumberOfChildren
;
759 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
760 Status
= NetDestroyLinkList (
762 Ip4DestroyChildEntryInHandleBuffer
,
766 } else if (IpSb
->DefaultInterface
->ArpHandle
== ControllerHandle
) {
769 // The ARP protocol for the default interface is being uninstalled and all
770 // its IP child handles should have been destroyed before. So, release the
771 // default interface and route table, create a new one and mark it as not started.
773 Ip4CancelReceive (IpSb
->DefaultInterface
);
774 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
775 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
777 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
781 RouteTable
= Ip4CreateRouteTable ();
782 if (RouteTable
== NULL
) {
783 Ip4FreeInterface (IpIf
, NULL
);
787 IpSb
->DefaultInterface
= IpIf
;
788 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
789 IpSb
->DefaultRouteTable
= RouteTable
;
790 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
792 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
794 } else if (IsListEmpty (&IpSb
->Children
)) {
797 // OK, clean other resources then uninstall the service binding protocol.
799 Status
= Ip4CleanService (IpSb
);
800 if (EFI_ERROR (Status
)) {
805 gBS
->UninstallMultipleProtocolInterfaces (
807 &gEfiIp4ServiceBindingProtocolGuid
,
809 &gEfiIp4Config2ProtocolGuid
,
810 &IpSb
->Ip4Config2Instance
.Ip4Config2
,
814 if (gIp4ControllerNameTable
!= NULL
) {
815 FreeUnicodeStringTable (gIp4ControllerNameTable
);
816 gIp4ControllerNameTable
= NULL
;
827 Creates a child handle and installs a protocol.
829 The CreateChild() function installs a protocol on ChildHandle.
830 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
831 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
833 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
834 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,
835 then a new handle is created. If it is a pointer to an existing UEFI handle,
836 then the protocol is added to the existing UEFI handle.
838 @retval EFI_SUCCES The protocol was added to ChildHandle.
839 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
840 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
842 @retval other The child handle was not created
847 Ip4ServiceBindingCreateChild (
848 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
849 IN OUT EFI_HANDLE
*ChildHandle
853 IP4_PROTOCOL
*IpInstance
;
858 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
859 return EFI_INVALID_PARAMETER
;
862 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
863 IpInstance
= AllocatePool (sizeof (IP4_PROTOCOL
));
865 if (IpInstance
== NULL
) {
866 return EFI_OUT_OF_RESOURCES
;
869 Ip4InitProtocol (IpSb
, IpInstance
);
872 // Install Ip4 onto ChildHandle
874 Status
= gBS
->InstallMultipleProtocolInterfaces (
876 &gEfiIp4ProtocolGuid
,
877 &IpInstance
->Ip4Proto
,
881 if (EFI_ERROR (Status
)) {
885 IpInstance
->Handle
= *ChildHandle
;
888 // Open the Managed Network protocol BY_CHILD.
890 Status
= gBS
->OpenProtocol (
891 IpSb
->MnpChildHandle
,
892 &gEfiManagedNetworkProtocolGuid
,
894 gIp4DriverBinding
.DriverBindingHandle
,
896 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
898 if (EFI_ERROR (Status
)) {
899 gBS
->UninstallMultipleProtocolInterfaces (
901 &gEfiIp4ProtocolGuid
,
902 &IpInstance
->Ip4Proto
,
910 // Insert it into the service binding instance.
912 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
914 InsertTailList (&IpSb
->Children
, &IpInstance
->Link
);
917 gBS
->RestoreTPL (OldTpl
);
921 if (EFI_ERROR (Status
)) {
923 Ip4CleanProtocol (IpInstance
);
925 FreePool (IpInstance
);
933 Destroys a child handle with a protocol installed on it.
935 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
936 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
937 last protocol on ChildHandle, then ChildHandle is destroyed.
939 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
940 @param ChildHandle Handle of the child to destroy
942 @retval EFI_SUCCES The protocol was removed from ChildHandle.
943 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
944 @retval EFI_INVALID_PARAMETER Child handle is NULL.
945 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
946 because its services are being used.
947 @retval other The child handle was not destroyed
952 Ip4ServiceBindingDestroyChild (
953 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
954 IN EFI_HANDLE ChildHandle
959 IP4_PROTOCOL
*IpInstance
;
960 EFI_IP4_PROTOCOL
*Ip4
;
963 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
964 return EFI_INVALID_PARAMETER
;
968 // Retrieve the private context data structures
970 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
972 Status
= gBS
->OpenProtocol (
974 &gEfiIp4ProtocolGuid
,
976 gIp4DriverBinding
.DriverBindingHandle
,
978 EFI_OPEN_PROTOCOL_GET_PROTOCOL
981 if (EFI_ERROR (Status
)) {
982 return EFI_UNSUPPORTED
;
985 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (Ip4
);
987 if (IpInstance
->Service
!= IpSb
) {
988 return EFI_INVALID_PARAMETER
;
991 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
994 // A child can be destroyed more than once. For example,
995 // Ip4DriverBindingStop will destroy all of its children.
996 // when UDP driver is being stopped, it will destroy all
997 // the IP child it opens.
999 if (IpInstance
->InDestroy
) {
1000 gBS
->RestoreTPL (OldTpl
);
1004 IpInstance
->InDestroy
= TRUE
;
1007 // Close the Managed Network protocol.
1009 gBS
->CloseProtocol (
1010 IpSb
->MnpChildHandle
,
1011 &gEfiManagedNetworkProtocolGuid
,
1012 gIp4DriverBinding
.DriverBindingHandle
,
1016 if (IpInstance
->Interface
!= NULL
&& IpInstance
->Interface
->Arp
!= NULL
) {
1017 gBS
->CloseProtocol (
1018 IpInstance
->Interface
->ArpHandle
,
1019 &gEfiArpProtocolGuid
,
1020 gIp4DriverBinding
.DriverBindingHandle
,
1026 // Uninstall the IP4 protocol first. Many thing happens during
1028 // 1. The consumer of the IP4 protocol will be stopped if it
1029 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
1030 // stopped, IP driver's stop function will be called, and uninstall
1031 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This
1032 // makes it possible to create the network stack bottom up, and
1033 // stop it top down.
1034 // 2. the upper layer will recycle the received packet. The recycle
1035 // event's TPL is higher than this function. The recycle events
1036 // will be called back before preceeding. If any packets not recycled,
1037 // that means there is a resource leak.
1039 gBS
->RestoreTPL (OldTpl
);
1040 Status
= gBS
->UninstallProtocolInterface (
1042 &gEfiIp4ProtocolGuid
,
1043 &IpInstance
->Ip4Proto
1045 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1046 if (EFI_ERROR (Status
)) {
1047 IpInstance
->InDestroy
= FALSE
;
1051 Status
= Ip4CleanProtocol (IpInstance
);
1052 if (EFI_ERROR (Status
)) {
1053 gBS
->InstallMultipleProtocolInterfaces (
1055 &gEfiIp4ProtocolGuid
,
1063 RemoveEntryList (&IpInstance
->Link
);
1064 IpSb
->NumChildren
--;
1066 gBS
->RestoreTPL (OldTpl
);
1068 FreePool (IpInstance
);
1072 gBS
->RestoreTPL (OldTpl
);