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