2 The driver binding and service binding protocol for DnsDxe driver.
4 Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 EFI_DRIVER_BINDING_PROTOCOL gDns4DriverBinding
= {
18 Dns4DriverBindingSupported
,
19 Dns4DriverBindingStart
,
20 Dns4DriverBindingStop
,
26 EFI_DRIVER_BINDING_PROTOCOL gDns6DriverBinding
= {
27 Dns6DriverBindingSupported
,
28 Dns6DriverBindingStart
,
29 Dns6DriverBindingStop
,
35 EFI_SERVICE_BINDING_PROTOCOL mDns4ServiceBinding
= {
36 Dns4ServiceBindingCreateChild
,
37 Dns4ServiceBindingDestroyChild
40 EFI_SERVICE_BINDING_PROTOCOL mDns6ServiceBinding
= {
41 Dns6ServiceBindingCreateChild
,
42 Dns6ServiceBindingDestroyChild
45 DNS_DRIVER_DATA
*mDriverData
= NULL
;
48 Destroy the DNS instance and recycle the resources.
50 @param[in] Instance The pointer to the DNS instance.
55 IN DNS_INSTANCE
*Instance
58 ZeroMem (&Instance
->Dns4CfgData
, sizeof (EFI_DNS4_CONFIG_DATA
));
60 ZeroMem (&Instance
->Dns6CfgData
, sizeof (EFI_DNS6_CONFIG_DATA
));
62 if (!NetMapIsEmpty (&Instance
->Dns4TxTokens
)) {
63 Dns4InstanceCancelToken (Instance
, NULL
);
66 if (!NetMapIsEmpty (&Instance
->Dns6TxTokens
)) {
67 Dns6InstanceCancelToken (Instance
, NULL
);
70 if (Instance
->UdpIo
!= NULL
) {
71 UdpIoFreeIo (Instance
->UdpIo
);
78 Create the DNS instance and initialize it.
80 @param[in] Service The pointer to the DNS service.
81 @param[out] Instance The pointer to the DNS instance.
83 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
84 @retval EFI_SUCCESS The DNS instance is created.
89 IN DNS_SERVICE
*Service
,
90 OUT DNS_INSTANCE
**Instance
97 DnsIns
= AllocateZeroPool (sizeof (DNS_INSTANCE
));
99 return EFI_OUT_OF_RESOURCES
;
102 DnsIns
->Signature
= DNS_INSTANCE_SIGNATURE
;
103 InitializeListHead (&DnsIns
->Link
);
104 DnsIns
->State
= DNS_STATE_UNCONFIGED
;
105 DnsIns
->InDestroy
= FALSE
;
106 DnsIns
->Service
= Service
;
108 if (Service
->IpVersion
== IP_VERSION_4
) {
109 CopyMem (&DnsIns
->Dns4
, &mDns4Protocol
, sizeof (DnsIns
->Dns4
));
110 NetMapInit (&DnsIns
->Dns4TxTokens
);
112 CopyMem (&DnsIns
->Dns6
, &mDns6Protocol
, sizeof (DnsIns
->Dns6
));
113 NetMapInit (&DnsIns
->Dns6TxTokens
);
116 DnsIns
->UdpIo
= UdpIoCreateIo (
117 Service
->ControllerHandle
, /// NicHandle
118 Service
->ImageHandle
,
123 if (DnsIns
->UdpIo
== NULL
) {
125 return EFI_OUT_OF_RESOURCES
;
134 Callback function which provided by user to remove one node in NetDestroyLinkList process.
136 @param[in] Entry The entry to be removed.
137 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
139 @retval EFI_SUCCESS The entry has been removed successfully.
140 @retval Others Fail to remove the entry.
145 DnsDestroyChildEntryInHandleBuffer (
146 IN LIST_ENTRY
*Entry
,
150 DNS_INSTANCE
*Instance
;
151 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
152 UINTN NumberOfChildren
;
153 EFI_HANDLE
*ChildHandleBuffer
;
155 if (Entry
== NULL
|| Context
== NULL
) {
156 return EFI_INVALID_PARAMETER
;
159 Instance
= NET_LIST_USER_STRUCT_S (Entry
, DNS_INSTANCE
, Link
, DNS_INSTANCE_SIGNATURE
);
160 ServiceBinding
= ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
161 NumberOfChildren
= ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
162 ChildHandleBuffer
= ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
164 if (!NetIsInHandleBuffer (Instance
->ChildHandle
, NumberOfChildren
, ChildHandleBuffer
)) {
168 return ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->ChildHandle
);
172 Config a NULL UDP that is used to keep the connection between UDP and DNS.
174 Just leave the Udp child unconfigured. When UDP is unloaded,
175 DNS will be informed with DriverBinding Stop.
177 @param UdpIo The UDP_IO to configure
178 @param Context The opaque parameter to the callback
180 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
194 Release all the resource used the DNS service binding instance.
196 @param DnsSb The Dns service binding instance.
201 IN DNS_SERVICE
*DnsSb
204 UdpIoFreeIo (DnsSb
->ConnectUdp
);
206 if (DnsSb
->TimerToGetMap
!= NULL
){
207 gBS
->CloseEvent (DnsSb
->TimerToGetMap
);
210 if (DnsSb
->Timer
!= NULL
){
211 gBS
->CloseEvent (DnsSb
->Timer
);
218 Create then initialize a Dns service binding instance.
220 @param Controller The controller to install the DNS service
222 @param Image The driver binding image of the DNS driver
223 @param IpVersion IpVersion for this service
224 @param Service The variable to receive the created service
227 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
228 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
230 @retval EFI_SUCCESS The service instance is created for the
236 IN EFI_HANDLE Controller
,
239 OUT DNS_SERVICE
**Service
245 Status
= EFI_SUCCESS
;
250 DnsSb
= AllocateZeroPool (sizeof (DNS_SERVICE
));
252 return EFI_OUT_OF_RESOURCES
;
255 DnsSb
->Signature
= DNS_SERVICE_SIGNATURE
;
257 if (IpVersion
== IP_VERSION_4
) {
258 DnsSb
->ServiceBinding
= mDns4ServiceBinding
;
260 DnsSb
->ServiceBinding
= mDns6ServiceBinding
;
263 DnsSb
->Dns4ChildrenNum
= 0;
264 InitializeListHead (&DnsSb
->Dns4ChildrenList
);
266 DnsSb
->Dns6ChildrenNum
= 0;
267 InitializeListHead (&DnsSb
->Dns6ChildrenList
);
269 DnsSb
->ControllerHandle
= Controller
;
270 DnsSb
->ImageHandle
= Image
;
272 DnsSb
->TimerToGetMap
= NULL
;
276 DnsSb
->IpVersion
= IpVersion
;
279 // Create the timer used to time out the procedure which is used to
280 // get the default IP address.
282 Status
= gBS
->CreateEvent (
287 &DnsSb
->TimerToGetMap
289 if (EFI_ERROR (Status
)) {
295 // Create the timer to retransmit packets.
297 Status
= gBS
->CreateEvent (
298 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
300 DnsOnTimerRetransmit
,
304 if (EFI_ERROR (Status
)) {
305 if (DnsSb
->TimerToGetMap
!= NULL
) {
306 gBS
->CloseEvent (DnsSb
->TimerToGetMap
);
312 DnsSb
->ConnectUdp
= NULL
;
313 DnsSb
->ConnectUdp
= UdpIoCreateIo (
320 if (DnsSb
->ConnectUdp
== NULL
) {
321 if (DnsSb
->TimerToGetMap
!= NULL
) {
322 gBS
->CloseEvent (DnsSb
->TimerToGetMap
);
324 gBS
->CloseEvent (DnsSb
->Timer
);
326 return EFI_DEVICE_ERROR
;
336 @param ImageHandle Handle that identifies the image to be unloaded.
338 @retval EFI_SUCCESS The image has been unloaded.
339 @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
345 IN EFI_HANDLE ImageHandle
351 DNS4_CACHE
*ItemCache4
;
352 DNS4_SERVER_IP
*ItemServerIp4
;
353 DNS6_CACHE
*ItemCache6
;
354 DNS6_SERVER_IP
*ItemServerIp6
;
357 ItemServerIp4
= NULL
;
359 ItemServerIp6
= NULL
;
362 // Disconnect the driver specified by ImageHandle
364 Status
= NetLibDefaultUnload(ImageHandle
);
365 if (EFI_ERROR (Status
)) {
372 if (mDriverData
!= NULL
) {
373 if (mDriverData
->Timer
!= NULL
) {
374 gBS
->CloseEvent (mDriverData
->Timer
);
377 while (!IsListEmpty (&mDriverData
->Dns4CacheList
)) {
378 Entry
= NetListRemoveHead (&mDriverData
->Dns4CacheList
);
379 ASSERT (Entry
!= NULL
);
380 ItemCache4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
381 FreePool (ItemCache4
->DnsCache
.HostName
);
382 FreePool (ItemCache4
->DnsCache
.IpAddress
);
383 FreePool (ItemCache4
);
386 while (!IsListEmpty (&mDriverData
->Dns4ServerList
)) {
387 Entry
= NetListRemoveHead (&mDriverData
->Dns4ServerList
);
388 ASSERT (Entry
!= NULL
);
389 ItemServerIp4
= NET_LIST_USER_STRUCT (Entry
, DNS4_SERVER_IP
, AllServerLink
);
390 FreePool (ItemServerIp4
);
393 while (!IsListEmpty (&mDriverData
->Dns6CacheList
)) {
394 Entry
= NetListRemoveHead (&mDriverData
->Dns6CacheList
);
395 ASSERT (Entry
!= NULL
);
396 ItemCache6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
397 FreePool (ItemCache6
->DnsCache
.HostName
);
398 FreePool (ItemCache6
->DnsCache
.IpAddress
);
399 FreePool (ItemCache6
);
402 while (!IsListEmpty (&mDriverData
->Dns6ServerList
)) {
403 Entry
= NetListRemoveHead (&mDriverData
->Dns6ServerList
);
404 ASSERT (Entry
!= NULL
);
405 ItemServerIp6
= NET_LIST_USER_STRUCT (Entry
, DNS6_SERVER_IP
, AllServerLink
);
406 FreePool (ItemServerIp6
);
409 FreePool (mDriverData
);
416 This is the declaration of an EFI image entry point. This entry point is
417 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
418 both device drivers and bus drivers.
420 @param ImageHandle The firmware allocated handle for the UEFI image.
421 @param SystemTable A pointer to the EFI System Table.
423 @retval EFI_SUCCESS The operation completed successfully.
424 @retval Others An unexpected error occurred.
428 DnsDriverEntryPoint (
429 IN EFI_HANDLE ImageHandle
,
430 IN EFI_SYSTEM_TABLE
*SystemTable
435 Status
= EFI_SUCCESS
;
438 // Install the Dns4 Driver Binding Protocol.
440 Status
= EfiLibInstallDriverBindingComponentName2 (
448 if (EFI_ERROR (Status
)) {
453 // Install the Dns6 Driver Binding Protocol.
455 Status
= EfiLibInstallDriverBindingComponentName2 (
463 if (EFI_ERROR (Status
)) {
468 // Create the driver data structures.
470 mDriverData
= AllocateZeroPool (sizeof (DNS_DRIVER_DATA
));
471 if (mDriverData
== NULL
) {
472 Status
= EFI_OUT_OF_RESOURCES
;
477 // Create the timer event to update DNS cache list.
479 Status
= gBS
->CreateEvent (
480 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
486 if (EFI_ERROR (Status
)) {
490 Status
= gBS
->SetTimer (mDriverData
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
491 if (EFI_ERROR (Status
)) {
495 InitializeListHead (&mDriverData
->Dns4CacheList
);
496 InitializeListHead (&mDriverData
->Dns4ServerList
);
497 InitializeListHead (&mDriverData
->Dns6CacheList
);
498 InitializeListHead (&mDriverData
->Dns6ServerList
);
503 gBS
->CloseEvent (mDriverData
->Timer
);
506 FreePool (mDriverData
);
509 EfiLibUninstallDriverBindingComponentName2 (
516 EfiLibUninstallDriverBindingComponentName2 (
526 Tests to see if this driver supports a given controller. If a child device is provided,
527 it further tests to see if this driver supports creating a handle for the specified child device.
529 This function checks to see if the driver specified by This supports the device specified by
530 ControllerHandle. Drivers will typically use the device path attached to
531 ControllerHandle and/or the services from the bus I/O abstraction attached to
532 ControllerHandle to determine if the driver supports ControllerHandle. This function
533 may be called many times during platform initialization. In order to reduce boot times, the tests
534 performed by this function must be very small, and take as little time as possible to execute. This
535 function must not change the state of any hardware devices, and this function must be aware that the
536 device specified by ControllerHandle may already be managed by the same driver or a
537 different driver. This function must match its calls to AllocatePages() with FreePages(),
538 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
539 Because ControllerHandle may have been previously started by the same driver, if a protocol is
540 already in the opened state, then it must not be closed with CloseProtocol(). This is required
541 to guarantee the state of ControllerHandle is not modified by this function.
543 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
544 @param[in] ControllerHandle The handle of the controller to test. This handle
545 must support a protocol interface that supplies
546 an I/O abstraction to the driver.
547 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
548 parameter is ignored by device drivers, and is optional for bus
549 drivers. For bus drivers, if this parameter is not NULL, then
550 the bus driver must determine if the bus controller specified
551 by ControllerHandle and the child controller specified
552 by RemainingDevicePath are both supported by this
555 @retval EFI_SUCCESS The device specified by ControllerHandle and
556 RemainingDevicePath is supported by the driver specified by This.
557 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
558 RemainingDevicePath is already being managed by the driver
560 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
561 RemainingDevicePath is already being managed by a different
562 driver or an application that requires exclusive access.
563 Currently not implemented.
564 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
565 RemainingDevicePath is not supported by the driver specified by This.
569 Dns4DriverBindingSupported (
570 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
571 IN EFI_HANDLE ControllerHandle
,
572 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
578 // Test for the Dns4ServiceBinding Protocol.
580 Status
= gBS
->OpenProtocol (
582 &gEfiDns4ServiceBindingProtocolGuid
,
584 This
->DriverBindingHandle
,
586 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
588 if (!EFI_ERROR (Status
)) {
589 return EFI_ALREADY_STARTED
;
593 // Test for the Udp4ServiceBinding Protocol.
595 Status
= gBS
->OpenProtocol (
597 &gEfiUdp4ServiceBindingProtocolGuid
,
599 This
->DriverBindingHandle
,
601 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
608 Starts a device controller or a bus controller.
610 The Start() function is designed to be invoked from the EFI boot service ConnectController().
611 As a result, much of the error checking on the parameters to Start() has been moved into this
612 common boot service. It is legal to call Start() from other locations,
613 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
614 1. ControllerHandle must be a valid EFI_HANDLE.
615 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
616 EFI_DEVICE_PATH_PROTOCOL.
617 3. Prior to calling Start(), the Supported() function for the driver specified by This must
618 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
620 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
621 @param[in] ControllerHandle The handle of the controller to start. This handle
622 must support a protocol interface that supplies
623 an I/O abstraction to the driver.
624 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
625 parameter is ignored by device drivers, and is optional for bus
626 drivers. For a bus driver, if this parameter is NULL, then handles
627 for all the children of Controller are created by this driver.
628 If this parameter is not NULL and the first Device Path Node is
629 not the End of Device Path Node, then only the handle for the
630 child device specified by the first Device Path Node of
631 RemainingDevicePath is created by this driver.
632 If the first Device Path Node of RemainingDevicePath is
633 the End of Device Path Node, no child handle is created by this
636 @retval EFI_SUCCESS The device was started.
637 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
638 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
639 @retval Others The driver failded to start the device.
644 Dns4DriverBindingStart (
645 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
646 IN EFI_HANDLE ControllerHandle
,
647 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
653 Status
= DnsCreateService (ControllerHandle
, This
->DriverBindingHandle
, IP_VERSION_4
, &DnsSb
);
654 if (EFI_ERROR (Status
)) {
658 ASSERT (DnsSb
!= NULL
);
660 Status
= gBS
->SetTimer (DnsSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
661 if (EFI_ERROR (Status
)) {
666 // Install the Dns4ServiceBinding Protocol onto ControllerHandle.
668 Status
= gBS
->InstallMultipleProtocolInterfaces (
670 &gEfiDns4ServiceBindingProtocolGuid
,
671 &DnsSb
->ServiceBinding
,
674 if (EFI_ERROR (Status
)) {
681 DnsDestroyService (DnsSb
);
687 Stops a device controller or a bus controller.
689 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
690 As a result, much of the error checking on the parameters to Stop() has been moved
691 into this common boot service. It is legal to call Stop() from other locations,
692 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
693 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
694 same driver's Start() function.
695 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
696 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
697 Start() function, and the Start() function must have called OpenProtocol() on
698 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
700 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
701 @param[in] ControllerHandle A handle to the device being stopped. The handle must
702 support a bus specific I/O protocol for the driver
703 to use to stop the device.
704 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
705 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
706 if NumberOfChildren is 0.
708 @retval EFI_SUCCESS The device was stopped.
709 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
714 Dns4DriverBindingStop (
715 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
716 IN EFI_HANDLE ControllerHandle
,
717 IN UINTN NumberOfChildren
,
718 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
721 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
723 EFI_HANDLE NicHandle
;
726 DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
729 // DNS driver opens UDP child, So, Controller is a UDP
730 // child handle. Locate the Nic handle first. Then get the
731 // DNS private data back.
733 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiUdp4ProtocolGuid
);
735 if (NicHandle
== NULL
) {
739 Status
= gBS
->OpenProtocol (
741 &gEfiDns4ServiceBindingProtocolGuid
,
742 (VOID
**) &ServiceBinding
,
743 This
->DriverBindingHandle
,
745 EFI_OPEN_PROTOCOL_GET_PROTOCOL
747 if (EFI_ERROR (Status
)) {
748 return EFI_DEVICE_ERROR
;
751 DnsSb
= DNS_SERVICE_FROM_THIS (ServiceBinding
);
753 if (!IsListEmpty (&DnsSb
->Dns4ChildrenList
)) {
755 // Destroy the Dns child instance in ChildHandleBuffer.
757 List
= &DnsSb
->Dns4ChildrenList
;
758 Context
.ServiceBinding
= ServiceBinding
;
759 Context
.NumberOfChildren
= NumberOfChildren
;
760 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
761 Status
= NetDestroyLinkList (
763 DnsDestroyChildEntryInHandleBuffer
,
769 if (NumberOfChildren
== 0 && IsListEmpty (&DnsSb
->Dns4ChildrenList
)) {
770 gBS
->UninstallProtocolInterface (
772 &gEfiDns4ServiceBindingProtocolGuid
,
776 DnsDestroyService (DnsSb
);
778 if (gDnsControllerNameTable
!= NULL
) {
779 FreeUnicodeStringTable (gDnsControllerNameTable
);
780 gDnsControllerNameTable
= NULL
;
783 Status
= EFI_SUCCESS
;
790 Tests to see if this driver supports a given controller. If a child device is provided,
791 it further tests to see if this driver supports creating a handle for the specified child device.
793 This function checks to see if the driver specified by This supports the device specified by
794 ControllerHandle. Drivers will typically use the device path attached to
795 ControllerHandle and/or the services from the bus I/O abstraction attached to
796 ControllerHandle to determine if the driver supports ControllerHandle. This function
797 may be called many times during platform initialization. In order to reduce boot times, the tests
798 performed by this function must be very small, and take as little time as possible to execute. This
799 function must not change the state of any hardware devices, and this function must be aware that the
800 device specified by ControllerHandle may already be managed by the same driver or a
801 different driver. This function must match its calls to AllocatePages() with FreePages(),
802 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
803 Because ControllerHandle may have been previously started by the same driver, if a protocol is
804 already in the opened state, then it must not be closed with CloseProtocol(). This is required
805 to guarantee the state of ControllerHandle is not modified by this function.
807 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
808 @param[in] ControllerHandle The handle of the controller to test. This handle
809 must support a protocol interface that supplies
810 an I/O abstraction to the driver.
811 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
812 parameter is ignored by device drivers, and is optional for bus
813 drivers. For bus drivers, if this parameter is not NULL, then
814 the bus driver must determine if the bus controller specified
815 by ControllerHandle and the child controller specified
816 by RemainingDevicePath are both supported by this
819 @retval EFI_SUCCESS The device specified by ControllerHandle and
820 RemainingDevicePath is supported by the driver specified by This.
821 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
822 RemainingDevicePath is already being managed by the driver
824 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
825 RemainingDevicePath is already being managed by a different
826 driver or an application that requires exclusive access.
827 Currently not implemented.
828 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
829 RemainingDevicePath is not supported by the driver specified by This.
833 Dns6DriverBindingSupported (
834 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
835 IN EFI_HANDLE ControllerHandle
,
836 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
842 // Test for the Dns6ServiceBinding Protocol
844 Status
= gBS
->OpenProtocol (
846 &gEfiDns6ServiceBindingProtocolGuid
,
848 This
->DriverBindingHandle
,
850 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
852 if (!EFI_ERROR (Status
)) {
853 return EFI_ALREADY_STARTED
;
857 // Test for the Udp6ServiceBinding Protocol
859 Status
= gBS
->OpenProtocol (
861 &gEfiUdp6ServiceBindingProtocolGuid
,
863 This
->DriverBindingHandle
,
865 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
872 Starts a device controller or a bus controller.
874 The Start() function is designed to be invoked from the EFI boot service ConnectController().
875 As a result, much of the error checking on the parameters to Start() has been moved into this
876 common boot service. It is legal to call Start() from other locations,
877 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
878 1. ControllerHandle must be a valid EFI_HANDLE.
879 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
880 EFI_DEVICE_PATH_PROTOCOL.
881 3. Prior to calling Start(), the Supported() function for the driver specified by This must
882 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
884 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
885 @param[in] ControllerHandle The handle of the controller to start. This handle
886 must support a protocol interface that supplies
887 an I/O abstraction to the driver.
888 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
889 parameter is ignored by device drivers, and is optional for bus
890 drivers. For a bus driver, if this parameter is NULL, then handles
891 for all the children of Controller are created by this driver.
892 If this parameter is not NULL and the first Device Path Node is
893 not the End of Device Path Node, then only the handle for the
894 child device specified by the first Device Path Node of
895 RemainingDevicePath is created by this driver.
896 If the first Device Path Node of RemainingDevicePath is
897 the End of Device Path Node, no child handle is created by this
900 @retval EFI_SUCCESS The device was started.
901 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
902 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
903 @retval Others The driver failded to start the device.
908 Dns6DriverBindingStart (
909 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
910 IN EFI_HANDLE ControllerHandle
,
911 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
917 Status
= DnsCreateService (ControllerHandle
, This
->DriverBindingHandle
, IP_VERSION_6
, &DnsSb
);
918 if (EFI_ERROR (Status
)) {
922 ASSERT (DnsSb
!= NULL
);
924 Status
= gBS
->SetTimer (DnsSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
925 if (EFI_ERROR (Status
)) {
930 // Install the Dns6ServiceBinding Protocol onto ControllerHandle
932 Status
= gBS
->InstallMultipleProtocolInterfaces (
934 &gEfiDns6ServiceBindingProtocolGuid
,
935 &DnsSb
->ServiceBinding
,
939 if (EFI_ERROR (Status
)) {
946 DnsDestroyService (DnsSb
);
952 Stops a device controller or a bus controller.
954 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
955 As a result, much of the error checking on the parameters to Stop() has been moved
956 into this common boot service. It is legal to call Stop() from other locations,
957 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
958 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
959 same driver's Start() function.
960 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
961 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
962 Start() function, and the Start() function must have called OpenProtocol() on
963 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
965 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
966 @param[in] ControllerHandle A handle to the device being stopped. The handle must
967 support a bus specific I/O protocol for the driver
968 to use to stop the device.
969 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
970 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
971 if NumberOfChildren is 0.
973 @retval EFI_SUCCESS The device was stopped.
974 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
979 Dns6DriverBindingStop (
980 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
981 IN EFI_HANDLE ControllerHandle
,
982 IN UINTN NumberOfChildren
,
983 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
986 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
988 EFI_HANDLE NicHandle
;
991 DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
994 // DNS driver opens UDP child, So, Controller is a UDP
995 // child handle. Locate the Nic handle first. Then get the
996 // DNS private data back.
998 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiUdp6ProtocolGuid
);
1000 if (NicHandle
== NULL
) {
1004 Status
= gBS
->OpenProtocol (
1006 &gEfiDns6ServiceBindingProtocolGuid
,
1007 (VOID
**) &ServiceBinding
,
1008 This
->DriverBindingHandle
,
1010 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1012 if (EFI_ERROR (Status
)) {
1013 return EFI_DEVICE_ERROR
;
1016 DnsSb
= DNS_SERVICE_FROM_THIS (ServiceBinding
);
1018 if (!IsListEmpty (&DnsSb
->Dns6ChildrenList
)) {
1020 // Destroy the Dns child instance in ChildHandleBuffer.
1022 List
= &DnsSb
->Dns6ChildrenList
;
1023 Context
.ServiceBinding
= ServiceBinding
;
1024 Context
.NumberOfChildren
= NumberOfChildren
;
1025 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
1026 Status
= NetDestroyLinkList (
1028 DnsDestroyChildEntryInHandleBuffer
,
1034 if (NumberOfChildren
== 0 && IsListEmpty (&DnsSb
->Dns6ChildrenList
)) {
1035 gBS
->UninstallProtocolInterface (
1037 &gEfiDns6ServiceBindingProtocolGuid
,
1041 DnsDestroyService (DnsSb
);
1043 if (gDnsControllerNameTable
!= NULL
) {
1044 FreeUnicodeStringTable (gDnsControllerNameTable
);
1045 gDnsControllerNameTable
= NULL
;
1048 Status
= EFI_SUCCESS
;
1055 Creates a child handle and installs a protocol.
1057 The CreateChild() function installs a protocol on ChildHandle.
1058 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
1059 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
1061 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
1062 @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
1063 then a new handle is created. If it is a pointer to an existing UEFI handle,
1064 then the protocol is added to the existing UEFI handle.
1066 @retval EFI_SUCCES The protocol was added to ChildHandle.
1067 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
1068 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
1070 @retval other The child handle was not created
1075 Dns4ServiceBindingCreateChild (
1076 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
1077 IN EFI_HANDLE
*ChildHandle
1081 DNS_INSTANCE
*Instance
;
1086 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
1087 return EFI_INVALID_PARAMETER
;
1090 DnsSb
= DNS_SERVICE_FROM_THIS (This
);
1092 Status
= DnsCreateInstance (DnsSb
, &Instance
);
1093 if (EFI_ERROR (Status
)) {
1096 ASSERT (Instance
!= NULL
);
1099 // Install the DNS protocol onto ChildHandle
1101 Status
= gBS
->InstallMultipleProtocolInterfaces (
1103 &gEfiDns4ProtocolGuid
,
1107 if (EFI_ERROR (Status
)) {
1111 Instance
->ChildHandle
= *ChildHandle
;
1114 // Open the Udp4 protocol BY_CHILD.
1116 Status
= gBS
->OpenProtocol (
1117 DnsSb
->ConnectUdp
->UdpHandle
,
1118 &gEfiUdp4ProtocolGuid
,
1120 gDns4DriverBinding
.DriverBindingHandle
,
1121 Instance
->ChildHandle
,
1122 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1124 if (EFI_ERROR (Status
)) {
1125 gBS
->UninstallMultipleProtocolInterfaces (
1126 Instance
->ChildHandle
,
1127 &gEfiDns4ProtocolGuid
,
1136 // Open the Udp4 protocol by child.
1138 Status
= gBS
->OpenProtocol (
1139 Instance
->UdpIo
->UdpHandle
,
1140 &gEfiUdp4ProtocolGuid
,
1142 gDns4DriverBinding
.DriverBindingHandle
,
1143 Instance
->ChildHandle
,
1144 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1146 if (EFI_ERROR (Status
)) {
1148 // Close the Udp4 protocol.
1150 gBS
->CloseProtocol (
1151 DnsSb
->ConnectUdp
->UdpHandle
,
1152 &gEfiUdp4ProtocolGuid
,
1153 gDns4DriverBinding
.DriverBindingHandle
,
1157 gBS
->UninstallMultipleProtocolInterfaces (
1158 Instance
->ChildHandle
,
1159 &gEfiDns4ProtocolGuid
,
1168 // Add it to the parent's child list.
1170 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1172 InsertTailList (&DnsSb
->Dns4ChildrenList
, &Instance
->Link
);
1173 DnsSb
->Dns4ChildrenNum
++;
1175 gBS
->RestoreTPL (OldTpl
);
1181 DnsDestroyInstance (Instance
);
1186 Destroys a child handle with a protocol installed on it.
1188 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
1189 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
1190 last protocol on ChildHandle, then ChildHandle is destroyed.
1192 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
1193 @param[in] ChildHandle Handle of the child to destroy
1195 @retval EFI_SUCCES The protocol was removed from ChildHandle.
1196 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
1197 @retval EFI_INVALID_PARAMETER Child handle is NULL.
1198 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
1199 because its services are being used.
1200 @retval other The child handle was not destroyed
1205 Dns4ServiceBindingDestroyChild (
1206 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
1207 IN EFI_HANDLE ChildHandle
1211 DNS_INSTANCE
*Instance
;
1213 EFI_DNS4_PROTOCOL
*Dns4
;
1217 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
1218 return EFI_INVALID_PARAMETER
;
1222 // Retrieve the private context data structures
1224 Status
= gBS
->OpenProtocol (
1226 &gEfiDns4ProtocolGuid
,
1228 gDns4DriverBinding
.DriverBindingHandle
,
1230 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1233 if (EFI_ERROR (Status
)) {
1234 return EFI_UNSUPPORTED
;
1237 Instance
= DNS_INSTANCE_FROM_THIS_PROTOCOL4 (Dns4
);
1238 DnsSb
= DNS_SERVICE_FROM_THIS (This
);
1240 if (Instance
->Service
!= DnsSb
) {
1241 return EFI_INVALID_PARAMETER
;
1244 if (Instance
->InDestroy
) {
1248 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1250 Instance
->InDestroy
= TRUE
;
1253 // Close the Udp4 protocol.
1255 gBS
->CloseProtocol (
1256 DnsSb
->ConnectUdp
->UdpHandle
,
1257 &gEfiUdp4ProtocolGuid
,
1258 gDns4DriverBinding
.DriverBindingHandle
,
1262 gBS
->CloseProtocol (
1263 Instance
->UdpIo
->UdpHandle
,
1264 &gEfiUdp4ProtocolGuid
,
1265 gDns4DriverBinding
.DriverBindingHandle
,
1269 gBS
->RestoreTPL (OldTpl
);
1272 // Uninstall the DNS protocol first to enable a top down destruction.
1274 Status
= gBS
->UninstallProtocolInterface (
1276 &gEfiDns4ProtocolGuid
,
1280 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1282 if (EFI_ERROR (Status
)) {
1283 Instance
->InDestroy
= FALSE
;
1284 gBS
->RestoreTPL (OldTpl
);
1288 RemoveEntryList (&Instance
->Link
);
1289 DnsSb
->Dns4ChildrenNum
--;
1291 gBS
->RestoreTPL (OldTpl
);
1293 DnsDestroyInstance (Instance
);
1298 Creates a child handle and installs a protocol.
1300 The CreateChild() function installs a protocol on ChildHandle.
1301 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
1302 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
1304 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
1305 @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
1306 then a new handle is created. If it is a pointer to an existing UEFI handle,
1307 then the protocol is added to the existing UEFI handle.
1309 @retval EFI_SUCCES The protocol was added to ChildHandle.
1310 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
1311 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
1313 @retval other The child handle was not created
1318 Dns6ServiceBindingCreateChild (
1319 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
1320 IN EFI_HANDLE
*ChildHandle
1324 DNS_INSTANCE
*Instance
;
1329 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
1330 return EFI_INVALID_PARAMETER
;
1333 DnsSb
= DNS_SERVICE_FROM_THIS (This
);
1335 Status
= DnsCreateInstance (DnsSb
, &Instance
);
1336 if (EFI_ERROR (Status
)) {
1339 ASSERT (Instance
!= NULL
);
1342 // Install the DNS protocol onto ChildHandle
1344 Status
= gBS
->InstallMultipleProtocolInterfaces (
1346 &gEfiDns6ProtocolGuid
,
1350 if (EFI_ERROR (Status
)) {
1354 Instance
->ChildHandle
= *ChildHandle
;
1357 // Open the Udp6 protocol BY_CHILD.
1359 Status
= gBS
->OpenProtocol (
1360 DnsSb
->ConnectUdp
->UdpHandle
,
1361 &gEfiUdp6ProtocolGuid
,
1363 gDns6DriverBinding
.DriverBindingHandle
,
1364 Instance
->ChildHandle
,
1365 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1367 if (EFI_ERROR (Status
)) {
1368 gBS
->UninstallMultipleProtocolInterfaces (
1369 Instance
->ChildHandle
,
1370 &gEfiDns6ProtocolGuid
,
1379 // Open the Udp6 protocol by child.
1381 Status
= gBS
->OpenProtocol (
1382 Instance
->UdpIo
->UdpHandle
,
1383 &gEfiUdp6ProtocolGuid
,
1385 gDns6DriverBinding
.DriverBindingHandle
,
1386 Instance
->ChildHandle
,
1387 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1389 if (EFI_ERROR (Status
)) {
1391 // Close the Udp6 protocol.
1393 gBS
->CloseProtocol (
1394 DnsSb
->ConnectUdp
->UdpHandle
,
1395 &gEfiUdp6ProtocolGuid
,
1396 gDns6DriverBinding
.DriverBindingHandle
,
1400 gBS
->UninstallMultipleProtocolInterfaces (
1401 Instance
->ChildHandle
,
1402 &gEfiDns6ProtocolGuid
,
1411 // Add it to the parent's child list.
1413 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1415 InsertTailList (&DnsSb
->Dns6ChildrenList
, &Instance
->Link
);
1416 DnsSb
->Dns6ChildrenNum
++;
1418 gBS
->RestoreTPL (OldTpl
);
1424 DnsDestroyInstance (Instance
);
1429 Destroys a child handle with a protocol installed on it.
1431 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
1432 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
1433 last protocol on ChildHandle, then ChildHandle is destroyed.
1435 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
1436 @param[in] ChildHandle Handle of the child to destroy
1438 @retval EFI_SUCCES The protocol was removed from ChildHandle.
1439 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
1440 @retval EFI_INVALID_PARAMETER Child handle is NULL.
1441 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
1442 because its services are being used.
1443 @retval other The child handle was not destroyed
1448 Dns6ServiceBindingDestroyChild (
1449 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
1450 IN EFI_HANDLE ChildHandle
1454 DNS_INSTANCE
*Instance
;
1456 EFI_DNS6_PROTOCOL
*Dns6
;
1460 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
1461 return EFI_INVALID_PARAMETER
;
1465 // Retrieve the private context data structures
1467 Status
= gBS
->OpenProtocol (
1469 &gEfiDns6ProtocolGuid
,
1471 gDns6DriverBinding
.DriverBindingHandle
,
1473 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1476 if (EFI_ERROR (Status
)) {
1477 return EFI_UNSUPPORTED
;
1480 Instance
= DNS_INSTANCE_FROM_THIS_PROTOCOL6 (Dns6
);
1481 DnsSb
= DNS_SERVICE_FROM_THIS (This
);
1483 if (Instance
->Service
!= DnsSb
) {
1484 return EFI_INVALID_PARAMETER
;
1487 if (Instance
->InDestroy
) {
1491 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1493 Instance
->InDestroy
= TRUE
;
1496 // Close the Udp6 protocol.
1498 gBS
->CloseProtocol (
1499 DnsSb
->ConnectUdp
->UdpHandle
,
1500 &gEfiUdp6ProtocolGuid
,
1501 gDns6DriverBinding
.DriverBindingHandle
,
1505 gBS
->CloseProtocol (
1506 Instance
->UdpIo
->UdpHandle
,
1507 &gEfiUdp6ProtocolGuid
,
1508 gDns6DriverBinding
.DriverBindingHandle
,
1512 gBS
->RestoreTPL (OldTpl
);
1515 // Uninstall the DNS protocol first to enable a top down destruction.
1517 Status
= gBS
->UninstallProtocolInterface (
1519 &gEfiDns6ProtocolGuid
,
1523 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1525 if (EFI_ERROR (Status
)) {
1526 Instance
->InDestroy
= FALSE
;
1527 gBS
->RestoreTPL (OldTpl
);
1531 RemoveEntryList (&Instance
->Link
);
1532 DnsSb
->Dns6ChildrenNum
--;
1534 gBS
->RestoreTPL (OldTpl
);
1536 DnsDestroyInstance (Instance
);