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 NetLibInstallAllDriverProtocols (
72 Test to see if this driver supports ControllerHandle.
74 @param This Protocol instance pointer.
75 @param ControllerHandle Handle of device to test
76 @param RemainingDevicePath Optional parameter use to pick a specific child
79 @retval EFI_SUCCES This driver supports this device
80 @retval EFI_ALREADY_STARTED This driver is already running on this device
81 @retval other This driver does not support this device
86 Ip4DriverBindingSupported (
87 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
88 IN EFI_HANDLE ControllerHandle
,
89 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
95 // Test for the MNP service binding Protocol
97 Status
= gBS
->OpenProtocol (
99 &gEfiManagedNetworkServiceBindingProtocolGuid
,
101 This
->DriverBindingHandle
,
103 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
106 if (EFI_ERROR (Status
)) {
111 // Test for the Arp service binding Protocol
113 Status
= gBS
->OpenProtocol (
115 &gEfiArpServiceBindingProtocolGuid
,
117 This
->DriverBindingHandle
,
119 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
133 Create a new IP4 driver service binding protocol
135 @param Controller The controller that has MNP service binding
137 @param ImageHandle The IP4 driver's image handle
138 @param Service The variable to receive the newly created IP4
141 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource
142 @retval EFI_SUCCESS A new IP4 service binding private is created.
148 IN EFI_HANDLE Controller
,
149 IN EFI_HANDLE ImageHandle
,
150 OUT IP4_SERVICE
**Service
156 ASSERT (Service
!= NULL
);
161 // allocate a service private data then initialize all the filed to
162 // empty resources, so if any thing goes wrong when allocating
163 // resources, Ip4CleanService can be called to clean it up.
165 IpSb
= NetAllocatePool (sizeof (IP4_SERVICE
));
168 return EFI_OUT_OF_RESOURCES
;
171 IpSb
->Signature
= IP4_SERVICE_SIGNATURE
;
172 IpSb
->ServiceBinding
.CreateChild
= Ip4ServiceBindingCreateChild
;
173 IpSb
->ServiceBinding
.DestroyChild
= Ip4ServiceBindingDestroyChild
;
174 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
175 IpSb
->InDestory
= FALSE
;
177 IpSb
->NumChildren
= 0;
178 NetListInit (&IpSb
->Children
);
180 NetListInit (&IpSb
->Interfaces
);
181 IpSb
->DefaultInterface
= NULL
;
182 IpSb
->DefaultRouteTable
= NULL
;
184 Ip4InitAssembleTable (&IpSb
->Assemble
);
186 IpSb
->IgmpCtrl
.Igmpv1QuerySeen
= 0;
187 NetListInit (&IpSb
->IgmpCtrl
.Groups
);
189 IpSb
->Image
= ImageHandle
;
190 IpSb
->Controller
= Controller
;
192 IpSb
->MnpChildHandle
= NULL
;
195 IpSb
->MnpConfigData
.ReceivedQueueTimeoutValue
= 0;
196 IpSb
->MnpConfigData
.TransmitQueueTimeoutValue
= 0;
197 IpSb
->MnpConfigData
.ProtocolTypeFilter
= IP4_ETHER_PROTO
;
198 IpSb
->MnpConfigData
.EnableUnicastReceive
= TRUE
;
199 IpSb
->MnpConfigData
.EnableMulticastReceive
= TRUE
;
200 IpSb
->MnpConfigData
.EnableBroadcastReceive
= TRUE
;
201 IpSb
->MnpConfigData
.EnablePromiscuousReceive
= FALSE
;
202 IpSb
->MnpConfigData
.FlushQueuesOnReset
= TRUE
;
203 IpSb
->MnpConfigData
.EnableReceiveTimestamps
= FALSE
;
204 IpSb
->MnpConfigData
.DisableBackgroundPolling
= FALSE
;
206 NetZeroMem (&IpSb
->SnpMode
, sizeof (EFI_SIMPLE_NETWORK_MODE
));
209 IpSb
->Ip4Config
= NULL
;
210 IpSb
->DoneEvent
= NULL
;
211 IpSb
->ReconfigEvent
= 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
->Ip4Config
= NULL
;
387 Start this driver on ControllerHandle.
389 @param This Protocol instance pointer.
390 @param ControllerHandle Handle of device to bind driver to
391 @param RemainingDevicePath Optional parameter use to pick a specific child
394 @retval EFI_SUCCES This driver is added to ControllerHandle
395 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
396 @retval other This driver does not support this device
401 Ip4DriverBindingStart (
402 IN EFI_DRIVER_BINDING_PROTOCOL
* This
,
403 IN EFI_HANDLE ControllerHandle
,
404 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
411 // Test for the Ip4 service binding protocol
413 Status
= gBS
->OpenProtocol (
415 &gEfiIp4ServiceBindingProtocolGuid
,
417 This
->DriverBindingHandle
,
419 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
422 if (Status
== EFI_SUCCESS
) {
423 return EFI_ALREADY_STARTED
;
426 Status
= Ip4CreateService (ControllerHandle
, This
->DriverBindingHandle
, &IpSb
);
428 if (EFI_ERROR (Status
)) {
433 // Install the Ip4ServiceBinding Protocol onto ControlerHandle
435 Status
= gBS
->InstallMultipleProtocolInterfaces (
437 &gEfiIp4ServiceBindingProtocolGuid
,
438 &IpSb
->ServiceBinding
,
442 if (EFI_ERROR (Status
)) {
447 // ready to go: start the receiving and timer
449 Status
= Ip4ReceiveFrame (IpSb
->DefaultInterface
, NULL
, Ip4AccpetFrame
, IpSb
);
451 if (EFI_ERROR (Status
)) {
452 goto UNINSTALL_PROTOCOL
;
455 Status
= gBS
->SetTimer (IpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
457 if (EFI_ERROR (Status
)) {
458 goto UNINSTALL_PROTOCOL
;
462 // Initialize the IP4 ID
464 mIp4Id
= (UINT16
)NET_RANDOM (NetRandomInitSeed ());
466 Ip4SetVariableData (IpSb
);
471 gBS
->UninstallProtocolInterface (
473 &gEfiIp4ServiceBindingProtocolGuid
,
474 &IpSb
->ServiceBinding
478 Ip4CleanService (IpSb
);
486 Stop this driver on ControllerHandle.
488 @param This Protocol instance pointer.
489 @param ControllerHandle Handle of device to stop driver on
490 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
491 of children is zero stop the entire bus driver.
492 @param ChildHandleBuffer List of Child Handles to Stop.
494 @retval EFI_SUCCES This driver is removed ControllerHandle
495 @retval other This driver was not removed from this device
500 Ip4DriverBindingStop (
501 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
502 IN EFI_HANDLE ControllerHandle
,
503 IN UINTN NumberOfChildren
,
504 IN EFI_HANDLE
*ChildHandleBuffer
507 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
509 IP4_PROTOCOL
*IpInstance
;
510 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
)) {
554 IpSb
= IP4_SERVICE_FROM_PROTOCOL (ServiceBinding
);
556 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
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 NET_RESTORE_TPL (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 NET_RESTORE_TPL (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.
596 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiManagedNetworkProtocolGuid
);
598 if (NicHandle
== NULL
) {
599 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiArpProtocolGuid
);
602 if (NicHandle
== NULL
) {
607 // Retrieve the IP4 service binding protocol
609 Status
= gBS
->OpenProtocol (
611 &gEfiIp4ServiceBindingProtocolGuid
,
612 (VOID
**) &ServiceBinding
,
613 This
->DriverBindingHandle
,
615 EFI_OPEN_PROTOCOL_GET_PROTOCOL
618 if (EFI_ERROR (Status
)) {
619 return EFI_DEVICE_ERROR
;
622 IpSb
= IP4_SERVICE_FROM_PROTOCOL (ServiceBinding
);
624 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
626 if (IpSb
->InDestory
) {
627 NET_RESTORE_TPL (OldTpl
);
631 IpSb
->InDestory
= TRUE
;
634 IpSb
->State
= IP4_SERVICE_DESTORY
;
637 // Destory all the children first. If not all children are destoried,
638 // the IP driver can operate correctly, so restore it state. Don't
639 // use NET_LIST_FOR_EACH_SAFE here, because it will cache the next
640 // pointer, which may point to the child that has already been destoried.
641 // For example, if there are two child in the list, the first is UDP
642 // listen child, the send is the MTFTP's child. When Udp child is
643 // destoried, it will destory the MTFTP's child. Then Next point to
646 while (!NetListIsEmpty (&IpSb
->Children
)) {
647 IpInstance
= NET_LIST_HEAD (&IpSb
->Children
, IP4_PROTOCOL
, Link
);
648 Ip4ServiceBindingDestroyChild (ServiceBinding
, IpInstance
->Handle
);
651 if (IpSb
->NumChildren
!= 0) {
653 Status
= EFI_DEVICE_ERROR
;
658 // Clear the variable data.
660 Ip4ClearVariableData (IpSb
);
663 // OK, clean other resources then uninstall the service binding protocol.
665 Status
= Ip4CleanService (IpSb
);
667 if (EFI_ERROR (Status
)) {
671 Status
= gBS
->UninstallProtocolInterface (
673 &gEfiIp4ServiceBindingProtocolGuid
,
677 if (EFI_ERROR (Status
)) {
681 NET_RESTORE_TPL (OldTpl
);
686 IpSb
->InDestory
= FALSE
;
687 NET_RESTORE_TPL (OldTpl
);
693 Creates a child handle with a set of I/O services.
695 @param This Protocol instance pointer.
696 @param ChildHandle Pointer to the handle of the child to create. If
697 it is NULL, then a new handle is created. If it
698 is not NULL, then the I/O services are added to
699 the existing child handle.
701 @retval EFI_SUCCES The child handle was created with the I/O services
702 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
704 @retval other The child handle was not created
709 Ip4ServiceBindingCreateChild (
710 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
711 IN EFI_HANDLE
*ChildHandle
715 IP4_PROTOCOL
*IpInstance
;
720 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
721 return EFI_INVALID_PARAMETER
;
724 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
725 IpInstance
= NetAllocatePool (sizeof (IP4_PROTOCOL
));
727 if (IpInstance
== NULL
) {
728 return EFI_OUT_OF_RESOURCES
;
731 Ip4InitProtocol (IpSb
, IpInstance
);
734 // Install Ip4 onto ChildHandle
736 Status
= gBS
->InstallMultipleProtocolInterfaces (
738 &gEfiIp4ProtocolGuid
,
739 &IpInstance
->Ip4Proto
,
743 if (EFI_ERROR (Status
)) {
747 IpInstance
->Handle
= *ChildHandle
;
750 // Open the Managed Network protocol BY_CHILD.
752 Status
= gBS
->OpenProtocol (
753 IpSb
->MnpChildHandle
,
754 &gEfiManagedNetworkProtocolGuid
,
756 gIp4DriverBinding
.DriverBindingHandle
,
758 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
760 if (EFI_ERROR (Status
)) {
761 gBS
->UninstallMultipleProtocolInterfaces (
763 &gEfiIp4ProtocolGuid
,
764 &IpInstance
->Ip4Proto
,
772 // Insert it into the service binding instance.
774 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
776 NetListInsertTail (&IpSb
->Children
, &IpInstance
->Link
);
779 NET_RESTORE_TPL (OldTpl
);
783 if (EFI_ERROR (Status
)) {
785 Ip4CleanProtocol (IpInstance
);
787 NetFreePool (IpInstance
);
795 Destroys a child handle with a set of I/O services.
797 @param This Protocol instance pointer.
798 @param ChildHandle Handle of the child to destroy
800 @retval EFI_SUCCES The I/O services were removed from the child
802 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
803 that are being removed
804 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
805 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
806 its I/O services are being used.
807 @retval other The child handle was not destroyed
812 Ip4ServiceBindingDestroyChild (
813 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
814 IN EFI_HANDLE ChildHandle
819 IP4_PROTOCOL
*IpInstance
;
820 EFI_IP4_PROTOCOL
*Ip4
;
824 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
825 return EFI_INVALID_PARAMETER
;
829 // Retrieve the private context data structures
831 IpSb
= IP4_SERVICE_FROM_PROTOCOL (This
);
833 Status
= gBS
->OpenProtocol (
835 &gEfiIp4ProtocolGuid
,
837 gIp4DriverBinding
.DriverBindingHandle
,
839 EFI_OPEN_PROTOCOL_GET_PROTOCOL
842 if (EFI_ERROR (Status
)) {
843 return EFI_UNSUPPORTED
;
846 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (Ip4
);
848 if (IpInstance
->Service
!= IpSb
) {
849 return EFI_INVALID_PARAMETER
;
852 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
855 // A child can be destoried more than once. For example,
856 // Ip4DriverBindingStop will destory all of its children.
857 // when UDP driver is being stopped, it will destory all
858 // the IP child it opens.
860 if (IpInstance
->State
== IP4_STATE_DESTORY
) {
861 NET_RESTORE_TPL (OldTpl
);
865 State
= IpInstance
->State
;
866 IpInstance
->State
= IP4_STATE_DESTORY
;
869 // Close the Managed Network protocol.
872 IpSb
->MnpChildHandle
,
873 &gEfiManagedNetworkProtocolGuid
,
874 gIp4DriverBinding
.DriverBindingHandle
,
879 // Uninstall the IP4 protocol first. Many thing happens during
881 // 1. The consumer of the IP4 protocol will be stopped if it
882 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
883 // stopped, IP driver's stop function will be called, and uninstall
884 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This
885 // makes it possible to create the network stack bottom up, and
887 // 2. the upper layer will recycle the received packet. The recycle
888 // event's TPL is higher than this function. The recycle events
889 // will be called back before preceeding. If any packets not recycled,
890 // that means there is a resource leak.
892 Status
= gBS
->UninstallProtocolInterface (
894 &gEfiIp4ProtocolGuid
,
895 &IpInstance
->Ip4Proto
898 if (EFI_ERROR (Status
)) {
902 Status
= Ip4CleanProtocol (IpInstance
);
904 Ip4SetVariableData (IpSb
);
906 if (EFI_ERROR (Status
)) {
907 gBS
->InstallMultipleProtocolInterfaces (
909 &gEfiIp4ProtocolGuid
,
917 NetListRemoveEntry (&IpInstance
->Link
);
920 NET_RESTORE_TPL (OldTpl
);
922 NetFreePool (IpInstance
);
926 IpInstance
->State
= State
;
927 NET_RESTORE_TPL (OldTpl
);