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