2 The driver binding and service binding protocol for IP4 driver.
4 Copyright (c) 2005 - 2018, 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
->UninstallProtocolInterface (
669 &gEfiIp4ServiceBindingProtocolGuid
,
670 &IpSb
->ServiceBinding
674 Ip4CleanService (IpSb
);
681 Stop this driver on ControllerHandle. This service is called by the
682 EFI boot service DisconnectController(). In order to
683 make drivers as small as possible, there are a few calling
684 restrictions for this service. DisconnectController()
685 must follow these calling restrictions. If any other agent wishes
686 to call Stop() it must also follow these calling restrictions.
688 @param[in] This Protocol instance pointer.
689 @param[in] ControllerHandle Handle of device to stop driver on
690 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
691 of children is zero stop the entire bus driver.
692 @param[in] ChildHandleBuffer List of Child Handles to Stop.
694 @retval EFI_SUCCESS This driver is removed ControllerHandle
695 @retval other This driver was not removed from this device
700 Ip4DriverBindingStop (
701 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
702 IN EFI_HANDLE ControllerHandle
,
703 IN UINTN NumberOfChildren
,
704 IN EFI_HANDLE
*ChildHandleBuffer
707 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
709 EFI_HANDLE NicHandle
;
713 IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
715 IP4_ROUTE_TABLE
*RouteTable
;
721 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiManagedNetworkProtocolGuid
);
722 if (NicHandle
== NULL
) {
723 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiArpProtocolGuid
);
724 if (NicHandle
== NULL
) {
725 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiDhcp4ProtocolGuid
);
726 if (NicHandle
!= NULL
) {
734 Status
= gBS
->OpenProtocol (
736 &gEfiIp4ServiceBindingProtocolGuid
,
737 (VOID
**) &ServiceBinding
,
738 This
->DriverBindingHandle
,
740 EFI_OPEN_PROTOCOL_GET_PROTOCOL
742 if (EFI_ERROR (Status
)) {
743 return EFI_DEVICE_ERROR
;
746 IpSb
= IP4_SERVICE_FROM_PROTOCOL (ServiceBinding
);
749 Status
= Ip4Config2DestroyDhcp4 (&IpSb
->Ip4Config2Instance
);
750 gBS
->CloseEvent (IpSb
->Ip4Config2Instance
.Dhcp4Event
);
751 IpSb
->Ip4Config2Instance
.Dhcp4Event
= NULL
;
752 } else if (NumberOfChildren
!= 0) {
753 List
= &IpSb
->Children
;
754 Context
.ServiceBinding
= ServiceBinding
;
755 Context
.NumberOfChildren
= NumberOfChildren
;
756 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
757 Status
= NetDestroyLinkList (
759 Ip4DestroyChildEntryInHandleBuffer
,
763 } else if (IpSb
->DefaultInterface
->ArpHandle
== ControllerHandle
) {
766 // The ARP protocol for the default interface is being uninstalled and all
767 // its IP child handles should have been destroyed before. So, release the
768 // default interface and route table, create a new one and mark it as not started.
770 Ip4CancelReceive (IpSb
->DefaultInterface
);
771 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
772 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
774 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
778 RouteTable
= Ip4CreateRouteTable ();
779 if (RouteTable
== NULL
) {
780 Ip4FreeInterface (IpIf
, NULL
);
784 IpSb
->DefaultInterface
= IpIf
;
785 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
786 IpSb
->DefaultRouteTable
= RouteTable
;
787 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
789 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
791 } else if (IsListEmpty (&IpSb
->Children
)) {
794 // OK, clean other resources then uninstall the service binding protocol.
796 Status
= Ip4CleanService (IpSb
);
797 if (EFI_ERROR (Status
)) {
802 gBS
->UninstallMultipleProtocolInterfaces (
804 &gEfiIp4ServiceBindingProtocolGuid
,
806 &gEfiIp4Config2ProtocolGuid
,
807 &IpSb
->Ip4Config2Instance
.Ip4Config2
,
811 if (gIp4ControllerNameTable
!= NULL
) {
812 FreeUnicodeStringTable (gIp4ControllerNameTable
);
813 gIp4ControllerNameTable
= NULL
;
824 Creates a child handle and installs a protocol.
826 The CreateChild() function installs a protocol on ChildHandle.
827 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
828 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
830 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
831 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,
832 then a new handle is created. If it is a pointer to an existing UEFI handle,
833 then the protocol is added to the existing UEFI handle.
835 @retval EFI_SUCCES The protocol was added to ChildHandle.
836 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
837 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
839 @retval other The child handle was not created
844 Ip4ServiceBindingCreateChild (
845 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
846 IN OUT EFI_HANDLE
*ChildHandle
850 IP4_PROTOCOL
*IpInstance
;
855 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
856 return EFI_INVALID_PARAMETER
;
859 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
860 IpInstance
= AllocatePool (sizeof (IP4_PROTOCOL
));
862 if (IpInstance
== NULL
) {
863 return EFI_OUT_OF_RESOURCES
;
866 Ip4InitProtocol (IpSb
, IpInstance
);
869 // Install Ip4 onto ChildHandle
871 Status
= gBS
->InstallMultipleProtocolInterfaces (
873 &gEfiIp4ProtocolGuid
,
874 &IpInstance
->Ip4Proto
,
878 if (EFI_ERROR (Status
)) {
882 IpInstance
->Handle
= *ChildHandle
;
885 // Open the Managed Network protocol BY_CHILD.
887 Status
= gBS
->OpenProtocol (
888 IpSb
->MnpChildHandle
,
889 &gEfiManagedNetworkProtocolGuid
,
891 gIp4DriverBinding
.DriverBindingHandle
,
893 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
895 if (EFI_ERROR (Status
)) {
896 gBS
->UninstallMultipleProtocolInterfaces (
898 &gEfiIp4ProtocolGuid
,
899 &IpInstance
->Ip4Proto
,
907 // Insert it into the service binding instance.
909 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
911 InsertTailList (&IpSb
->Children
, &IpInstance
->Link
);
914 gBS
->RestoreTPL (OldTpl
);
918 if (EFI_ERROR (Status
)) {
920 Ip4CleanProtocol (IpInstance
);
922 FreePool (IpInstance
);
930 Destroys a child handle with a protocol installed on it.
932 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
933 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
934 last protocol on ChildHandle, then ChildHandle is destroyed.
936 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
937 @param ChildHandle Handle of the child to destroy
939 @retval EFI_SUCCES The protocol was removed from ChildHandle.
940 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
941 @retval EFI_INVALID_PARAMETER Child handle is NULL.
942 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
943 because its services are being used.
944 @retval other The child handle was not destroyed
949 Ip4ServiceBindingDestroyChild (
950 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
951 IN EFI_HANDLE ChildHandle
956 IP4_PROTOCOL
*IpInstance
;
957 EFI_IP4_PROTOCOL
*Ip4
;
960 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
961 return EFI_INVALID_PARAMETER
;
965 // Retrieve the private context data structures
967 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
969 Status
= gBS
->OpenProtocol (
971 &gEfiIp4ProtocolGuid
,
973 gIp4DriverBinding
.DriverBindingHandle
,
975 EFI_OPEN_PROTOCOL_GET_PROTOCOL
978 if (EFI_ERROR (Status
)) {
979 return EFI_UNSUPPORTED
;
982 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (Ip4
);
984 if (IpInstance
->Service
!= IpSb
) {
985 return EFI_INVALID_PARAMETER
;
988 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
991 // A child can be destroyed more than once. For example,
992 // Ip4DriverBindingStop will destroy all of its children.
993 // when UDP driver is being stopped, it will destroy all
994 // the IP child it opens.
996 if (IpInstance
->InDestroy
) {
997 gBS
->RestoreTPL (OldTpl
);
1001 IpInstance
->InDestroy
= TRUE
;
1004 // Close the Managed Network protocol.
1006 gBS
->CloseProtocol (
1007 IpSb
->MnpChildHandle
,
1008 &gEfiManagedNetworkProtocolGuid
,
1009 gIp4DriverBinding
.DriverBindingHandle
,
1013 if (IpInstance
->Interface
!= NULL
&& IpInstance
->Interface
->Arp
!= NULL
) {
1014 gBS
->CloseProtocol (
1015 IpInstance
->Interface
->ArpHandle
,
1016 &gEfiArpProtocolGuid
,
1017 gIp4DriverBinding
.DriverBindingHandle
,
1023 // Uninstall the IP4 protocol first. Many thing happens during
1025 // 1. The consumer of the IP4 protocol will be stopped if it
1026 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
1027 // stopped, IP driver's stop function will be called, and uninstall
1028 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This
1029 // makes it possible to create the network stack bottom up, and
1030 // stop it top down.
1031 // 2. the upper layer will recycle the received packet. The recycle
1032 // event's TPL is higher than this function. The recycle events
1033 // will be called back before preceeding. If any packets not recycled,
1034 // that means there is a resource leak.
1036 gBS
->RestoreTPL (OldTpl
);
1037 Status
= gBS
->UninstallProtocolInterface (
1039 &gEfiIp4ProtocolGuid
,
1040 &IpInstance
->Ip4Proto
1042 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1043 if (EFI_ERROR (Status
)) {
1044 IpInstance
->InDestroy
= FALSE
;
1048 Status
= Ip4CleanProtocol (IpInstance
);
1049 if (EFI_ERROR (Status
)) {
1050 gBS
->InstallMultipleProtocolInterfaces (
1052 &gEfiIp4ProtocolGuid
,
1060 RemoveEntryList (&IpInstance
->Link
);
1061 IpSb
->NumChildren
--;
1063 gBS
->RestoreTPL (OldTpl
);
1065 FreePool (IpInstance
);
1069 gBS
->RestoreTPL (OldTpl
);