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