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