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