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
,
37 IN EFI_HANDLE ImageHandle
,
38 IN EFI_SYSTEM_TABLE
*SystemTable
44 The entry point for IP4 driver which install the driver
45 binding and component name protocol on its image.
49 ImageHandle - The image handle of the driver
50 SystemTable - The system table
54 EFI_SUCCESS if the driver binding and component name protocols
55 are successfully installed, otherwise if failed.
59 return EfiLibInstallDriverBindingComponentName2 (
71 Test to see if this driver supports ControllerHandle.
73 @param This Protocol instance pointer.
74 @param ControllerHandle Handle of device to test
75 @param RemainingDevicePath Optional parameter use to pick a specific child
78 @retval EFI_SUCCES This driver supports this device
79 @retval EFI_ALREADY_STARTED This driver is already running on this device
80 @retval other This driver does not support this device
85 Ip4DriverBindingSupported (
86 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
87 IN EFI_HANDLE ControllerHandle
,
88 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
94 // Test for the MNP service binding Protocol
96 Status
= gBS
->OpenProtocol (
98 &gEfiManagedNetworkServiceBindingProtocolGuid
,
100 This
->DriverBindingHandle
,
102 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
105 if (EFI_ERROR (Status
)) {
110 // Test for the Arp service binding Protocol
112 Status
= gBS
->OpenProtocol (
114 &gEfiArpServiceBindingProtocolGuid
,
116 This
->DriverBindingHandle
,
118 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
131 Create a new IP4 driver service binding protocol
133 @param Controller The controller that has MNP service binding
135 @param ImageHandle The IP4 driver's image handle
136 @param Service The variable to receive the newly created IP4
139 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource
140 @retval EFI_SUCCESS A new IP4 service binding private is created.
145 IN EFI_HANDLE Controller
,
146 IN EFI_HANDLE ImageHandle
,
147 OUT IP4_SERVICE
**Service
153 ASSERT (Service
!= NULL
);
158 // allocate a service private data then initialize all the filed to
159 // empty resources, so if any thing goes wrong when allocating
160 // resources, Ip4CleanService can be called to clean it up.
162 IpSb
= AllocatePool (sizeof (IP4_SERVICE
));
165 return EFI_OUT_OF_RESOURCES
;
168 IpSb
->Signature
= IP4_SERVICE_SIGNATURE
;
169 IpSb
->ServiceBinding
.CreateChild
= Ip4ServiceBindingCreateChild
;
170 IpSb
->ServiceBinding
.DestroyChild
= Ip4ServiceBindingDestroyChild
;
171 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
172 IpSb
->InDestory
= FALSE
;
174 IpSb
->NumChildren
= 0;
175 InitializeListHead (&IpSb
->Children
);
177 InitializeListHead (&IpSb
->Interfaces
);
178 IpSb
->DefaultInterface
= NULL
;
179 IpSb
->DefaultRouteTable
= NULL
;
181 Ip4InitAssembleTable (&IpSb
->Assemble
);
183 IpSb
->IgmpCtrl
.Igmpv1QuerySeen
= 0;
184 InitializeListHead (&IpSb
->IgmpCtrl
.Groups
);
186 IpSb
->Image
= ImageHandle
;
187 IpSb
->Controller
= Controller
;
189 IpSb
->MnpChildHandle
= NULL
;
192 IpSb
->MnpConfigData
.ReceivedQueueTimeoutValue
= 0;
193 IpSb
->MnpConfigData
.TransmitQueueTimeoutValue
= 0;
194 IpSb
->MnpConfigData
.ProtocolTypeFilter
= IP4_ETHER_PROTO
;
195 IpSb
->MnpConfigData
.EnableUnicastReceive
= TRUE
;
196 IpSb
->MnpConfigData
.EnableMulticastReceive
= TRUE
;
197 IpSb
->MnpConfigData
.EnableBroadcastReceive
= TRUE
;
198 IpSb
->MnpConfigData
.EnablePromiscuousReceive
= FALSE
;
199 IpSb
->MnpConfigData
.FlushQueuesOnReset
= TRUE
;
200 IpSb
->MnpConfigData
.EnableReceiveTimestamps
= FALSE
;
201 IpSb
->MnpConfigData
.DisableBackgroundPolling
= FALSE
;
203 ZeroMem (&IpSb
->SnpMode
, sizeof (EFI_SIMPLE_NETWORK_MODE
));
206 IpSb
->Ip4Config
= NULL
;
207 IpSb
->DoneEvent
= NULL
;
208 IpSb
->ReconfigEvent
= NULL
;
209 IpSb
->ActiveEvent
= NULL
;
212 // Create various resources. First create the route table, timer
213 // event and MNP child. IGMP, interface's initialization depend
216 IpSb
->DefaultRouteTable
= Ip4CreateRouteTable ();
218 if (IpSb
->DefaultRouteTable
== NULL
) {
219 Status
= EFI_OUT_OF_RESOURCES
;
223 Status
= gBS
->CreateEvent (
224 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
231 if (EFI_ERROR (Status
)) {
235 Status
= NetLibCreateServiceChild (
238 &gEfiManagedNetworkServiceBindingProtocolGuid
,
239 &IpSb
->MnpChildHandle
242 if (EFI_ERROR (Status
)) {
246 Status
= gBS
->OpenProtocol (
247 IpSb
->MnpChildHandle
,
248 &gEfiManagedNetworkProtocolGuid
,
249 (VOID
**) &IpSb
->Mnp
,
252 EFI_OPEN_PROTOCOL_BY_DRIVER
255 if (EFI_ERROR (Status
)) {
259 Status
= Ip4ServiceConfigMnp (IpSb
, TRUE
);
261 if (EFI_ERROR (Status
)) {
265 Status
= IpSb
->Mnp
->GetModeData (IpSb
->Mnp
, NULL
, &IpSb
->SnpMode
);
267 if (EFI_ERROR (Status
)) {
271 Status
= Ip4InitIgmp (IpSb
);
273 if (EFI_ERROR (Status
)) {
277 IpSb
->DefaultInterface
= Ip4CreateInterface (IpSb
->Mnp
, Controller
, ImageHandle
);
279 if (IpSb
->DefaultInterface
== NULL
) {
280 Status
= EFI_OUT_OF_RESOURCES
;
284 InsertHeadList (&IpSb
->Interfaces
, &IpSb
->DefaultInterface
->Link
);
286 IpSb
->MacString
= NULL
;
292 Ip4CleanService (IpSb
);
293 gBS
->FreePool (IpSb
);
300 Clean up a IP4 service binding instance. It will release all
301 the resource allocated by the instance. The instance may be
302 partly initialized, or partly destoried. If a resource is
303 destoried, it is marked as that in case the destory failed and
304 being called again later.
306 @param IpSb The IP4 serviceing binding instance to clean up
308 @retval EFI_SUCCESS The resource used by the instance are cleaned up
309 @retval Others Failed to clean up some of the resources.
319 if (IpSb
->DefaultInterface
!= NULL
) {
320 Status
= Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
322 if (EFI_ERROR (Status
)) {
326 IpSb
->DefaultInterface
= NULL
;
329 if (IpSb
->DefaultRouteTable
!= NULL
) {
330 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
331 IpSb
->DefaultRouteTable
= NULL
;
334 Ip4CleanAssembleTable (&IpSb
->Assemble
);
336 if (IpSb
->MnpChildHandle
!= NULL
) {
339 IpSb
->MnpChildHandle
,
340 &gEfiManagedNetworkProtocolGuid
,
348 NetLibDestroyServiceChild (
351 &gEfiManagedNetworkServiceBindingProtocolGuid
,
355 IpSb
->MnpChildHandle
= NULL
;
358 if (IpSb
->Timer
!= NULL
) {
359 gBS
->SetTimer (IpSb
->Timer
, TimerCancel
, 0);
360 gBS
->CloseEvent (IpSb
->Timer
);
365 if (IpSb
->Ip4Config
!= NULL
) {
366 IpSb
->Ip4Config
->Stop (IpSb
->Ip4Config
);
370 &gEfiIp4ConfigProtocolGuid
,
375 gBS
->CloseEvent (IpSb
->DoneEvent
);
376 gBS
->CloseEvent (IpSb
->ReconfigEvent
);
377 IpSb
->ActiveEvent
= NULL
;
378 IpSb
->Ip4Config
= NULL
;
386 Start this driver on ControllerHandle.
388 @param This Protocol instance pointer.
389 @param ControllerHandle Handle of device to bind driver to
390 @param RemainingDevicePath Optional parameter use to pick a specific child
393 @retval EFI_SUCCES This driver is added to ControllerHandle
394 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
395 @retval other This driver does not support this device
400 Ip4DriverBindingStart (
401 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
402 IN EFI_HANDLE ControllerHandle
,
403 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
410 // Test for the Ip4 service binding protocol
412 Status
= gBS
->OpenProtocol (
414 &gEfiIp4ServiceBindingProtocolGuid
,
416 This
->DriverBindingHandle
,
418 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
421 if (Status
== EFI_SUCCESS
) {
422 return EFI_ALREADY_STARTED
;
425 Status
= Ip4CreateService (ControllerHandle
, This
->DriverBindingHandle
, &IpSb
);
427 if (EFI_ERROR (Status
)) {
432 // Install the Ip4ServiceBinding Protocol onto ControlerHandle
434 Status
= gBS
->InstallMultipleProtocolInterfaces (
436 &gEfiIp4ServiceBindingProtocolGuid
,
437 &IpSb
->ServiceBinding
,
441 if (EFI_ERROR (Status
)) {
446 // ready to go: start the receiving and timer
448 Status
= Ip4ReceiveFrame (IpSb
->DefaultInterface
, NULL
, Ip4AccpetFrame
, IpSb
);
450 if (EFI_ERROR (Status
)) {
451 goto UNINSTALL_PROTOCOL
;
454 Status
= gBS
->SetTimer (IpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
456 if (EFI_ERROR (Status
)) {
457 goto UNINSTALL_PROTOCOL
;
461 // Initialize the IP4 ID
463 mIp4Id
= (UINT16
)NET_RANDOM (NetRandomInitSeed ());
465 Ip4SetVariableData (IpSb
);
470 gBS
->UninstallProtocolInterface (
472 &gEfiIp4ServiceBindingProtocolGuid
,
473 &IpSb
->ServiceBinding
477 Ip4CleanService (IpSb
);
478 gBS
->FreePool (IpSb
);
485 Stop this driver on ControllerHandle.
487 @param This Protocol instance pointer.
488 @param ControllerHandle Handle of device to stop driver on
489 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
490 of children is zero stop the entire bus driver.
491 @param ChildHandleBuffer List of Child Handles to Stop.
493 @retval EFI_SUCCES This driver is removed ControllerHandle
494 @retval other This driver was not removed from this device
499 Ip4DriverBindingStop (
500 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
501 IN EFI_HANDLE ControllerHandle
,
502 IN UINTN NumberOfChildren
,
503 IN EFI_HANDLE
*ChildHandleBuffer
506 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
508 IP4_PROTOCOL
*IpInstance
;
509 EFI_HANDLE NicHandle
;
516 // IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol
517 // by driver. So the ControllerHandle may be the MNP child handle, ARP child
518 // handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed
519 // in the NIC handle.
522 // First, check whether it is the IP4_CONFIG protocol being uninstalled.
523 // IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary
524 // to clean up the default configuration if IP4_CONFIG is being stopped.
526 Status
= gBS
->OpenProtocol (
528 &gEfiIp4ConfigProtocolGuid
,
530 This
->DriverBindingHandle
,
532 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
535 if (Status
== EFI_SUCCESS
) {
537 // Retrieve the IP4 service binding protocol. If failed, it is
538 // likely that Ip4 ServiceBinding is uninstalled already. In this
539 // case, return immediately.
541 Status
= gBS
->OpenProtocol (
543 &gEfiIp4ServiceBindingProtocolGuid
,
544 (VOID
**) &ServiceBinding
,
545 This
->DriverBindingHandle
,
547 EFI_OPEN_PROTOCOL_GET_PROTOCOL
550 if (EFI_ERROR (Status
)) {
551 return EFI_DEVICE_ERROR
;
554 IpSb
= IP4_SERVICE_FROM_PROTOCOL (ServiceBinding
);
556 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
558 if (IpSb
->Ip4Config
&& (IpSb
->State
!= IP4_SERVICE_DESTORY
)) {
560 IpSb
->Ip4Config
->Stop (IpSb
->Ip4Config
);
562 Status
= gBS
->CloseProtocol (
564 &gEfiIp4ConfigProtocolGuid
,
569 if (EFI_ERROR (Status
)) {
570 gBS
->RestoreTPL (OldTpl
);
575 // If the auto configure hasn't complete, mark it as not started.
577 if (IpSb
->State
== IP4_SERVICE_STARTED
) {
578 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
581 IpSb
->Ip4Config
= NULL
;
582 gBS
->CloseEvent (IpSb
->DoneEvent
);
583 gBS
->CloseEvent (IpSb
->ReconfigEvent
);
586 gBS
->RestoreTPL (OldTpl
);
591 // Either MNP or ARP protocol is being uninstalled. The controller
592 // handle is either the MNP child or ARP child. But, the IP4's
593 // service binding is installed on the NIC handle. So, need to open
594 // the protocol info to find the NIC handle.
597 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiManagedNetworkProtocolGuid
);
599 if (NicHandle
== NULL
) {
600 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiArpProtocolGuid
);
604 if (NicHandle
== NULL
) {
605 return EFI_DEVICE_ERROR
;
609 // Retrieve the IP4 service binding protocol
611 Status
= gBS
->OpenProtocol (
613 &gEfiIp4ServiceBindingProtocolGuid
,
614 (VOID
**) &ServiceBinding
,
615 This
->DriverBindingHandle
,
617 EFI_OPEN_PROTOCOL_GET_PROTOCOL
620 if (EFI_ERROR (Status
)) {
621 return EFI_DEVICE_ERROR
;
624 IpSb
= IP4_SERVICE_FROM_PROTOCOL (ServiceBinding
);
626 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
628 if (IpSb
->InDestory
) {
629 gBS
->RestoreTPL (OldTpl
);
634 while (!IsListEmpty (&IpSb
->Children
)) {
635 IpInstance
= NET_LIST_HEAD (&IpSb
->Children
, IP4_PROTOCOL
, Link
);
637 ServiceBinding
->DestroyChild (ServiceBinding
, IpInstance
->Handle
);
640 if (IpSb
->NumChildren
!= 0) {
641 Status
= EFI_DEVICE_ERROR
;
645 IpSb
->InDestory
= TRUE
;
648 IpSb
->State
= IP4_SERVICE_DESTORY
;
651 // Clear the variable data.
653 Ip4ClearVariableData (IpSb
);
656 // OK, clean other resources then uninstall the service binding protocol.
658 Status
= Ip4CleanService (IpSb
);
660 if (EFI_ERROR (Status
)) {
665 gBS
->UninstallProtocolInterface (
667 &gEfiIp4ServiceBindingProtocolGuid
,
671 gBS
->FreePool (IpSb
);
672 } else if (NumberOfChildren
== 0) {
673 IpSb
->InDestory
= TRUE
;
676 IpSb
->State
= IP4_SERVICE_DESTORY
;
679 // Clear the variable data.
681 Ip4ClearVariableData (IpSb
);
684 // OK, clean other resources then uninstall the service binding protocol.
686 Status
= Ip4CleanService (IpSb
);
688 if (EFI_ERROR (Status
)) {
693 gBS
->UninstallProtocolInterface (
695 &gEfiIp4ServiceBindingProtocolGuid
,
699 gBS
->FreePool (IpSb
);
702 while (!IsListEmpty (&IpSb
->Children
)) {
703 IpInstance
= NET_LIST_HEAD (&IpSb
->Children
, IP4_PROTOCOL
, Link
);
705 ServiceBinding
->DestroyChild (ServiceBinding
, IpInstance
->Handle
);
708 if (IpSb
->NumChildren
!= 0) {
709 Status
= EFI_DEVICE_ERROR
;
715 gBS
->RestoreTPL (OldTpl
);
721 Creates a child handle with a set of I/O services.
723 @param This Protocol instance pointer.
724 @param ChildHandle Pointer to the handle of the child to create. If
725 it is NULL, then a new handle is created. If it
726 is not NULL, then the I/O services are added to
727 the existing child handle.
729 @retval EFI_SUCCES The child handle was created with the I/O services
730 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
732 @retval other The child handle was not created
737 Ip4ServiceBindingCreateChild (
738 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
739 IN EFI_HANDLE
*ChildHandle
743 IP4_PROTOCOL
*IpInstance
;
748 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
749 return EFI_INVALID_PARAMETER
;
752 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
753 IpInstance
= AllocatePool (sizeof (IP4_PROTOCOL
));
755 if (IpInstance
== NULL
) {
756 return EFI_OUT_OF_RESOURCES
;
759 Ip4InitProtocol (IpSb
, IpInstance
);
762 // Install Ip4 onto ChildHandle
764 Status
= gBS
->InstallMultipleProtocolInterfaces (
766 &gEfiIp4ProtocolGuid
,
767 &IpInstance
->Ip4Proto
,
771 if (EFI_ERROR (Status
)) {
775 IpInstance
->Handle
= *ChildHandle
;
778 // Open the Managed Network protocol BY_CHILD.
780 Status
= gBS
->OpenProtocol (
781 IpSb
->MnpChildHandle
,
782 &gEfiManagedNetworkProtocolGuid
,
784 gIp4DriverBinding
.DriverBindingHandle
,
786 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
788 if (EFI_ERROR (Status
)) {
789 gBS
->UninstallMultipleProtocolInterfaces (
791 &gEfiIp4ProtocolGuid
,
792 &IpInstance
->Ip4Proto
,
800 // Insert it into the service binding instance.
802 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
804 InsertTailList (&IpSb
->Children
, &IpInstance
->Link
);
807 gBS
->RestoreTPL (OldTpl
);
811 if (EFI_ERROR (Status
)) {
813 Ip4CleanProtocol (IpInstance
);
815 gBS
->FreePool (IpInstance
);
823 Destroys a child handle with a set of I/O services.
825 @param This Protocol instance pointer.
826 @param ChildHandle Handle of the child to destroy
828 @retval EFI_SUCCES The I/O services were removed from the child
830 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
831 that are being removed
832 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
833 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
834 its I/O services are being used.
835 @retval other The child handle was not destroyed
840 Ip4ServiceBindingDestroyChild (
841 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
842 IN EFI_HANDLE ChildHandle
847 IP4_PROTOCOL
*IpInstance
;
848 EFI_IP4_PROTOCOL
*Ip4
;
852 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
853 return EFI_INVALID_PARAMETER
;
857 // Retrieve the private context data structures
859 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
861 Status
= gBS
->OpenProtocol (
863 &gEfiIp4ProtocolGuid
,
865 gIp4DriverBinding
.DriverBindingHandle
,
867 EFI_OPEN_PROTOCOL_GET_PROTOCOL
870 if (EFI_ERROR (Status
)) {
871 return EFI_UNSUPPORTED
;
874 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (Ip4
);
876 if (IpInstance
->Service
!= IpSb
) {
877 return EFI_INVALID_PARAMETER
;
880 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
883 // A child can be destoried more than once. For example,
884 // Ip4DriverBindingStop will destory all of its children.
885 // when UDP driver is being stopped, it will destory all
886 // the IP child it opens.
888 if (IpInstance
->State
== IP4_STATE_DESTORY
) {
889 gBS
->RestoreTPL (OldTpl
);
893 State
= IpInstance
->State
;
894 IpInstance
->State
= IP4_STATE_DESTORY
;
897 // Close the Managed Network protocol.
900 IpSb
->MnpChildHandle
,
901 &gEfiManagedNetworkProtocolGuid
,
902 gIp4DriverBinding
.DriverBindingHandle
,
907 // Uninstall the IP4 protocol first. Many thing happens during
909 // 1. The consumer of the IP4 protocol will be stopped if it
910 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
911 // stopped, IP driver's stop function will be called, and uninstall
912 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This
913 // makes it possible to create the network stack bottom up, and
915 // 2. the upper layer will recycle the received packet. The recycle
916 // event's TPL is higher than this function. The recycle events
917 // will be called back before preceeding. If any packets not recycled,
918 // that means there is a resource leak.
920 Status
= gBS
->UninstallProtocolInterface (
922 &gEfiIp4ProtocolGuid
,
923 &IpInstance
->Ip4Proto
926 if (EFI_ERROR (Status
)) {
930 Status
= Ip4CleanProtocol (IpInstance
);
932 Ip4SetVariableData (IpSb
);
934 if (EFI_ERROR (Status
)) {
935 gBS
->InstallMultipleProtocolInterfaces (
937 &gEfiIp4ProtocolGuid
,
945 RemoveEntryList (&IpInstance
->Link
);
948 gBS
->RestoreTPL (OldTpl
);
950 gBS
->FreePool (IpInstance
);
954 IpInstance
->State
= State
;
955 gBS
->RestoreTPL (OldTpl
);