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