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
,
34 //@MT: EFI_DRIVER_ENTRY_POINT (Ip4DriverEntryPoint)
39 IN EFI_HANDLE ImageHandle
,
40 IN EFI_SYSTEM_TABLE
*SystemTable
46 The entry point for IP4 driver which install the driver
47 binding and component name protocol on its image.
51 ImageHandle - The image handle of the driver
52 SystemTable - The system table
56 EFI_SUCCESS if the driver binding and component name protocols
57 are successfully installed, otherwise if failed.
61 return NetLibInstallAllDriverProtocols (
74 Test to see if this driver supports ControllerHandle.
76 @param This Protocol instance pointer.
77 @param ControllerHandle Handle of device to test
78 @param RemainingDevicePath Optional parameter use to pick a specific child
81 @retval EFI_SUCCES This driver supports this device
82 @retval EFI_ALREADY_STARTED This driver is already running on this device
83 @retval other This driver does not support this device
88 Ip4DriverBindingSupported (
89 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
90 IN EFI_HANDLE ControllerHandle
,
91 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
97 // Test for the MNP service binding Protocol
99 Status
= gBS
->OpenProtocol (
101 &gEfiManagedNetworkServiceBindingProtocolGuid
,
103 This
->DriverBindingHandle
,
105 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
108 if (EFI_ERROR (Status
)) {
113 // Test for the Arp service binding Protocol
115 Status
= gBS
->OpenProtocol (
117 &gEfiArpServiceBindingProtocolGuid
,
119 This
->DriverBindingHandle
,
121 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
135 Create a new IP4 driver service binding protocol
137 @param Controller The controller that has MNP service binding
139 @param ImageHandle The IP4 driver's image handle
140 @param Service The variable to receive the newly created IP4
143 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource
144 @retval EFI_SUCCESS A new IP4 service binding private is created.
150 IN EFI_HANDLE Controller
,
151 IN EFI_HANDLE ImageHandle
,
152 OUT IP4_SERVICE
**Service
158 ASSERT (Service
!= NULL
);
163 // allocate a service private data then initialize all the filed to
164 // empty resources, so if any thing goes wrong when allocating
165 // resources, Ip4CleanService can be called to clean it up.
167 IpSb
= NetAllocatePool (sizeof (IP4_SERVICE
));
170 return EFI_OUT_OF_RESOURCES
;
173 IpSb
->Signature
= IP4_SERVICE_SIGNATURE
;
174 IpSb
->ServiceBinding
.CreateChild
= Ip4ServiceBindingCreateChild
;
175 IpSb
->ServiceBinding
.DestroyChild
= Ip4ServiceBindingDestroyChild
;
176 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
177 IpSb
->InDestory
= FALSE
;
179 IpSb
->NumChildren
= 0;
180 NetListInit (&IpSb
->Children
);
182 NetListInit (&IpSb
->Interfaces
);
183 IpSb
->DefaultInterface
= NULL
;
184 IpSb
->DefaultRouteTable
= NULL
;
186 Ip4InitAssembleTable (&IpSb
->Assemble
);
188 IpSb
->IgmpCtrl
.Igmpv1QuerySeen
= 0;
189 NetListInit (&IpSb
->IgmpCtrl
.Groups
);
191 IpSb
->Image
= ImageHandle
;
192 IpSb
->Controller
= Controller
;
194 IpSb
->MnpChildHandle
= NULL
;
197 IpSb
->MnpConfigData
.ReceivedQueueTimeoutValue
= 0;
198 IpSb
->MnpConfigData
.TransmitQueueTimeoutValue
= 0;
199 IpSb
->MnpConfigData
.ProtocolTypeFilter
= IP4_ETHER_PROTO
;
200 IpSb
->MnpConfigData
.EnableUnicastReceive
= TRUE
;
201 IpSb
->MnpConfigData
.EnableMulticastReceive
= TRUE
;
202 IpSb
->MnpConfigData
.EnableBroadcastReceive
= TRUE
;
203 IpSb
->MnpConfigData
.EnablePromiscuousReceive
= FALSE
;
204 IpSb
->MnpConfigData
.FlushQueuesOnReset
= TRUE
;
205 IpSb
->MnpConfigData
.EnableReceiveTimestamps
= FALSE
;
206 IpSb
->MnpConfigData
.DisableBackgroundPolling
= FALSE
;
208 NetZeroMem (&IpSb
->SnpMode
, sizeof (EFI_SIMPLE_NETWORK_MODE
));
211 IpSb
->Ip4Config
= NULL
;
212 IpSb
->DoneEvent
= NULL
;
213 IpSb
->ReconfigEvent
= NULL
;
216 // Create various resources. First create the route table, timer
217 // event and MNP child. IGMP, interface's initialization depend
220 IpSb
->DefaultRouteTable
= Ip4CreateRouteTable ();
222 if (IpSb
->DefaultRouteTable
== NULL
) {
223 Status
= EFI_OUT_OF_RESOURCES
;
227 Status
= gBS
->CreateEvent (
228 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
235 if (EFI_ERROR (Status
)) {
239 Status
= NetLibCreateServiceChild (
242 &gEfiManagedNetworkServiceBindingProtocolGuid
,
243 &IpSb
->MnpChildHandle
246 if (EFI_ERROR (Status
)) {
250 Status
= gBS
->OpenProtocol (
251 IpSb
->MnpChildHandle
,
252 &gEfiManagedNetworkProtocolGuid
,
253 (VOID
**) &IpSb
->Mnp
,
256 EFI_OPEN_PROTOCOL_BY_DRIVER
259 if (EFI_ERROR (Status
)) {
263 Status
= Ip4ServiceConfigMnp (IpSb
, TRUE
);
265 if (EFI_ERROR (Status
)) {
269 Status
= IpSb
->Mnp
->GetModeData (IpSb
->Mnp
, NULL
, &IpSb
->SnpMode
);
271 if (EFI_ERROR (Status
)) {
275 Status
= Ip4InitIgmp (IpSb
);
277 if (EFI_ERROR (Status
)) {
281 IpSb
->DefaultInterface
= Ip4CreateInterface (IpSb
->Mnp
, Controller
, ImageHandle
);
283 if (IpSb
->DefaultInterface
== NULL
) {
284 Status
= EFI_OUT_OF_RESOURCES
;
288 NetListInsertHead (&IpSb
->Interfaces
, &IpSb
->DefaultInterface
->Link
);
290 IpSb
->MacString
= NULL
;
296 Ip4CleanService (IpSb
);
304 Clean up a IP4 service binding instance. It will release all
305 the resource allocated by the instance. The instance may be
306 partly initialized, or partly destoried. If a resource is
307 destoried, it is marked as that in case the destory failed and
308 being called again later.
310 @param IpSb The IP4 serviceing binding instance to clean up
312 @retval EFI_SUCCESS The resource used by the instance are cleaned up
313 @retval Others Failed to clean up some of the resources.
323 if (IpSb
->DefaultInterface
!= NULL
) {
324 Status
= Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
326 if (EFI_ERROR (Status
)) {
330 IpSb
->DefaultInterface
= NULL
;
333 if (IpSb
->DefaultRouteTable
!= NULL
) {
334 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
335 IpSb
->DefaultRouteTable
= NULL
;
338 Ip4CleanAssembleTable (&IpSb
->Assemble
);
340 if (IpSb
->MnpChildHandle
!= NULL
) {
343 IpSb
->MnpChildHandle
,
344 &gEfiManagedNetworkProtocolGuid
,
352 NetLibDestroyServiceChild (
355 &gEfiManagedNetworkServiceBindingProtocolGuid
,
359 IpSb
->MnpChildHandle
= NULL
;
362 if (IpSb
->Timer
!= NULL
) {
363 gBS
->SetTimer (IpSb
->Timer
, TimerCancel
, 0);
364 gBS
->CloseEvent (IpSb
->Timer
);
369 if (IpSb
->Ip4Config
!= NULL
) {
370 IpSb
->Ip4Config
->Stop (IpSb
->Ip4Config
);
374 &gEfiIp4ConfigProtocolGuid
,
379 gBS
->CloseEvent (IpSb
->DoneEvent
);
380 gBS
->CloseEvent (IpSb
->ReconfigEvent
);
381 IpSb
->Ip4Config
= NULL
;
389 Start this driver on ControllerHandle.
391 @param This Protocol instance pointer.
392 @param ControllerHandle Handle of device to bind driver to
393 @param RemainingDevicePath Optional parameter use to pick a specific child
396 @retval EFI_SUCCES This driver is added to ControllerHandle
397 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
398 @retval other This driver does not support this device
403 Ip4DriverBindingStart (
404 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
405 IN EFI_HANDLE ControllerHandle
,
406 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
413 // Test for the Ip4 service binding protocol
415 Status
= gBS
->OpenProtocol (
417 &gEfiIp4ServiceBindingProtocolGuid
,
419 This
->DriverBindingHandle
,
421 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
424 if (Status
== EFI_SUCCESS
) {
425 return EFI_ALREADY_STARTED
;
428 Status
= Ip4CreateService (ControllerHandle
, This
->DriverBindingHandle
, &IpSb
);
430 if (EFI_ERROR (Status
)) {
435 // Install the Ip4ServiceBinding Protocol onto ControlerHandle
437 Status
= gBS
->InstallMultipleProtocolInterfaces (
439 &gEfiIp4ServiceBindingProtocolGuid
,
440 &IpSb
->ServiceBinding
,
444 if (EFI_ERROR (Status
)) {
449 // ready to go: start the receiving and timer
451 Status
= Ip4ReceiveFrame (IpSb
->DefaultInterface
, NULL
, Ip4AccpetFrame
, IpSb
);
453 if (EFI_ERROR (Status
)) {
454 goto UNINSTALL_PROTOCOL
;
457 Status
= gBS
->SetTimer (IpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
459 if (EFI_ERROR (Status
)) {
460 goto UNINSTALL_PROTOCOL
;
464 // Initialize the IP4 ID
466 mIp4Id
= (UINT16
)NET_RANDOM (NetRandomInitSeed ());
468 Ip4SetVariableData (IpSb
);
473 gBS
->UninstallProtocolInterface (
475 &gEfiIp4ServiceBindingProtocolGuid
,
476 &IpSb
->ServiceBinding
480 Ip4CleanService (IpSb
);
488 Stop this driver on ControllerHandle.
490 @param This Protocol instance pointer.
491 @param ControllerHandle Handle of device to stop driver on
492 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
493 of children is zero stop the entire bus driver.
494 @param ChildHandleBuffer List of Child Handles to Stop.
496 @retval EFI_SUCCES This driver is removed ControllerHandle
497 @retval other This driver was not removed from this device
502 Ip4DriverBindingStop (
503 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
504 IN EFI_HANDLE ControllerHandle
,
505 IN UINTN NumberOfChildren
,
506 IN EFI_HANDLE
*ChildHandleBuffer
509 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
511 IP4_PROTOCOL
*IpInstance
;
512 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
)) {
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.
598 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiManagedNetworkProtocolGuid
);
600 if (NicHandle
== NULL
) {
601 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiArpProtocolGuid
);
604 if (NicHandle
== NULL
) {
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
= NET_RAISE_TPL (NET_TPL_LOCK
);
628 if (IpSb
->InDestory
) {
629 NET_RESTORE_TPL (OldTpl
);
633 IpSb
->InDestory
= TRUE
;
636 IpSb
->State
= IP4_SERVICE_DESTORY
;
639 // Destory all the children first. If not all children are destoried,
640 // the IP driver can operate correctly, so restore it state. Don't
641 // use NET_LIST_FOR_EACH_SAFE here, because it will cache the next
642 // pointer, which may point to the child that has already been destoried.
643 // For example, if there are two child in the list, the first is UDP
644 // listen child, the send is the MTFTP's child. When Udp child is
645 // destoried, it will destory the MTFTP's child. Then Next point to
648 while (!NetListIsEmpty (&IpSb
->Children
)) {
649 IpInstance
= NET_LIST_HEAD (&IpSb
->Children
, IP4_PROTOCOL
, Link
);
650 Ip4ServiceBindingDestroyChild (ServiceBinding
, IpInstance
->Handle
);
653 if (IpSb
->NumChildren
!= 0) {
655 Status
= EFI_DEVICE_ERROR
;
660 // Clear the variable data.
662 Ip4ClearVariableData (IpSb
);
665 // OK, clean other resources then uninstall the service binding protocol.
667 Status
= Ip4CleanService (IpSb
);
669 if (EFI_ERROR (Status
)) {
673 Status
= gBS
->UninstallProtocolInterface (
675 &gEfiIp4ServiceBindingProtocolGuid
,
679 if (EFI_ERROR (Status
)) {
683 NET_RESTORE_TPL (OldTpl
);
688 IpSb
->InDestory
= FALSE
;
689 NET_RESTORE_TPL (OldTpl
);
695 Creates a child handle with a set of I/O services.
697 @param This Protocol instance pointer.
698 @param ChildHandle Pointer to the handle of the child to create. If
699 it is NULL, then a new handle is created. If it
700 is not NULL, then the I/O services are added to
701 the existing child handle.
703 @retval EFI_SUCCES The child handle was created with the I/O services
704 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
706 @retval other The child handle was not created
711 Ip4ServiceBindingCreateChild (
712 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
713 IN EFI_HANDLE
*ChildHandle
717 IP4_PROTOCOL
*IpInstance
;
722 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
723 return EFI_INVALID_PARAMETER
;
726 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
727 IpInstance
= NetAllocatePool (sizeof (IP4_PROTOCOL
));
729 if (IpInstance
== NULL
) {
730 return EFI_OUT_OF_RESOURCES
;
733 Ip4InitProtocol (IpSb
, IpInstance
);
736 // Install Ip4 onto ChildHandle
738 Status
= gBS
->InstallMultipleProtocolInterfaces (
740 &gEfiIp4ProtocolGuid
,
741 &IpInstance
->Ip4Proto
,
745 if (EFI_ERROR (Status
)) {
749 IpInstance
->Handle
= *ChildHandle
;
752 // Open the Managed Network protocol BY_CHILD.
754 Status
= gBS
->OpenProtocol (
755 IpSb
->MnpChildHandle
,
756 &gEfiManagedNetworkProtocolGuid
,
758 gIp4DriverBinding
.DriverBindingHandle
,
760 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
762 if (EFI_ERROR (Status
)) {
763 gBS
->UninstallMultipleProtocolInterfaces (
765 &gEfiIp4ProtocolGuid
,
766 &IpInstance
->Ip4Proto
,
774 // Insert it into the service binding instance.
776 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
778 NetListInsertTail (&IpSb
->Children
, &IpInstance
->Link
);
781 NET_RESTORE_TPL (OldTpl
);
785 if (EFI_ERROR (Status
)) {
787 Ip4CleanProtocol (IpInstance
);
789 NetFreePool (IpInstance
);
797 Destroys a child handle with a set of I/O services.
799 @param This Protocol instance pointer.
800 @param ChildHandle Handle of the child to destroy
802 @retval EFI_SUCCES The I/O services were removed from the child
804 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
805 that are being removed
806 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
807 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
808 its I/O services are being used.
809 @retval other The child handle was not destroyed
814 Ip4ServiceBindingDestroyChild (
815 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
816 IN EFI_HANDLE ChildHandle
821 IP4_PROTOCOL
*IpInstance
;
822 EFI_IP4_PROTOCOL
*Ip4
;
826 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
827 return EFI_INVALID_PARAMETER
;
831 // Retrieve the private context data structures
833 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
835 Status
= gBS
->OpenProtocol (
837 &gEfiIp4ProtocolGuid
,
839 gIp4DriverBinding
.DriverBindingHandle
,
841 EFI_OPEN_PROTOCOL_GET_PROTOCOL
844 if (EFI_ERROR (Status
)) {
845 return EFI_UNSUPPORTED
;
848 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (Ip4
);
850 if (IpInstance
->Service
!= IpSb
) {
851 return EFI_INVALID_PARAMETER
;
854 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
857 // A child can be destoried more than once. For example,
858 // Ip4DriverBindingStop will destory all of its children.
859 // when UDP driver is being stopped, it will destory all
860 // the IP child it opens.
862 if (IpInstance
->State
== IP4_STATE_DESTORY
) {
863 NET_RESTORE_TPL (OldTpl
);
867 State
= IpInstance
->State
;
868 IpInstance
->State
= IP4_STATE_DESTORY
;
871 // Close the Managed Network protocol.
874 IpSb
->MnpChildHandle
,
875 &gEfiManagedNetworkProtocolGuid
,
876 gIp4DriverBinding
.DriverBindingHandle
,
881 // Uninstall the IP4 protocol first. Many thing happens during
883 // 1. The consumer of the IP4 protocol will be stopped if it
884 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
885 // stopped, IP driver's stop function will be called, and uninstall
886 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This
887 // makes it possible to create the network stack bottom up, and
889 // 2. the upper layer will recycle the received packet. The recycle
890 // event's TPL is higher than this function. The recycle events
891 // will be called back before preceeding. If any packets not recycled,
892 // that means there is a resource leak.
894 Status
= gBS
->UninstallProtocolInterface (
896 &gEfiIp4ProtocolGuid
,
897 &IpInstance
->Ip4Proto
900 if (EFI_ERROR (Status
)) {
904 Status
= Ip4CleanProtocol (IpInstance
);
906 Ip4SetVariableData (IpSb
);
908 if (EFI_ERROR (Status
)) {
909 gBS
->InstallMultipleProtocolInterfaces (
911 &gEfiIp4ProtocolGuid
,
919 NetListRemoveEntry (&IpInstance
->Link
);
922 NET_RESTORE_TPL (OldTpl
);
924 NetFreePool (IpInstance
);
928 IpInstance
->State
= State
;
929 NET_RESTORE_TPL (OldTpl
);