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
132 Create a new IP4 driver service binding protocol
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.
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
= NetAllocatePool (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 NetListInit (&IpSb
->Children
);
179 NetListInit (&IpSb
->Interfaces
);
180 IpSb
->DefaultInterface
= NULL
;
181 IpSb
->DefaultRouteTable
= NULL
;
183 Ip4InitAssembleTable (&IpSb
->Assemble
);
185 IpSb
->IgmpCtrl
.Igmpv1QuerySeen
= 0;
186 NetListInit (&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 NetZeroMem (&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 NetListInsertHead (&IpSb
->Interfaces
, &IpSb
->DefaultInterface
->Link
);
288 IpSb
->MacString
= NULL
;
294 Ip4CleanService (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 destoried. If a resource is
305 destoried, 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 Others 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
) {
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.
390 @param This Protocol instance pointer.
391 @param ControllerHandle Handle of device to bind driver to
392 @param RemainingDevicePath Optional parameter use to pick a specific child
395 @retval EFI_SUCCES This driver is added to ControllerHandle
396 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
397 @retval other This driver does not support this device
402 Ip4DriverBindingStart (
403 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
404 IN EFI_HANDLE ControllerHandle
,
405 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
412 // Test for the Ip4 service binding protocol
414 Status
= gBS
->OpenProtocol (
416 &gEfiIp4ServiceBindingProtocolGuid
,
418 This
->DriverBindingHandle
,
420 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
423 if (Status
== EFI_SUCCESS
) {
424 return EFI_ALREADY_STARTED
;
427 Status
= Ip4CreateService (ControllerHandle
, This
->DriverBindingHandle
, &IpSb
);
429 if (EFI_ERROR (Status
)) {
434 // Install the Ip4ServiceBinding Protocol onto ControlerHandle
436 Status
= gBS
->InstallMultipleProtocolInterfaces (
438 &gEfiIp4ServiceBindingProtocolGuid
,
439 &IpSb
->ServiceBinding
,
443 if (EFI_ERROR (Status
)) {
448 // ready to go: start the receiving and timer
450 Status
= Ip4ReceiveFrame (IpSb
->DefaultInterface
, NULL
, Ip4AccpetFrame
, IpSb
);
452 if (EFI_ERROR (Status
)) {
453 goto UNINSTALL_PROTOCOL
;
456 Status
= gBS
->SetTimer (IpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
458 if (EFI_ERROR (Status
)) {
459 goto UNINSTALL_PROTOCOL
;
463 // Initialize the IP4 ID
465 mIp4Id
= (UINT16
)NET_RANDOM (NetRandomInitSeed ());
467 Ip4SetVariableData (IpSb
);
472 gBS
->UninstallProtocolInterface (
474 &gEfiIp4ServiceBindingProtocolGuid
,
475 &IpSb
->ServiceBinding
479 Ip4CleanService (IpSb
);
487 Stop this driver on ControllerHandle.
489 @param This Protocol instance pointer.
490 @param ControllerHandle Handle of device to stop driver on
491 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
492 of children is zero stop the entire bus driver.
493 @param ChildHandleBuffer List of Child Handles to Stop.
495 @retval EFI_SUCCES This driver is removed ControllerHandle
496 @retval other This driver was not removed from this device
501 Ip4DriverBindingStop (
502 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
503 IN EFI_HANDLE ControllerHandle
,
504 IN UINTN NumberOfChildren
,
505 IN EFI_HANDLE
*ChildHandleBuffer
508 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
510 IP4_PROTOCOL
*IpInstance
;
511 EFI_HANDLE NicHandle
;
518 // IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol
519 // by driver. So the ControllerHandle may be the MNP child handle, ARP child
520 // handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed
521 // in the NIC handle.
524 // First, check whether it is the IP4_CONFIG protocol being uninstalled.
525 // IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary
526 // to clean up the default configuration if IP4_CONFIG is being stopped.
528 Status
= gBS
->OpenProtocol (
530 &gEfiIp4ConfigProtocolGuid
,
532 This
->DriverBindingHandle
,
534 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
537 if (Status
== EFI_SUCCESS
) {
539 // Retrieve the IP4 service binding protocol. If failed, it is
540 // likely that Ip4 ServiceBinding is uninstalled already. In this
541 // case, return immediately.
543 Status
= gBS
->OpenProtocol (
545 &gEfiIp4ServiceBindingProtocolGuid
,
546 (VOID
**) &ServiceBinding
,
547 This
->DriverBindingHandle
,
549 EFI_OPEN_PROTOCOL_GET_PROTOCOL
552 if (EFI_ERROR (Status
)) {
553 return EFI_DEVICE_ERROR
;
556 IpSb
= IP4_SERVICE_FROM_PROTOCOL (ServiceBinding
);
558 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
560 if (IpSb
->Ip4Config
&& (IpSb
->State
!= IP4_SERVICE_DESTORY
)) {
562 IpSb
->Ip4Config
->Stop (IpSb
->Ip4Config
);
564 Status
= gBS
->CloseProtocol (
566 &gEfiIp4ConfigProtocolGuid
,
571 if (EFI_ERROR (Status
)) {
572 NET_RESTORE_TPL (OldTpl
);
577 // If the auto configure hasn't complete, mark it as not started.
579 if (IpSb
->State
== IP4_SERVICE_STARTED
) {
580 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
583 IpSb
->Ip4Config
= NULL
;
584 gBS
->CloseEvent (IpSb
->DoneEvent
);
585 gBS
->CloseEvent (IpSb
->ReconfigEvent
);
588 NET_RESTORE_TPL (OldTpl
);
593 // Either MNP or ARP protocol is being uninstalled. The controller
594 // handle is either the MNP child or ARP child. But, the IP4's
595 // service binding is installed on the NIC handle. So, need to open
596 // the protocol info to find the NIC handle.
599 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiManagedNetworkProtocolGuid
);
601 if (NicHandle
== NULL
) {
602 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiArpProtocolGuid
);
606 if (NicHandle
== NULL
) {
607 return EFI_DEVICE_ERROR
;
611 // Retrieve the IP4 service binding protocol
613 Status
= gBS
->OpenProtocol (
615 &gEfiIp4ServiceBindingProtocolGuid
,
616 (VOID
**) &ServiceBinding
,
617 This
->DriverBindingHandle
,
619 EFI_OPEN_PROTOCOL_GET_PROTOCOL
622 if (EFI_ERROR (Status
)) {
623 return EFI_DEVICE_ERROR
;
626 IpSb
= IP4_SERVICE_FROM_PROTOCOL (ServiceBinding
);
628 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
630 if (IpSb
->InDestory
) {
631 NET_RESTORE_TPL (OldTpl
);
636 while (!NetListIsEmpty (&IpSb
->Children
)) {
637 IpInstance
= NET_LIST_HEAD (&IpSb
->Children
, IP4_PROTOCOL
, Link
);
639 ServiceBinding
->DestroyChild (ServiceBinding
, IpInstance
->Handle
);
642 if (IpSb
->NumChildren
!= 0) {
643 Status
= EFI_DEVICE_ERROR
;
647 IpSb
->InDestory
= TRUE
;
650 IpSb
->State
= IP4_SERVICE_DESTORY
;
653 // Clear the variable data.
655 Ip4ClearVariableData (IpSb
);
658 // OK, clean other resources then uninstall the service binding protocol.
660 Status
= Ip4CleanService (IpSb
);
662 if (EFI_ERROR (Status
)) {
667 gBS
->UninstallProtocolInterface (
669 &gEfiIp4ServiceBindingProtocolGuid
,
674 } else if (NumberOfChildren
== 0) {
675 IpSb
->InDestory
= TRUE
;
678 IpSb
->State
= IP4_SERVICE_DESTORY
;
681 // Clear the variable data.
683 Ip4ClearVariableData (IpSb
);
686 // OK, clean other resources then uninstall the service binding protocol.
688 Status
= Ip4CleanService (IpSb
);
690 if (EFI_ERROR (Status
)) {
695 gBS
->UninstallProtocolInterface (
697 &gEfiIp4ServiceBindingProtocolGuid
,
704 while (!NetListIsEmpty (&IpSb
->Children
)) {
705 IpInstance
= NET_LIST_HEAD (&IpSb
->Children
, IP4_PROTOCOL
, Link
);
707 ServiceBinding
->DestroyChild (ServiceBinding
, IpInstance
->Handle
);
710 if (IpSb
->NumChildren
!= 0) {
711 Status
= EFI_DEVICE_ERROR
;
717 NET_RESTORE_TPL (OldTpl
);
723 Creates a child handle with a set of I/O services.
725 @param This Protocol instance pointer.
726 @param ChildHandle Pointer to the handle of the child to create. If
727 it is NULL, then a new handle is created. If it
728 is not NULL, then the I/O services are added to
729 the existing child handle.
731 @retval EFI_SUCCES The child handle was created with the I/O services
732 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
734 @retval other The child handle was not created
739 Ip4ServiceBindingCreateChild (
740 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
741 IN EFI_HANDLE
*ChildHandle
745 IP4_PROTOCOL
*IpInstance
;
750 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
751 return EFI_INVALID_PARAMETER
;
754 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
755 IpInstance
= NetAllocatePool (sizeof (IP4_PROTOCOL
));
757 if (IpInstance
== NULL
) {
758 return EFI_OUT_OF_RESOURCES
;
761 Ip4InitProtocol (IpSb
, IpInstance
);
764 // Install Ip4 onto ChildHandle
766 Status
= gBS
->InstallMultipleProtocolInterfaces (
768 &gEfiIp4ProtocolGuid
,
769 &IpInstance
->Ip4Proto
,
773 if (EFI_ERROR (Status
)) {
777 IpInstance
->Handle
= *ChildHandle
;
780 // Open the Managed Network protocol BY_CHILD.
782 Status
= gBS
->OpenProtocol (
783 IpSb
->MnpChildHandle
,
784 &gEfiManagedNetworkProtocolGuid
,
786 gIp4DriverBinding
.DriverBindingHandle
,
788 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
790 if (EFI_ERROR (Status
)) {
791 gBS
->UninstallMultipleProtocolInterfaces (
793 &gEfiIp4ProtocolGuid
,
794 &IpInstance
->Ip4Proto
,
802 // Insert it into the service binding instance.
804 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
806 NetListInsertTail (&IpSb
->Children
, &IpInstance
->Link
);
809 NET_RESTORE_TPL (OldTpl
);
813 if (EFI_ERROR (Status
)) {
815 Ip4CleanProtocol (IpInstance
);
817 NetFreePool (IpInstance
);
825 Destroys a child handle with a set of I/O services.
827 @param This Protocol instance pointer.
828 @param ChildHandle Handle of the child to destroy
830 @retval EFI_SUCCES The I/O services were removed from the child
832 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
833 that are being removed
834 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
835 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
836 its I/O services are being used.
837 @retval other The child handle was not destroyed
842 Ip4ServiceBindingDestroyChild (
843 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
844 IN EFI_HANDLE ChildHandle
849 IP4_PROTOCOL
*IpInstance
;
850 EFI_IP4_PROTOCOL
*Ip4
;
854 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
855 return EFI_INVALID_PARAMETER
;
859 // Retrieve the private context data structures
861 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
863 Status
= gBS
->OpenProtocol (
865 &gEfiIp4ProtocolGuid
,
867 gIp4DriverBinding
.DriverBindingHandle
,
869 EFI_OPEN_PROTOCOL_GET_PROTOCOL
872 if (EFI_ERROR (Status
)) {
873 return EFI_UNSUPPORTED
;
876 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (Ip4
);
878 if (IpInstance
->Service
!= IpSb
) {
879 return EFI_INVALID_PARAMETER
;
882 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
885 // A child can be destoried more than once. For example,
886 // Ip4DriverBindingStop will destory all of its children.
887 // when UDP driver is being stopped, it will destory all
888 // the IP child it opens.
890 if (IpInstance
->State
== IP4_STATE_DESTORY
) {
891 NET_RESTORE_TPL (OldTpl
);
895 State
= IpInstance
->State
;
896 IpInstance
->State
= IP4_STATE_DESTORY
;
899 // Close the Managed Network protocol.
902 IpSb
->MnpChildHandle
,
903 &gEfiManagedNetworkProtocolGuid
,
904 gIp4DriverBinding
.DriverBindingHandle
,
909 // Uninstall the IP4 protocol first. Many thing happens during
911 // 1. The consumer of the IP4 protocol will be stopped if it
912 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
913 // stopped, IP driver's stop function will be called, and uninstall
914 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This
915 // makes it possible to create the network stack bottom up, and
917 // 2. the upper layer will recycle the received packet. The recycle
918 // event's TPL is higher than this function. The recycle events
919 // will be called back before preceeding. If any packets not recycled,
920 // that means there is a resource leak.
922 Status
= gBS
->UninstallProtocolInterface (
924 &gEfiIp4ProtocolGuid
,
925 &IpInstance
->Ip4Proto
928 if (EFI_ERROR (Status
)) {
932 Status
= Ip4CleanProtocol (IpInstance
);
934 Ip4SetVariableData (IpSb
);
936 if (EFI_ERROR (Status
)) {
937 gBS
->InstallMultipleProtocolInterfaces (
939 &gEfiIp4ProtocolGuid
,
947 NetListRemoveEntry (&IpInstance
->Link
);
950 NET_RESTORE_TPL (OldTpl
);
952 NetFreePool (IpInstance
);
956 IpInstance
->State
= State
;
957 NET_RESTORE_TPL (OldTpl
);