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