1 /** @file
2 The driver binding and service binding protocol for DnsDxe driver.
3 
4 Copyright (c) 2015, 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
9 
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.
12 
13 **/
14 
15 #include "DnsImpl.h"
16 
17 EFI_DRIVER_BINDING_PROTOCOL gDns4DriverBinding = {
18   Dns4DriverBindingSupported,
19   Dns4DriverBindingStart,
20   Dns4DriverBindingStop,
21   DNS_VERSION,
22   NULL,
23   NULL
24 };
25 
26 EFI_DRIVER_BINDING_PROTOCOL gDns6DriverBinding = {
27   Dns6DriverBindingSupported,
28   Dns6DriverBindingStart,
29   Dns6DriverBindingStop,
30   DNS_VERSION,
31   NULL,
32   NULL
33 };
34 
35 EFI_SERVICE_BINDING_PROTOCOL mDns4ServiceBinding = {
36   Dns4ServiceBindingCreateChild,
37   Dns4ServiceBindingDestroyChild
38 };
39 
40 EFI_SERVICE_BINDING_PROTOCOL mDns6ServiceBinding = {
41   Dns6ServiceBindingCreateChild,
42   Dns6ServiceBindingDestroyChild
43 };
44 
45 DNS_DRIVER_DATA          *mDriverData = NULL;
46 
47 /**
48   Destroy the DNS instance and recycle the resources.
49 
50   @param[in]  Instance        The pointer to the DNS instance.
51 
52 **/
53 VOID
DnsDestroyInstance(IN DNS_INSTANCE * Instance)54 DnsDestroyInstance (
55   IN DNS_INSTANCE         *Instance
56   )
57 {
58   ZeroMem (&Instance->Dns4CfgData, sizeof (EFI_DNS4_CONFIG_DATA));
59 
60   ZeroMem (&Instance->Dns6CfgData, sizeof (EFI_DNS6_CONFIG_DATA));
61 
62   if (!NetMapIsEmpty (&Instance->Dns4TxTokens)) {
63     Dns4InstanceCancelToken (Instance, NULL);
64   }
65 
66   if (!NetMapIsEmpty (&Instance->Dns6TxTokens)) {
67     Dns6InstanceCancelToken (Instance, NULL);
68   }
69 
70   if (Instance->UdpIo!= NULL) {
71     UdpIoFreeIo (Instance->UdpIo);
72   }
73 
74   FreePool (Instance);
75 }
76 
77 /**
78   Create the DNS instance and initialize it.
79 
80   @param[in]  Service              The pointer to the DNS service.
81   @param[out] Instance             The pointer to the DNS instance.
82 
83   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
84   @retval EFI_SUCCESS            The DNS instance is created.
85 
86 **/
87 EFI_STATUS
DnsCreateInstance(IN DNS_SERVICE * Service,OUT DNS_INSTANCE ** Instance)88 DnsCreateInstance (
89   IN  DNS_SERVICE         *Service,
90   OUT DNS_INSTANCE        **Instance
91   )
92 {
93   DNS_INSTANCE            *DnsIns;
94 
95   *Instance = NULL;
96 
97   DnsIns = AllocateZeroPool (sizeof (DNS_INSTANCE));
98   if (DnsIns == NULL) {
99     return EFI_OUT_OF_RESOURCES;
100   }
101 
102   DnsIns->Signature = DNS_INSTANCE_SIGNATURE;
103   InitializeListHead (&DnsIns->Link);
104   DnsIns->State     = DNS_STATE_UNCONFIGED;
105   DnsIns->InDestroy = FALSE;
106   DnsIns->Service   = Service;
107 
108   if (Service->IpVersion == IP_VERSION_4) {
109     CopyMem (&DnsIns->Dns4, &mDns4Protocol, sizeof (DnsIns->Dns4));
110     NetMapInit (&DnsIns->Dns4TxTokens);
111   } else {
112     CopyMem (&DnsIns->Dns6, &mDns6Protocol, sizeof (DnsIns->Dns6));
113     NetMapInit (&DnsIns->Dns6TxTokens);
114   }
115 
116   DnsIns->UdpIo = UdpIoCreateIo (
117                     Service->ControllerHandle, /// NicHandle
118                     Service->ImageHandle,
119                     DnsConfigNullUdp,
120                     Service->IpVersion,
121                     DnsIns
122                     );
123   if (DnsIns->UdpIo == NULL) {
124     FreePool (DnsIns);
125     return EFI_OUT_OF_RESOURCES;
126   }
127 
128   *Instance = DnsIns;
129 
130   return EFI_SUCCESS;
131 }
132 
133 /**
134   Callback function which provided by user to remove one node in NetDestroyLinkList process.
135 
136   @param[in]    Entry           The entry to be removed.
137   @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
138 
139   @retval EFI_SUCCESS           The entry has been removed successfully.
140   @retval Others                Fail to remove the entry.
141 
142 **/
143 EFI_STATUS
144 EFIAPI
DnsDestroyChildEntryInHandleBuffer(IN LIST_ENTRY * Entry,IN VOID * Context)145 DnsDestroyChildEntryInHandleBuffer (
146   IN LIST_ENTRY         *Entry,
147   IN VOID               *Context
148   )
149 {
150   DNS_INSTANCE                  *Instance;
151   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
152   UINTN                         NumberOfChildren;
153   EFI_HANDLE                    *ChildHandleBuffer;
154 
155   if (Entry == NULL || Context == NULL) {
156     return EFI_INVALID_PARAMETER;
157   }
158 
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;
163 
164   if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) {
165     return EFI_SUCCESS;
166   }
167 
168   return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);
169 }
170 
171 /**
172   Config a NULL UDP that is used to keep the connection between UDP and DNS.
173 
174   Just leave the Udp child unconfigured. When UDP is unloaded,
175     DNS will be informed with DriverBinding Stop.
176 
177   @param  UdpIo                  The UDP_IO to configure
178   @param  Context                The opaque parameter to the callback
179 
180   @retval EFI_SUCCESS            It always return EFI_SUCCESS directly.
181 
182 **/
183 EFI_STATUS
184 EFIAPI
DnsConfigNullUdp(IN UDP_IO * UdpIo,IN VOID * Context)185 DnsConfigNullUdp (
186   IN UDP_IO                 *UdpIo,
187   IN VOID                   *Context
188   )
189 {
190   return EFI_SUCCESS;
191 }
192 
193 /**
194   Release all the resource used the DNS service binding instance.
195 
196   @param  DnsSb                The Dns service binding instance.
197 
198 **/
199 VOID
DnsDestroyService(IN DNS_SERVICE * DnsSb)200 DnsDestroyService (
201   IN DNS_SERVICE     *DnsSb
202   )
203 {
204   UdpIoFreeIo (DnsSb->ConnectUdp);
205 
206   if (DnsSb->TimerToGetMap != NULL){
207     gBS->CloseEvent (DnsSb->TimerToGetMap);
208   }
209 
210   if (DnsSb->Timer != NULL){
211     gBS->CloseEvent (DnsSb->Timer);
212   }
213 
214   FreePool (DnsSb);
215 }
216 
217 /**
218   Create then initialize a Dns service binding instance.
219 
220   @param  Controller             The controller to install the DNS service
221                                  binding on
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
225                                  binding instance.
226 
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
229                                  connection  with UDP.
230   @retval EFI_SUCCESS            The service instance is created for the
231                                  controller.
232 
233 **/
234 EFI_STATUS
DnsCreateService(IN EFI_HANDLE Controller,IN EFI_HANDLE Image,IN UINT8 IpVersion,OUT DNS_SERVICE ** Service)235 DnsCreateService (
236   IN     EFI_HANDLE            Controller,
237   IN     EFI_HANDLE            Image,
238   IN     UINT8                 IpVersion,
239      OUT DNS_SERVICE           **Service
240   )
241 {
242   EFI_STATUS             Status;
243   DNS_SERVICE            *DnsSb;
244 
245   Status    = EFI_SUCCESS;
246   DnsSb     = NULL;
247 
248   *Service  = NULL;
249 
250   DnsSb = AllocateZeroPool (sizeof (DNS_SERVICE));
251   if (DnsSb == NULL) {
252     return EFI_OUT_OF_RESOURCES;
253   }
254 
255   DnsSb->Signature = DNS_SERVICE_SIGNATURE;
256 
257   if (IpVersion == IP_VERSION_4) {
258     DnsSb->ServiceBinding = mDns4ServiceBinding;
259   } else {
260     DnsSb->ServiceBinding = mDns6ServiceBinding;
261   }
262 
263   DnsSb->Dns4ChildrenNum = 0;
264   InitializeListHead (&DnsSb->Dns4ChildrenList);
265 
266   DnsSb->Dns6ChildrenNum = 0;
267   InitializeListHead (&DnsSb->Dns6ChildrenList);
268 
269   DnsSb->ControllerHandle = Controller;
270   DnsSb->ImageHandle      = Image;
271 
272   DnsSb->TimerToGetMap    = NULL;
273 
274   DnsSb->Timer            = NULL;
275 
276   DnsSb->IpVersion        = IpVersion;
277 
278   //
279   // Create the timer used to time out the procedure which is used to
280   // get the default IP address.
281   //
282   if (DnsSb->IpVersion == IP_VERSION_4) {
283     Status = gBS->CreateEvent (
284                     EVT_TIMER,
285                     TPL_CALLBACK,
286                     NULL,
287                     NULL,
288                     &DnsSb->TimerToGetMap
289                     );
290     if (EFI_ERROR (Status)) {
291       FreePool (DnsSb);
292       return Status;
293     }
294   }
295 
296   //
297   // Create the timer to retransmit packets.
298   //
299   Status = gBS->CreateEvent (
300                   EVT_NOTIFY_SIGNAL | EVT_TIMER,
301                   TPL_CALLBACK,
302                   DnsOnTimerRetransmit,
303                   DnsSb,
304                   &DnsSb->Timer
305                   );
306   if (EFI_ERROR (Status)) {
307     if (DnsSb->TimerToGetMap != NULL) {
308       gBS->CloseEvent (DnsSb->TimerToGetMap);
309     }
310     FreePool (DnsSb);
311     return Status;
312   }
313 
314   DnsSb->ConnectUdp = NULL;
315   DnsSb->ConnectUdp = UdpIoCreateIo (
316                         Controller,
317                         Image,
318                         DnsConfigNullUdp,
319                         DnsSb->IpVersion,
320                         NULL
321                         );
322   if (DnsSb->ConnectUdp == NULL) {
323     if (DnsSb->TimerToGetMap != NULL) {
324       gBS->CloseEvent (DnsSb->TimerToGetMap);
325     }
326     gBS->CloseEvent (DnsSb->Timer);
327     FreePool (DnsSb);
328     return EFI_DEVICE_ERROR;
329   }
330 
331   *Service = DnsSb;
332   return Status;
333 }
334 
335 /**
336   Unloads an image.
337 
338   @param  ImageHandle           Handle that identifies the image to be unloaded.
339 
340   @retval EFI_SUCCESS           The image has been unloaded.
341   @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
342 
343 **/
344 EFI_STATUS
345 EFIAPI
DnsUnload(IN EFI_HANDLE ImageHandle)346 DnsUnload (
347   IN EFI_HANDLE  ImageHandle
348   )
349 {
350   EFI_STATUS  Status;
351 
352   LIST_ENTRY                      *Entry;
353   DNS4_CACHE                      *ItemCache4;
354   DNS4_SERVER_IP                  *ItemServerIp4;
355   DNS6_CACHE                      *ItemCache6;
356   DNS6_SERVER_IP                  *ItemServerIp6;
357 
358   ItemCache4    = NULL;
359   ItemServerIp4 = NULL;
360   ItemCache6    = NULL;
361   ItemServerIp6 = NULL;
362 
363   //
364   // Disconnect the driver specified by ImageHandle
365   //
366   Status = NetLibDefaultUnload(ImageHandle);
367   if (EFI_ERROR (Status)) {
368     return Status;
369   }
370 
371   //
372   // Free mDriverData.
373   //
374   if (mDriverData != NULL) {
375     if (mDriverData->Timer != NULL) {
376       gBS->CloseEvent (mDriverData->Timer);
377     }
378 
379     while (!IsListEmpty (&mDriverData->Dns4CacheList)) {
380       Entry = NetListRemoveHead (&mDriverData->Dns4CacheList);
381       ItemCache4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
382       if (ItemCache4->DnsCache.HostName != NULL) {
383         FreePool (ItemCache4->DnsCache.HostName);
384       }
385       if (ItemCache4->DnsCache.IpAddress != NULL) {
386         FreePool (ItemCache4->DnsCache.IpAddress);
387       }
388       FreePool (ItemCache4);
389     }
390 
391     while (!IsListEmpty (&mDriverData->Dns4ServerList)) {
392       Entry = NetListRemoveHead (&mDriverData->Dns4ServerList);
393       ItemServerIp4 = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);
394       FreePool (ItemServerIp4);
395     }
396 
397     while (!IsListEmpty (&mDriverData->Dns6CacheList)) {
398       Entry = NetListRemoveHead (&mDriverData->Dns6CacheList);
399       ItemCache6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
400       if (ItemCache6->DnsCache.HostName != NULL) {
401         FreePool (ItemCache6->DnsCache.HostName);
402       }
403       if (ItemCache6->DnsCache.IpAddress != NULL) {
404         FreePool (ItemCache6->DnsCache.IpAddress);
405       }
406       FreePool (ItemCache6);
407     }
408 
409     while (!IsListEmpty (&mDriverData->Dns6ServerList)) {
410       Entry = NetListRemoveHead (&mDriverData->Dns6ServerList);
411       ItemServerIp6 = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);
412       FreePool (ItemServerIp6);
413     }
414 
415     FreePool (mDriverData);
416   }
417 
418   return Status;
419 }
420 
421 /**
422   This is the declaration of an EFI image entry point. This entry point is
423   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
424   both device drivers and bus drivers.
425 
426   @param  ImageHandle           The firmware allocated handle for the UEFI image.
427   @param  SystemTable           A pointer to the EFI System Table.
428 
429   @retval EFI_SUCCESS           The operation completed successfully.
430   @retval Others                An unexpected error occurred.
431 **/
432 EFI_STATUS
433 EFIAPI
DnsDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)434 DnsDriverEntryPoint (
435   IN EFI_HANDLE        ImageHandle,
436   IN EFI_SYSTEM_TABLE  *SystemTable
437   )
438 {
439   EFI_STATUS  Status;
440 
441   Status = EFI_SUCCESS;
442 
443   //
444   // Install the Dns4 Driver Binding Protocol.
445   //
446   Status = EfiLibInstallDriverBindingComponentName2 (
447              ImageHandle,
448              SystemTable,
449              &gDns4DriverBinding,
450              ImageHandle,
451              &gDnsComponentName,
452              &gDnsComponentName2
453              );
454   if (EFI_ERROR (Status)) {
455     return Status;
456   }
457 
458   //
459   // Install the Dns6 Driver Binding Protocol.
460   //
461   Status = EfiLibInstallDriverBindingComponentName2 (
462              ImageHandle,
463              SystemTable,
464              &gDns6DriverBinding,
465              NULL,
466              &gDnsComponentName,
467              &gDnsComponentName2
468              );
469   if (EFI_ERROR (Status)) {
470     goto Error1;
471   }
472 
473   //
474   // Create the driver data structures.
475   //
476   mDriverData = AllocateZeroPool (sizeof (DNS_DRIVER_DATA));
477   if (mDriverData == NULL) {
478     Status = EFI_OUT_OF_RESOURCES;
479     goto Error2;
480   }
481 
482   //
483   // Create the timer event to update DNS cache list.
484   //
485   Status = gBS->CreateEvent (
486                   EVT_NOTIFY_SIGNAL | EVT_TIMER,
487                   TPL_CALLBACK,
488                   DnsOnTimerUpdate,
489                   NULL,
490                   &mDriverData->Timer
491                   );
492   if (EFI_ERROR (Status)) {
493     goto Error3;
494   }
495 
496   Status = gBS->SetTimer (mDriverData->Timer, TimerPeriodic, TICKS_PER_SECOND);
497   if (EFI_ERROR (Status)) {
498     goto Error4;
499   }
500 
501   InitializeListHead (&mDriverData->Dns4CacheList);
502   InitializeListHead (&mDriverData->Dns4ServerList);
503   InitializeListHead (&mDriverData->Dns6CacheList);
504   InitializeListHead (&mDriverData->Dns6ServerList);
505 
506   return Status;
507 
508   Error4:
509     gBS->CloseEvent (mDriverData->Timer);
510 
511   Error3:
512     FreePool (mDriverData);
513 
514   Error2:
515      gBS->UninstallMultipleProtocolInterfaces (
516            gDns6DriverBinding.DriverBindingHandle,
517            &gEfiDriverBindingProtocolGuid,
518            &gDns6DriverBinding,
519            &gEfiComponentName2ProtocolGuid,
520            &gDnsComponentName2,
521            &gEfiComponentNameProtocolGuid,
522            &gDnsComponentName,
523            NULL
524            );
525 
526   Error1:
527     gBS->UninstallMultipleProtocolInterfaces (
528            ImageHandle,
529            &gEfiDriverBindingProtocolGuid,
530            &gDns4DriverBinding,
531            &gEfiComponentName2ProtocolGuid,
532            &gDnsComponentName2,
533            &gEfiComponentNameProtocolGuid,
534            &gDnsComponentName,
535            NULL
536            );
537 
538   return Status;
539 }
540 
541 /**
542   Tests to see if this driver supports a given controller. If a child device is provided,
543   it further tests to see if this driver supports creating a handle for the specified child device.
544 
545   This function checks to see if the driver specified by This supports the device specified by
546   ControllerHandle. Drivers will typically use the device path attached to
547   ControllerHandle and/or the services from the bus I/O abstraction attached to
548   ControllerHandle to determine if the driver supports ControllerHandle. This function
549   may be called many times during platform initialization. In order to reduce boot times, the tests
550   performed by this function must be very small, and take as little time as possible to execute. This
551   function must not change the state of any hardware devices, and this function must be aware that the
552   device specified by ControllerHandle may already be managed by the same driver or a
553   different driver. This function must match its calls to AllocatePages() with FreePages(),
554   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
555   Because ControllerHandle may have been previously started by the same driver, if a protocol is
556   already in the opened state, then it must not be closed with CloseProtocol(). This is required
557   to guarantee the state of ControllerHandle is not modified by this function.
558 
559   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
560   @param[in]  ControllerHandle     The handle of the controller to test. This handle
561                                    must support a protocol interface that supplies
562                                    an I/O abstraction to the driver.
563   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
564                                    parameter is ignored by device drivers, and is optional for bus
565                                    drivers. For bus drivers, if this parameter is not NULL, then
566                                    the bus driver must determine if the bus controller specified
567                                    by ControllerHandle and the child controller specified
568                                    by RemainingDevicePath are both supported by this
569                                    bus driver.
570 
571   @retval EFI_SUCCESS              The device specified by ControllerHandle and
572                                    RemainingDevicePath is supported by the driver specified by This.
573   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
574                                    RemainingDevicePath is already being managed by the driver
575                                    specified by This.
576   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
577                                    RemainingDevicePath is already being managed by a different
578                                    driver or an application that requires exclusive access.
579                                    Currently not implemented.
580   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
581                                    RemainingDevicePath is not supported by the driver specified by This.
582 **/
583 EFI_STATUS
584 EFIAPI
Dns4DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)585 Dns4DriverBindingSupported (
586   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
587   IN EFI_HANDLE                   ControllerHandle,
588   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
589   )
590 {
591   EFI_STATUS  Status;
592 
593   //
594   // Test for the Dns4ServiceBinding Protocol.
595   //
596   Status = gBS->OpenProtocol (
597                   ControllerHandle,
598                   &gEfiDns4ServiceBindingProtocolGuid,
599                   NULL,
600                   This->DriverBindingHandle,
601                   ControllerHandle,
602                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
603                   );
604   if (!EFI_ERROR (Status)) {
605     return EFI_ALREADY_STARTED;
606   }
607 
608   //
609   // Test for the Udp4ServiceBinding Protocol.
610   //
611   Status = gBS->OpenProtocol (
612                   ControllerHandle,
613                   &gEfiUdp4ServiceBindingProtocolGuid,
614                   NULL,
615                   This->DriverBindingHandle,
616                   ControllerHandle,
617                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
618                   );
619 
620   return Status;
621 }
622 
623 /**
624   Starts a device controller or a bus controller.
625 
626   The Start() function is designed to be invoked from the EFI boot service ConnectController().
627   As a result, much of the error checking on the parameters to Start() has been moved into this
628   common boot service. It is legal to call Start() from other locations,
629   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
630   1. ControllerHandle must be a valid EFI_HANDLE.
631   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
632      EFI_DEVICE_PATH_PROTOCOL.
633   3. Prior to calling Start(), the Supported() function for the driver specified by This must
634      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
635 
636   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
637   @param[in]  ControllerHandle     The handle of the controller to start. This handle
638                                    must support a protocol interface that supplies
639                                    an I/O abstraction to the driver.
640   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
641                                    parameter is ignored by device drivers, and is optional for bus
642                                    drivers. For a bus driver, if this parameter is NULL, then handles
643                                    for all the children of Controller are created by this driver.
644                                    If this parameter is not NULL and the first Device Path Node is
645                                    not the End of Device Path Node, then only the handle for the
646                                    child device specified by the first Device Path Node of
647                                    RemainingDevicePath is created by this driver.
648                                    If the first Device Path Node of RemainingDevicePath is
649                                    the End of Device Path Node, no child handle is created by this
650                                    driver.
651 
652   @retval EFI_SUCCESS              The device was started.
653   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
654   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
655   @retval Others                   The driver failded to start the device.
656 
657 **/
658 EFI_STATUS
659 EFIAPI
Dns4DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)660 Dns4DriverBindingStart (
661   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
662   IN EFI_HANDLE                   ControllerHandle,
663   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
664   )
665 {
666   DNS_SERVICE            *DnsSb;
667   EFI_STATUS             Status;
668 
669   Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4, &DnsSb);
670   if (EFI_ERROR (Status)) {
671     return Status;
672   }
673 
674   ASSERT (DnsSb != NULL);
675 
676   Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
677   if (EFI_ERROR (Status)) {
678     goto ON_ERROR;
679   }
680 
681   //
682   // Install the Dns4ServiceBinding Protocol onto ControllerHandle.
683   //
684   Status = gBS->InstallMultipleProtocolInterfaces (
685                   &ControllerHandle,
686                   &gEfiDns4ServiceBindingProtocolGuid,
687                   &DnsSb->ServiceBinding,
688                   NULL
689                   );
690   if (EFI_ERROR (Status)) {
691     goto ON_ERROR;
692   }
693 
694   return EFI_SUCCESS;
695 
696 ON_ERROR:
697   DnsDestroyService (DnsSb);
698 
699   return Status;
700 }
701 
702 /**
703   Stops a device controller or a bus controller.
704 
705   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
706   As a result, much of the error checking on the parameters to Stop() has been moved
707   into this common boot service. It is legal to call Stop() from other locations,
708   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
709   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
710      same driver's Start() function.
711   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
712      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
713      Start() function, and the Start() function must have called OpenProtocol() on
714      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
715 
716   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
717   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
718                                 support a bus specific I/O protocol for the driver
719                                 to use to stop the device.
720   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
721   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
722                                 if NumberOfChildren is 0.
723 
724   @retval EFI_SUCCESS           The device was stopped.
725   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
726 
727 **/
728 EFI_STATUS
729 EFIAPI
Dns4DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)730 Dns4DriverBindingStop (
731   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
732   IN EFI_HANDLE                   ControllerHandle,
733   IN UINTN                        NumberOfChildren,
734   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
735   )
736 {
737   EFI_SERVICE_BINDING_PROTOCOL               *ServiceBinding;
738   DNS_SERVICE                                *DnsSb;
739   EFI_HANDLE                                 NicHandle;
740   EFI_STATUS                                 Status;
741   LIST_ENTRY                                 *List;
742   DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT    Context;
743 
744   //
745   // DNS driver opens UDP child, So, Controller is a UDP
746   // child handle. Locate the Nic handle first. Then get the
747   // DNS private data back.
748   //
749   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
750 
751   if (NicHandle == NULL) {
752     return EFI_SUCCESS;
753   }
754 
755   Status = gBS->OpenProtocol (
756                   NicHandle,
757                   &gEfiDns4ServiceBindingProtocolGuid,
758                   (VOID **) &ServiceBinding,
759                   This->DriverBindingHandle,
760                   NicHandle,
761                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
762                   );
763   if (EFI_ERROR (Status)) {
764     return EFI_DEVICE_ERROR;
765   }
766 
767   DnsSb = DNS_SERVICE_FROM_THIS (ServiceBinding);
768 
769   if (!IsListEmpty (&DnsSb->Dns4ChildrenList)) {
770     //
771     // Destroy the Dns child instance in ChildHandleBuffer.
772     //
773     List = &DnsSb->Dns4ChildrenList;
774     Context.ServiceBinding    = ServiceBinding;
775     Context.NumberOfChildren  = NumberOfChildren;
776     Context.ChildHandleBuffer = ChildHandleBuffer;
777     Status = NetDestroyLinkList (
778                List,
779                DnsDestroyChildEntryInHandleBuffer,
780                &Context,
781                NULL
782                );
783   }
784 
785   if (NumberOfChildren == 0 && IsListEmpty (&DnsSb->Dns4ChildrenList)) {
786     gBS->UninstallProtocolInterface (
787            NicHandle,
788            &gEfiDns4ServiceBindingProtocolGuid,
789            ServiceBinding
790            );
791 
792     DnsDestroyService (DnsSb);
793 
794     if (gDnsControllerNameTable != NULL) {
795       FreeUnicodeStringTable (gDnsControllerNameTable);
796       gDnsControllerNameTable = NULL;
797     }
798 
799     Status = EFI_SUCCESS;
800   }
801 
802   return Status;
803 }
804 
805 /**
806   Tests to see if this driver supports a given controller. If a child device is provided,
807   it further tests to see if this driver supports creating a handle for the specified child device.
808 
809   This function checks to see if the driver specified by This supports the device specified by
810   ControllerHandle. Drivers will typically use the device path attached to
811   ControllerHandle and/or the services from the bus I/O abstraction attached to
812   ControllerHandle to determine if the driver supports ControllerHandle. This function
813   may be called many times during platform initialization. In order to reduce boot times, the tests
814   performed by this function must be very small, and take as little time as possible to execute. This
815   function must not change the state of any hardware devices, and this function must be aware that the
816   device specified by ControllerHandle may already be managed by the same driver or a
817   different driver. This function must match its calls to AllocatePages() with FreePages(),
818   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
819   Because ControllerHandle may have been previously started by the same driver, if a protocol is
820   already in the opened state, then it must not be closed with CloseProtocol(). This is required
821   to guarantee the state of ControllerHandle is not modified by this function.
822 
823   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
824   @param[in]  ControllerHandle     The handle of the controller to test. This handle
825                                    must support a protocol interface that supplies
826                                    an I/O abstraction to the driver.
827   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
828                                    parameter is ignored by device drivers, and is optional for bus
829                                    drivers. For bus drivers, if this parameter is not NULL, then
830                                    the bus driver must determine if the bus controller specified
831                                    by ControllerHandle and the child controller specified
832                                    by RemainingDevicePath are both supported by this
833                                    bus driver.
834 
835   @retval EFI_SUCCESS              The device specified by ControllerHandle and
836                                    RemainingDevicePath is supported by the driver specified by This.
837   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
838                                    RemainingDevicePath is already being managed by the driver
839                                    specified by This.
840   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
841                                    RemainingDevicePath is already being managed by a different
842                                    driver or an application that requires exclusive access.
843                                    Currently not implemented.
844   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
845                                    RemainingDevicePath is not supported by the driver specified by This.
846 **/
847 EFI_STATUS
848 EFIAPI
Dns6DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)849 Dns6DriverBindingSupported (
850   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
851   IN EFI_HANDLE                   ControllerHandle,
852   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
853   )
854 {
855   EFI_STATUS  Status;
856 
857   //
858   // Test for the Dns6ServiceBinding Protocol
859   //
860   Status = gBS->OpenProtocol (
861                   ControllerHandle,
862                   &gEfiDns6ServiceBindingProtocolGuid,
863                   NULL,
864                   This->DriverBindingHandle,
865                   ControllerHandle,
866                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
867                   );
868   if (!EFI_ERROR (Status)) {
869     return EFI_ALREADY_STARTED;
870   }
871 
872   //
873   // Test for the Udp6ServiceBinding Protocol
874   //
875   Status = gBS->OpenProtocol (
876                   ControllerHandle,
877                   &gEfiUdp6ServiceBindingProtocolGuid,
878                   NULL,
879                   This->DriverBindingHandle,
880                   ControllerHandle,
881                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
882                   );
883 
884   return Status;
885 }
886 
887 /**
888   Starts a device controller or a bus controller.
889 
890   The Start() function is designed to be invoked from the EFI boot service ConnectController().
891   As a result, much of the error checking on the parameters to Start() has been moved into this
892   common boot service. It is legal to call Start() from other locations,
893   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
894   1. ControllerHandle must be a valid EFI_HANDLE.
895   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
896      EFI_DEVICE_PATH_PROTOCOL.
897   3. Prior to calling Start(), the Supported() function for the driver specified by This must
898      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
899 
900   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
901   @param[in]  ControllerHandle     The handle of the controller to start. This handle
902                                    must support a protocol interface that supplies
903                                    an I/O abstraction to the driver.
904   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
905                                    parameter is ignored by device drivers, and is optional for bus
906                                    drivers. For a bus driver, if this parameter is NULL, then handles
907                                    for all the children of Controller are created by this driver.
908                                    If this parameter is not NULL and the first Device Path Node is
909                                    not the End of Device Path Node, then only the handle for the
910                                    child device specified by the first Device Path Node of
911                                    RemainingDevicePath is created by this driver.
912                                    If the first Device Path Node of RemainingDevicePath is
913                                    the End of Device Path Node, no child handle is created by this
914                                    driver.
915 
916   @retval EFI_SUCCESS              The device was started.
917   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
918   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
919   @retval Others                   The driver failded to start the device.
920 
921 **/
922 EFI_STATUS
923 EFIAPI
Dns6DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)924 Dns6DriverBindingStart (
925   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
926   IN EFI_HANDLE                   ControllerHandle,
927   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
928   )
929 {
930   DNS_SERVICE            *DnsSb;
931   EFI_STATUS             Status;
932 
933   Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6, &DnsSb);
934   if (EFI_ERROR (Status)) {
935     return Status;
936   }
937 
938   ASSERT (DnsSb != NULL);
939 
940   Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
941   if (EFI_ERROR (Status)) {
942     goto ON_ERROR;
943   }
944 
945   //
946   // Install the Dns6ServiceBinding Protocol onto ControllerHandle
947   //
948   Status = gBS->InstallMultipleProtocolInterfaces (
949                   &ControllerHandle,
950                   &gEfiDns6ServiceBindingProtocolGuid,
951                   &DnsSb->ServiceBinding,
952                   NULL
953                   );
954 
955   if (EFI_ERROR (Status)) {
956     goto ON_ERROR;
957   }
958 
959   return EFI_SUCCESS;
960 
961 ON_ERROR:
962   DnsDestroyService (DnsSb);
963 
964   return Status;
965 }
966 
967 /**
968   Stops a device controller or a bus controller.
969 
970   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
971   As a result, much of the error checking on the parameters to Stop() has been moved
972   into this common boot service. It is legal to call Stop() from other locations,
973   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
974   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
975      same driver's Start() function.
976   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
977      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
978      Start() function, and the Start() function must have called OpenProtocol() on
979      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
980 
981   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
982   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
983                                 support a bus specific I/O protocol for the driver
984                                 to use to stop the device.
985   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
986   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
987                                 if NumberOfChildren is 0.
988 
989   @retval EFI_SUCCESS           The device was stopped.
990   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
991 
992 **/
993 EFI_STATUS
994 EFIAPI
Dns6DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)995 Dns6DriverBindingStop (
996   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
997   IN EFI_HANDLE                   ControllerHandle,
998   IN UINTN                        NumberOfChildren,
999   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
1000   )
1001 {
1002   EFI_SERVICE_BINDING_PROTOCOL               *ServiceBinding;
1003   DNS_SERVICE                                *DnsSb;
1004   EFI_HANDLE                                 NicHandle;
1005   EFI_STATUS                                 Status;
1006   LIST_ENTRY                                 *List;
1007   DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT    Context;
1008 
1009   //
1010   // DNS driver opens UDP child, So, Controller is a UDP
1011   // child handle. Locate the Nic handle first. Then get the
1012   // DNS private data back.
1013   //
1014   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);
1015 
1016   if (NicHandle == NULL) {
1017     return EFI_SUCCESS;
1018   }
1019 
1020   Status = gBS->OpenProtocol (
1021                   NicHandle,
1022                   &gEfiDns6ServiceBindingProtocolGuid,
1023                   (VOID **) &ServiceBinding,
1024                   This->DriverBindingHandle,
1025                   NicHandle,
1026                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1027                   );
1028   if (EFI_ERROR (Status)) {
1029     return EFI_DEVICE_ERROR;
1030   }
1031 
1032   DnsSb = DNS_SERVICE_FROM_THIS (ServiceBinding);
1033 
1034   if (!IsListEmpty (&DnsSb->Dns6ChildrenList)) {
1035     //
1036     // Destroy the Dns child instance in ChildHandleBuffer.
1037     //
1038     List = &DnsSb->Dns6ChildrenList;
1039     Context.ServiceBinding    = ServiceBinding;
1040     Context.NumberOfChildren  = NumberOfChildren;
1041     Context.ChildHandleBuffer = ChildHandleBuffer;
1042     Status = NetDestroyLinkList (
1043                List,
1044                DnsDestroyChildEntryInHandleBuffer,
1045                &Context,
1046                NULL
1047                );
1048   }
1049 
1050   if (NumberOfChildren == 0 && IsListEmpty (&DnsSb->Dns6ChildrenList)) {
1051     gBS->UninstallProtocolInterface (
1052            NicHandle,
1053            &gEfiDns6ServiceBindingProtocolGuid,
1054            ServiceBinding
1055            );
1056 
1057     DnsDestroyService (DnsSb);
1058 
1059     if (gDnsControllerNameTable != NULL) {
1060       FreeUnicodeStringTable (gDnsControllerNameTable);
1061       gDnsControllerNameTable = NULL;
1062     }
1063 
1064     Status = EFI_SUCCESS;
1065   }
1066 
1067   return Status;
1068 }
1069 
1070 /**
1071   Creates a child handle and installs a protocol.
1072 
1073   The CreateChild() function installs a protocol on ChildHandle.
1074   If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
1075   If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
1076 
1077   @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
1078   @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
1079                          then a new handle is created. If it is a pointer to an existing UEFI handle,
1080                          then the protocol is added to the existing UEFI handle.
1081 
1082   @retval EFI_SUCCES            The protocol was added to ChildHandle.
1083   @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
1084   @retval EFI_OUT_OF_RESOURCES  There are not enough resources availabe to create
1085                                 the child
1086   @retval other                 The child handle was not created
1087 
1088 **/
1089 EFI_STATUS
1090 EFIAPI
Dns4ServiceBindingCreateChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN EFI_HANDLE * ChildHandle)1091 Dns4ServiceBindingCreateChild (
1092   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
1093   IN EFI_HANDLE                    *ChildHandle
1094   )
1095 {
1096   DNS_SERVICE               *DnsSb;
1097   DNS_INSTANCE              *Instance;
1098   EFI_STATUS                Status;
1099   EFI_TPL                   OldTpl;
1100   VOID                      *Udp4;
1101 
1102   if ((This == NULL) || (ChildHandle == NULL)) {
1103     return EFI_INVALID_PARAMETER;
1104   }
1105 
1106   DnsSb = DNS_SERVICE_FROM_THIS (This);
1107 
1108   Status = DnsCreateInstance (DnsSb, &Instance);
1109   if (EFI_ERROR (Status)) {
1110     return Status;
1111   }
1112   ASSERT (Instance != NULL);
1113 
1114   //
1115   // Install the DNS protocol onto ChildHandle
1116   //
1117   Status = gBS->InstallMultipleProtocolInterfaces (
1118                   ChildHandle,
1119                   &gEfiDns4ProtocolGuid,
1120                   &Instance->Dns4,
1121                   NULL
1122                   );
1123   if (EFI_ERROR (Status)) {
1124     goto ON_ERROR;
1125   }
1126 
1127   Instance->ChildHandle = *ChildHandle;
1128 
1129   //
1130   // Open the Udp4 protocol BY_CHILD.
1131   //
1132   Status = gBS->OpenProtocol (
1133                   DnsSb->ConnectUdp->UdpHandle,
1134                   &gEfiUdp4ProtocolGuid,
1135                   (VOID **) &Udp4,
1136                   gDns4DriverBinding.DriverBindingHandle,
1137                   Instance->ChildHandle,
1138                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1139                   );
1140   if (EFI_ERROR (Status)) {
1141     gBS->UninstallMultipleProtocolInterfaces (
1142            Instance->ChildHandle,
1143            &gEfiDns4ProtocolGuid,
1144            &Instance->Dns4,
1145            NULL
1146            );
1147 
1148     goto ON_ERROR;
1149   }
1150 
1151   //
1152   // Open the Udp4 protocol by child.
1153   //
1154   Status = gBS->OpenProtocol (
1155                   Instance->UdpIo->UdpHandle,
1156                   &gEfiUdp4ProtocolGuid,
1157                   (VOID **) &Udp4,
1158                   gDns4DriverBinding.DriverBindingHandle,
1159                   Instance->ChildHandle,
1160                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1161                   );
1162   if (EFI_ERROR (Status)) {
1163     //
1164     // Close the Udp4 protocol.
1165     //
1166     gBS->CloseProtocol (
1167            DnsSb->ConnectUdp->UdpHandle,
1168            &gEfiUdp4ProtocolGuid,
1169            gDns4DriverBinding.DriverBindingHandle,
1170            ChildHandle
1171            );
1172 
1173      gBS->UninstallMultipleProtocolInterfaces (
1174             Instance->ChildHandle,
1175             &gEfiDns4ProtocolGuid,
1176             &Instance->Dns4,
1177             NULL
1178             );
1179 
1180     goto ON_ERROR;
1181   }
1182 
1183   //
1184   // Add it to the parent's child list.
1185   //
1186   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1187 
1188   InsertTailList (&DnsSb->Dns4ChildrenList, &Instance->Link);
1189   DnsSb->Dns4ChildrenNum++;
1190 
1191   gBS->RestoreTPL (OldTpl);
1192 
1193   return EFI_SUCCESS;
1194 
1195 ON_ERROR:
1196 
1197   DnsDestroyInstance (Instance);
1198   return Status;
1199 }
1200 
1201 /**
1202   Destroys a child handle with a protocol installed on it.
1203 
1204   The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
1205   that was installed by CreateChild() from ChildHandle. If the removed protocol is the
1206   last protocol on ChildHandle, then ChildHandle is destroyed.
1207 
1208   @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
1209   @param[in] ChildHandle Handle of the child to destroy
1210 
1211   @retval EFI_SUCCES            The protocol was removed from ChildHandle.
1212   @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.
1213   @retval EFI_INVALID_PARAMETER Child handle is NULL.
1214   @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle
1215                                 because its services are being used.
1216   @retval other                 The child handle was not destroyed
1217 
1218 **/
1219 EFI_STATUS
1220 EFIAPI
Dns4ServiceBindingDestroyChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN EFI_HANDLE ChildHandle)1221 Dns4ServiceBindingDestroyChild (
1222   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
1223   IN EFI_HANDLE                    ChildHandle
1224   )
1225 {
1226   DNS_SERVICE               *DnsSb;
1227   DNS_INSTANCE              *Instance;
1228 
1229   EFI_DNS4_PROTOCOL         *Dns4;
1230   EFI_STATUS                Status;
1231   EFI_TPL                   OldTpl;
1232 
1233   if ((This == NULL) || (ChildHandle == NULL)) {
1234     return EFI_INVALID_PARAMETER;
1235   }
1236 
1237   //
1238   // Retrieve the private context data structures
1239   //
1240   Status = gBS->OpenProtocol (
1241                   ChildHandle,
1242                   &gEfiDns4ProtocolGuid,
1243                   (VOID **) &Dns4,
1244                   gDns4DriverBinding.DriverBindingHandle,
1245                   ChildHandle,
1246                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1247                   );
1248 
1249   if (EFI_ERROR (Status)) {
1250     return EFI_UNSUPPORTED;
1251   }
1252 
1253   Instance  = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (Dns4);
1254   DnsSb     = DNS_SERVICE_FROM_THIS (This);
1255 
1256   if (Instance->Service != DnsSb) {
1257     return EFI_INVALID_PARAMETER;
1258   }
1259 
1260   if (Instance->InDestroy) {
1261     return EFI_SUCCESS;
1262   }
1263 
1264   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1265 
1266   Instance->InDestroy = TRUE;
1267 
1268   //
1269   // Close the Udp4 protocol.
1270   //
1271   gBS->CloseProtocol (
1272          DnsSb->ConnectUdp->UdpHandle,
1273          &gEfiUdp4ProtocolGuid,
1274          gDns4DriverBinding.DriverBindingHandle,
1275          ChildHandle
1276          );
1277 
1278   gBS->CloseProtocol (
1279          Instance->UdpIo->UdpHandle,
1280          &gEfiUdp4ProtocolGuid,
1281          gDns4DriverBinding.DriverBindingHandle,
1282          ChildHandle
1283          );
1284 
1285   gBS->RestoreTPL (OldTpl);
1286 
1287   //
1288   // Uninstall the DNS protocol first to enable a top down destruction.
1289   //
1290   Status = gBS->UninstallProtocolInterface (
1291                   ChildHandle,
1292                   &gEfiDns4ProtocolGuid,
1293                   Dns4
1294                   );
1295 
1296   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1297 
1298   if (EFI_ERROR (Status)) {
1299     Instance->InDestroy = FALSE;
1300     gBS->RestoreTPL (OldTpl);
1301     return Status;
1302   }
1303 
1304   RemoveEntryList (&Instance->Link);
1305   DnsSb->Dns4ChildrenNum--;
1306 
1307   gBS->RestoreTPL (OldTpl);
1308 
1309   DnsDestroyInstance (Instance);
1310   return EFI_SUCCESS;
1311 }
1312 
1313 /**
1314   Creates a child handle and installs a protocol.
1315 
1316   The CreateChild() function installs a protocol on ChildHandle.
1317   If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
1318   If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
1319 
1320   @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
1321   @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
1322                          then a new handle is created. If it is a pointer to an existing UEFI handle,
1323                          then the protocol is added to the existing UEFI handle.
1324 
1325   @retval EFI_SUCCES            The protocol was added to ChildHandle.
1326   @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
1327   @retval EFI_OUT_OF_RESOURCES  There are not enough resources availabe to create
1328                                 the child
1329   @retval other                 The child handle was not created
1330 
1331 **/
1332 EFI_STATUS
1333 EFIAPI
Dns6ServiceBindingCreateChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN EFI_HANDLE * ChildHandle)1334 Dns6ServiceBindingCreateChild (
1335   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
1336   IN EFI_HANDLE                    *ChildHandle
1337   )
1338 {
1339   DNS_SERVICE               *DnsSb;
1340   DNS_INSTANCE              *Instance;
1341   EFI_STATUS                Status;
1342   EFI_TPL                   OldTpl;
1343   VOID                      *Udp6;
1344 
1345   if ((This == NULL) || (ChildHandle == NULL)) {
1346     return EFI_INVALID_PARAMETER;
1347   }
1348 
1349   DnsSb = DNS_SERVICE_FROM_THIS (This);
1350 
1351   Status = DnsCreateInstance (DnsSb, &Instance);
1352   if (EFI_ERROR (Status)) {
1353     return Status;
1354   }
1355   ASSERT (Instance != NULL);
1356 
1357   //
1358   // Install the DNS protocol onto ChildHandle
1359   //
1360   Status = gBS->InstallMultipleProtocolInterfaces (
1361                   ChildHandle,
1362                   &gEfiDns6ProtocolGuid,
1363                   &Instance->Dns6,
1364                   NULL
1365                   );
1366   if (EFI_ERROR (Status)) {
1367     goto ON_ERROR;
1368   }
1369 
1370   Instance->ChildHandle = *ChildHandle;
1371 
1372   //
1373   // Open the Udp6 protocol BY_CHILD.
1374   //
1375   Status = gBS->OpenProtocol (
1376                   DnsSb->ConnectUdp->UdpHandle,
1377                   &gEfiUdp6ProtocolGuid,
1378                   (VOID **) &Udp6,
1379                   gDns6DriverBinding.DriverBindingHandle,
1380                   Instance->ChildHandle,
1381                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1382                   );
1383   if (EFI_ERROR (Status)) {
1384     gBS->UninstallMultipleProtocolInterfaces (
1385            Instance->ChildHandle,
1386            &gEfiDns6ProtocolGuid,
1387            &Instance->Dns6,
1388            NULL
1389            );
1390 
1391     goto ON_ERROR;
1392   }
1393 
1394   //
1395   // Open the Udp6 protocol by child.
1396   //
1397   Status = gBS->OpenProtocol (
1398                   Instance->UdpIo->UdpHandle,
1399                   &gEfiUdp6ProtocolGuid,
1400                   (VOID **) &Udp6,
1401                   gDns6DriverBinding.DriverBindingHandle,
1402                   Instance->ChildHandle,
1403                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1404                   );
1405   if (EFI_ERROR (Status)) {
1406     //
1407     // Close the Udp6 protocol.
1408     //
1409     gBS->CloseProtocol (
1410            DnsSb->ConnectUdp->UdpHandle,
1411            &gEfiUdp6ProtocolGuid,
1412            gDns6DriverBinding.DriverBindingHandle,
1413            ChildHandle
1414            );
1415 
1416      gBS->UninstallMultipleProtocolInterfaces (
1417             Instance->ChildHandle,
1418             &gEfiDns6ProtocolGuid,
1419             &Instance->Dns6,
1420             NULL
1421             );
1422 
1423     goto ON_ERROR;
1424   }
1425 
1426   //
1427   // Add it to the parent's child list.
1428   //
1429   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1430 
1431   InsertTailList (&DnsSb->Dns6ChildrenList, &Instance->Link);
1432   DnsSb->Dns6ChildrenNum++;
1433 
1434   gBS->RestoreTPL (OldTpl);
1435 
1436   return EFI_SUCCESS;
1437 
1438 ON_ERROR:
1439 
1440   DnsDestroyInstance (Instance);
1441   return Status;
1442 }
1443 
1444 /**
1445   Destroys a child handle with a protocol installed on it.
1446 
1447   The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
1448   that was installed by CreateChild() from ChildHandle. If the removed protocol is the
1449   last protocol on ChildHandle, then ChildHandle is destroyed.
1450 
1451   @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
1452   @param[in] ChildHandle Handle of the child to destroy
1453 
1454   @retval EFI_SUCCES            The protocol was removed from ChildHandle.
1455   @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.
1456   @retval EFI_INVALID_PARAMETER Child handle is NULL.
1457   @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle
1458                                 because its services are being used.
1459   @retval other                 The child handle was not destroyed
1460 
1461 **/
1462 EFI_STATUS
1463 EFIAPI
Dns6ServiceBindingDestroyChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN EFI_HANDLE ChildHandle)1464 Dns6ServiceBindingDestroyChild (
1465   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
1466   IN EFI_HANDLE                    ChildHandle
1467   )
1468 {
1469   DNS_SERVICE               *DnsSb;
1470   DNS_INSTANCE              *Instance;
1471 
1472   EFI_DNS6_PROTOCOL         *Dns6;
1473   EFI_STATUS                Status;
1474   EFI_TPL                   OldTpl;
1475 
1476   if ((This == NULL) || (ChildHandle == NULL)) {
1477     return EFI_INVALID_PARAMETER;
1478   }
1479 
1480   //
1481   // Retrieve the private context data structures
1482   //
1483   Status = gBS->OpenProtocol (
1484                   ChildHandle,
1485                   &gEfiDns6ProtocolGuid,
1486                   (VOID **) &Dns6,
1487                   gDns6DriverBinding.DriverBindingHandle,
1488                   ChildHandle,
1489                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1490                   );
1491 
1492   if (EFI_ERROR (Status)) {
1493     return EFI_UNSUPPORTED;
1494   }
1495 
1496   Instance  = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (Dns6);
1497   DnsSb     = DNS_SERVICE_FROM_THIS (This);
1498 
1499   if (Instance->Service != DnsSb) {
1500     return EFI_INVALID_PARAMETER;
1501   }
1502 
1503   if (Instance->InDestroy) {
1504     return EFI_SUCCESS;
1505   }
1506 
1507   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1508 
1509   Instance->InDestroy = TRUE;
1510 
1511   //
1512   // Close the Udp6 protocol.
1513   //
1514   gBS->CloseProtocol (
1515          DnsSb->ConnectUdp->UdpHandle,
1516          &gEfiUdp6ProtocolGuid,
1517          gDns6DriverBinding.DriverBindingHandle,
1518          ChildHandle
1519          );
1520 
1521   gBS->CloseProtocol (
1522          Instance->UdpIo->UdpHandle,
1523          &gEfiUdp6ProtocolGuid,
1524          gDns6DriverBinding.DriverBindingHandle,
1525          ChildHandle
1526          );
1527 
1528   gBS->RestoreTPL (OldTpl);
1529 
1530   //
1531   // Uninstall the DNS protocol first to enable a top down destruction.
1532   //
1533   Status = gBS->UninstallProtocolInterface (
1534                   ChildHandle,
1535                   &gEfiDns6ProtocolGuid,
1536                   Dns6
1537                   );
1538 
1539   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1540 
1541   if (EFI_ERROR (Status)) {
1542     Instance->InDestroy = FALSE;
1543     gBS->RestoreTPL (OldTpl);
1544     return Status;
1545   }
1546 
1547   RemoveEntryList (&Instance->Link);
1548   DnsSb->Dns6ChildrenNum--;
1549 
1550   gBS->RestoreTPL (OldTpl);
1551 
1552   DnsDestroyInstance (Instance);
1553   return EFI_SUCCESS;
1554 }
1555