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