]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Driver.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Dhcp4Dxe / Dhcp4Driver.c
CommitLineData
772db4bb 1/** @file\r
2\r
7bce0c5a 3Copyright (c) 2006 - 2008, Intel Corporation\r
772db4bb 4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12\r
13Module Name:\r
14\r
15 Dhcp4Driver.c\r
16\r
17Abstract:\r
18\r
19\r
20**/\r
21\r
22#include "Dhcp4Impl.h"\r
23#include "Dhcp4Driver.h"\r
24\r
25EFI_DRIVER_BINDING_PROTOCOL gDhcp4DriverBinding = {\r
26 Dhcp4DriverBindingSupported,\r
27 Dhcp4DriverBindingStart,\r
28 Dhcp4DriverBindingStop,\r
29 0xa,\r
30 NULL,\r
31 NULL\r
32};\r
33\r
34EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplete = {\r
35 Dhcp4ServiceBindingCreateChild,\r
36 Dhcp4ServiceBindingDestroyChild\r
37};\r
38\r
7bce0c5a 39/**\r
40 Entry point of the DHCP driver to install various protocols.\r
41\r
42 @param ImageHandle The image handle of the driver.\r
43 @param SystemTable The system table.\r
44\r
45 @retval EFI_SUCCES if the driver binding and component name protocols are successfully\r
46 @retval Others Failed to install the protocols.\r
772db4bb 47\r
7bce0c5a 48**/\r
772db4bb 49EFI_STATUS\r
50EFIAPI\r
51Dhcp4DriverEntryPoint (\r
52 IN EFI_HANDLE ImageHandle,\r
53 IN EFI_SYSTEM_TABLE *SystemTable\r
54 )\r
772db4bb 55{\r
83cbd279 56 return EfiLibInstallDriverBindingComponentName2 (\r
772db4bb 57 ImageHandle,\r
58 SystemTable,\r
59 &gDhcp4DriverBinding,\r
60 ImageHandle,\r
61 &gDhcp4ComponentName,\r
83cbd279 62 &gDhcp4ComponentName2\r
772db4bb 63 );\r
64}\r
65\r
66\r
67/**\r
68 Test to see if DHCP driver supports the ControllerHandle.\r
69\r
70 @param This Protocol instance pointer.\r
71 @param ControllerHandle Handle of device to test\r
72 @param RemainingDevicePath Optional parameter use to pick a specific child\r
73 device to start.\r
74\r
75 @retval EFI_SUCCES This driver supports this device\r
76 @retval other This driver does not support this device\r
77\r
78**/\r
79EFI_STATUS\r
80EFIAPI\r
81Dhcp4DriverBindingSupported (\r
82 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
83 IN EFI_HANDLE ControllerHandle,\r
84 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
85 )\r
86{\r
87 EFI_STATUS Status;\r
88\r
89 Status = gBS->OpenProtocol (\r
90 ControllerHandle,\r
91 &gEfiUdp4ServiceBindingProtocolGuid,\r
92 NULL,\r
93 This->DriverBindingHandle,\r
94 ControllerHandle,\r
95 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
96 );\r
97\r
98 return Status;\r
99}\r
100\r
101\r
102\r
103/**\r
104 Configure the default UDP child to receive all the DHCP traffics\r
105 on this network interface.\r
106\r
107 @param UdpIo The UDP IO port to configure\r
108 @param Context The context to the function\r
109\r
110 @retval EFI_SUCCESS The UDP IO port is successfully configured.\r
111 @retval Others Failed to configure the UDP child.\r
112\r
113**/\r
114EFI_STATUS\r
115DhcpConfigUdpIo (\r
116 IN UDP_IO_PORT *UdpIo,\r
117 IN VOID *Context\r
118 )\r
119{\r
120 EFI_UDP4_CONFIG_DATA UdpConfigData;\r
121\r
122 UdpConfigData.AcceptBroadcast = TRUE;\r
123 UdpConfigData.AcceptPromiscuous = FALSE;\r
124 UdpConfigData.AcceptAnyPort = FALSE;\r
125 UdpConfigData.AllowDuplicatePort = TRUE;\r
126 UdpConfigData.TypeOfService = 0;\r
127 UdpConfigData.TimeToLive = 64;\r
128 UdpConfigData.DoNotFragment = FALSE;\r
129 UdpConfigData.ReceiveTimeout = 0;\r
130 UdpConfigData.TransmitTimeout = 0;\r
131\r
132 UdpConfigData.UseDefaultAddress = FALSE;\r
133 UdpConfigData.StationPort = DHCP_CLIENT_PORT;\r
134 UdpConfigData.RemotePort = DHCP_SERVER_PORT;\r
135\r
e48e37fc 136 ZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));\r
137 ZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
138 ZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));\r
772db4bb 139\r
140 return UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfigData);;\r
141}\r
142\r
143\r
144\r
145/**\r
146 Destory the DHCP service. The Dhcp4 service may be partly initialized,\r
147 or partly destoried. If a resource is destoried, it is marked as so in\r
148 case the destory failed and being called again later.\r
149\r
150 @param DhcpSb The DHCP service instance to destory.\r
151\r
152 @retval EFI_SUCCESS The DHCP service is successfully closed.\r
153\r
154**/\r
155EFI_STATUS\r
156Dhcp4CloseService (\r
157 IN DHCP_SERVICE *DhcpSb\r
158 )\r
159{\r
160 DhcpCleanLease (DhcpSb);\r
161\r
162 if (DhcpSb->UdpIo != NULL) {\r
163 UdpIoFreePort (DhcpSb->UdpIo);\r
164 DhcpSb->UdpIo = NULL;\r
165 }\r
166\r
167 if (DhcpSb->Timer != NULL) {\r
168 gBS->SetTimer (DhcpSb->Timer, TimerCancel, 0);\r
169 gBS->CloseEvent (DhcpSb->Timer);\r
170\r
171 DhcpSb->Timer = NULL;\r
172 }\r
173\r
174 return EFI_SUCCESS;\r
175}\r
176\r
177\r
178\r
179/**\r
180 Create a new DHCP service binding instance for the controller.\r
181\r
182 @param Controller The controller to install DHCP service binding\r
183 protocol onto\r
184 @param ImageHandle The driver's image handle\r
185 @param Service The variable to receive the created DHCP service\r
186 instance.\r
187\r
188 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource .\r
189 @retval EFI_SUCCESS The DHCP service instance is created.\r
190\r
191**/\r
192EFI_STATUS\r
193Dhcp4CreateService (\r
194 IN EFI_HANDLE Controller,\r
195 IN EFI_HANDLE ImageHandle,\r
196 OUT DHCP_SERVICE **Service\r
197 )\r
198{\r
199 DHCP_SERVICE *DhcpSb;\r
200 EFI_STATUS Status;\r
201\r
202 *Service = NULL;\r
e48e37fc 203 DhcpSb = AllocateZeroPool (sizeof (DHCP_SERVICE));\r
772db4bb 204\r
205 if (DhcpSb == NULL) {\r
206 return EFI_OUT_OF_RESOURCES;\r
207 }\r
208\r
209 DhcpSb->Signature = DHCP_SERVICE_SIGNATURE;\r
210 DhcpSb->ServiceBinding = mDhcp4ServiceBindingTemplete;\r
211 DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
212 DhcpSb->InDestory = FALSE;\r
213 DhcpSb->Controller = Controller;\r
214 DhcpSb->Image = ImageHandle;\r
e48e37fc 215 InitializeListHead (&DhcpSb->Children);\r
772db4bb 216 DhcpSb->DhcpState = Dhcp4Stopped;\r
217 DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ());\r
218\r
219 //\r
220 // Create various resources, UdpIo, Timer, and get Mac address\r
221 //\r
222 Status = gBS->CreateEvent (\r
223 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 224 TPL_CALLBACK,\r
772db4bb 225 DhcpOnTimerTick,\r
226 DhcpSb,\r
227 &DhcpSb->Timer\r
228 );\r
229\r
230 if (EFI_ERROR (Status)) {\r
231 goto ON_ERROR;\r
232 }\r
233\r
234 DhcpSb->UdpIo = UdpIoCreatePort (Controller, ImageHandle, DhcpConfigUdpIo, NULL);\r
235\r
236 if (DhcpSb->UdpIo == NULL) {\r
237 Status = EFI_OUT_OF_RESOURCES;\r
238 goto ON_ERROR;\r
239 }\r
240\r
241 DhcpSb->HwLen = (UINT8) DhcpSb->UdpIo->SnpMode.HwAddressSize;\r
242 DhcpSb->HwType = DhcpSb->UdpIo->SnpMode.IfType;\r
687a2e5f 243 CopyMem (&DhcpSb->Mac, &DhcpSb->UdpIo->SnpMode.CurrentAddress, sizeof (DhcpSb->Mac));\r
772db4bb 244\r
245 *Service = DhcpSb;\r
246 return EFI_SUCCESS;\r
247\r
248ON_ERROR:\r
249 Dhcp4CloseService (DhcpSb);\r
e48e37fc 250 gBS->FreePool (DhcpSb);\r
772db4bb 251\r
252 return Status;\r
253}\r
254\r
255\r
256/**\r
257 Start this driver on ControllerHandle.\r
258\r
259 @param This Protocol instance pointer.\r
260 @param ControllerHandle Handle of device to bind driver to\r
261 @param RemainingDevicePath Optional parameter use to pick a specific child\r
262 device to start.\r
263\r
264 @retval EFI_SUCCES This driver is added to ControllerHandle\r
265 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
266 @retval other This driver does not support this device\r
267\r
268**/\r
269EFI_STATUS\r
270EFIAPI\r
271Dhcp4DriverBindingStart (\r
272 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
273 IN EFI_HANDLE ControllerHandle,\r
274 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
275 )\r
276{\r
277 DHCP_SERVICE *DhcpSb;\r
278 EFI_STATUS Status;\r
279\r
280 //\r
281 // First: test for the DHCP4 Protocol\r
282 //\r
283 Status = gBS->OpenProtocol (\r
284 ControllerHandle,\r
285 &gEfiDhcp4ServiceBindingProtocolGuid,\r
286 NULL,\r
287 This->DriverBindingHandle,\r
288 ControllerHandle,\r
289 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
290 );\r
291\r
292 if (Status == EFI_SUCCESS) {\r
293 return EFI_ALREADY_STARTED;\r
294 }\r
295\r
296 Status = Dhcp4CreateService (ControllerHandle, This->DriverBindingHandle, &DhcpSb);\r
297\r
298 if (EFI_ERROR (Status)) {\r
299 return Status;\r
300 }\r
301\r
302 Status = gBS->SetTimer (DhcpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
303\r
304 if (EFI_ERROR (Status)) {\r
305 goto ON_ERROR;\r
306 }\r
307\r
308 //\r
309 // Install the Dhcp4ServiceBinding Protocol onto ControlerHandle\r
310 //\r
311 Status = gBS->InstallMultipleProtocolInterfaces (\r
312 &ControllerHandle,\r
313 &gEfiDhcp4ServiceBindingProtocolGuid,\r
314 &DhcpSb->ServiceBinding,\r
315 NULL\r
316 );\r
317\r
318 if (EFI_ERROR (Status)) {\r
319 goto ON_ERROR;\r
320 }\r
321\r
322 return Status;\r
323\r
324ON_ERROR:\r
325 Dhcp4CloseService (DhcpSb);\r
e48e37fc 326 gBS->FreePool (DhcpSb);\r
772db4bb 327 return Status;\r
328}\r
329\r
330\r
331/**\r
332 Stop this driver on ControllerHandle.\r
333\r
334 @param This Protocol instance pointer.\r
335 @param ControllerHandle Handle of device to stop driver on\r
336 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
337 of children is zero stop the entire bus driver.\r
338 @param ChildHandleBuffer List of Child Handles to Stop.\r
339\r
340 @retval EFI_SUCCES This driver is removed ControllerHandle\r
341 @retval other This driver was not removed from this device\r
342\r
343**/\r
344EFI_STATUS\r
345EFIAPI\r
346Dhcp4DriverBindingStop (\r
347 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
348 IN EFI_HANDLE ControllerHandle,\r
349 IN UINTN NumberOfChildren,\r
350 IN EFI_HANDLE *ChildHandleBuffer\r
351 )\r
352{\r
353 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
354 DHCP_SERVICE *DhcpSb;\r
355 DHCP_PROTOCOL *Instance;\r
356 EFI_HANDLE NicHandle;\r
357 EFI_STATUS Status;\r
358 EFI_TPL OldTpl;\r
359\r
360 //\r
361 // DHCP driver opens UDP child, So, the ControllerHandle is the\r
362 // UDP child handle. locate the Nic handle first.\r
363 //\r
364 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);\r
365\r
366 if (NicHandle == NULL) {\r
c4a62a12 367 return EFI_DEVICE_ERROR;\r
772db4bb 368 }\r
369\r
370 Status = gBS->OpenProtocol (\r
371 NicHandle,\r
372 &gEfiDhcp4ServiceBindingProtocolGuid,\r
373 (VOID **) &ServiceBinding,\r
374 This->DriverBindingHandle,\r
375 NicHandle,\r
376 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
377 );\r
378\r
379 if (EFI_ERROR (Status)) {\r
380 return EFI_DEVICE_ERROR;\r
381 }\r
382\r
383 DhcpSb = DHCP_SERVICE_FROM_THIS (ServiceBinding);\r
384\r
385 if (DhcpSb->InDestory) {\r
386 return EFI_SUCCESS;\r
387 }\r
388\r
e48e37fc 389 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 390\r
c4a62a12 391 if (NumberOfChildren == 0) {\r
772db4bb 392\r
c4a62a12 393 DhcpSb->InDestory = TRUE;\r
394 DhcpSb->ServiceState = DHCP_DESTORY;\r
772db4bb 395\r
c4a62a12 396 gBS->UninstallProtocolInterface (\r
397 NicHandle,\r
398 &gEfiDhcp4ServiceBindingProtocolGuid,\r
399 ServiceBinding\r
400 );\r
772db4bb 401\r
c4a62a12 402 Dhcp4CloseService (DhcpSb);\r
403\r
e48e37fc 404 gBS->FreePool (DhcpSb);\r
c4a62a12 405 } else {\r
406 //\r
407 // Don't use NET_LIST_FOR_EACH_SAFE here, Dhcp4ServiceBindingDestoryChild\r
408 // may cause other child to be deleted.\r
409 //\r
e48e37fc 410 while (!IsListEmpty (&DhcpSb->Children)) {\r
c4a62a12 411 Instance = NET_LIST_HEAD (&DhcpSb->Children, DHCP_PROTOCOL, Link);\r
412 ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
413 }\r
414\r
415 if (DhcpSb->NumChildren != 0) {\r
416 Status = EFI_DEVICE_ERROR;\r
417 }\r
772db4bb 418 }\r
419\r
e48e37fc 420 gBS->RestoreTPL (OldTpl);\r
772db4bb 421\r
772db4bb 422 return Status;\r
423}\r
424\r
425\r
426/**\r
7bce0c5a 427 Initialize a new DHCP child.\r
772db4bb 428\r
429 @param DhcpSb The dhcp service instance\r
430 @param Instance The dhcp instance to initialize\r
431\r
432 @return None\r
433\r
434**/\r
435VOID\r
436DhcpInitProtocol (\r
437 IN DHCP_SERVICE *DhcpSb,\r
438 IN DHCP_PROTOCOL *Instance\r
439 )\r
440{\r
441 Instance->Signature = DHCP_PROTOCOL_SIGNATURE;\r
687a2e5f 442 CopyMem (&Instance->Dhcp4Protocol, &mDhcp4ProtocolTemplate, sizeof (Instance->Dhcp4Protocol));\r
e48e37fc 443 InitializeListHead (&Instance->Link);\r
772db4bb 444 Instance->Handle = NULL;\r
445 Instance->Service = DhcpSb;\r
446 Instance->InDestory = FALSE;\r
447 Instance->CompletionEvent = NULL;\r
448 Instance->RenewRebindEvent = NULL;\r
449 Instance->Token = NULL;\r
c4a62a12 450 Instance->UdpIo = NULL;\r
451 NetbufQueInit (&Instance->ResponseQueue);\r
772db4bb 452}\r
453\r
454\r
455/**\r
456 Creates a child handle with a set of DHCP4 services.\r
457\r
458 @param This Protocol instance pointer.\r
459 @param ChildHandle Pointer to the handle of the child to create. If\r
460 it is NULL, then a new handle is created. If it\r
461 is not NULL, then the DHCP4 services are added to\r
462 the existing child handle.\r
463\r
464 @retval EFI_SUCCES The child handle was created with the DHCP4\r
465 services\r
466 @retval EFI_OUT_OF_RESOURCES There are not enough resources to create the child\r
467 @retval other The child handle was not created\r
468\r
469**/\r
470EFI_STATUS\r
471EFIAPI\r
472Dhcp4ServiceBindingCreateChild (\r
473 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
474 IN EFI_HANDLE *ChildHandle\r
475 )\r
476{\r
477 DHCP_SERVICE *DhcpSb;\r
478 DHCP_PROTOCOL *Instance;\r
479 EFI_STATUS Status;\r
480 EFI_TPL OldTpl;\r
481 VOID *Udp4;\r
482\r
483 if ((This == NULL) || (ChildHandle == NULL)) {\r
484 return EFI_INVALID_PARAMETER;\r
485 }\r
486\r
e48e37fc 487 Instance = AllocatePool (sizeof (*Instance));\r
772db4bb 488\r
489 if (Instance == NULL) {\r
490 return EFI_OUT_OF_RESOURCES;\r
491 }\r
492\r
493 DhcpSb = DHCP_SERVICE_FROM_THIS (This);\r
494 DhcpInitProtocol (DhcpSb, Instance);\r
495\r
496 //\r
497 // Install DHCP4 onto ChildHandle\r
498 //\r
499 Status = gBS->InstallMultipleProtocolInterfaces (\r
500 ChildHandle,\r
501 &gEfiDhcp4ProtocolGuid,\r
502 &Instance->Dhcp4Protocol,\r
503 NULL\r
504 );\r
505\r
506 if (EFI_ERROR (Status)) {\r
e48e37fc 507 gBS->FreePool (Instance);\r
772db4bb 508 return Status;\r
509 }\r
510\r
511 Instance->Handle = *ChildHandle;\r
512\r
513 //\r
514 // Open the Udp4 protocol BY_CHILD.\r
515 //\r
516 Status = gBS->OpenProtocol (\r
517 DhcpSb->UdpIo->UdpHandle,\r
518 &gEfiUdp4ProtocolGuid,\r
519 (VOID **) &Udp4,\r
520 gDhcp4DriverBinding.DriverBindingHandle,\r
521 Instance->Handle,\r
522 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
523 );\r
524 if (EFI_ERROR (Status)) {\r
525 gBS->UninstallMultipleProtocolInterfaces (\r
526 Instance->Handle,\r
527 &gEfiDhcp4ProtocolGuid,\r
528 &Instance->Dhcp4Protocol,\r
529 NULL\r
530 );\r
531\r
e48e37fc 532 gBS->FreePool (Instance);\r
772db4bb 533 return Status;\r
534 }\r
535\r
e48e37fc 536 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 537\r
e48e37fc 538 InsertTailList (&DhcpSb->Children, &Instance->Link);\r
772db4bb 539 DhcpSb->NumChildren++;\r
540\r
e48e37fc 541 gBS->RestoreTPL (OldTpl);\r
772db4bb 542\r
543 return EFI_SUCCESS;\r
544}\r
545\r
546\r
547/**\r
548 Destroys a child handle with a set of DHCP4 services.\r
549\r
550 @param This Protocol instance pointer.\r
551 @param ChildHandle Handle of the child to destroy\r
552\r
553 @retval EFI_SUCCES The DHCP4 service is removed from the child handle\r
554 @retval EFI_UNSUPPORTED The child handle does not support the DHCP4\r
555 service\r
556 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.\r
557 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because\r
558 its DHCP4 services are being used.\r
559 @retval other The child handle was not destroyed\r
560\r
561**/\r
562EFI_STATUS\r
563EFIAPI\r
564Dhcp4ServiceBindingDestroyChild (\r
565 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
566 IN EFI_HANDLE ChildHandle\r
567 )\r
568{\r
569 DHCP_SERVICE *DhcpSb;\r
570 DHCP_PROTOCOL *Instance;\r
571 EFI_DHCP4_PROTOCOL *Dhcp;\r
572 EFI_TPL OldTpl;\r
573 EFI_STATUS Status;\r
574\r
575 if ((This == NULL) || (ChildHandle == NULL)) {\r
576 return EFI_INVALID_PARAMETER;\r
577 }\r
578\r
579 //\r
580 // Retrieve the private context data structures\r
581 //\r
582 Status = gBS->OpenProtocol (\r
583 ChildHandle,\r
584 &gEfiDhcp4ProtocolGuid,\r
585 (VOID **) &Dhcp,\r
586 gDhcp4DriverBinding.DriverBindingHandle,\r
587 ChildHandle,\r
588 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
589 );\r
590\r
591 if (EFI_ERROR (Status)) {\r
592 return EFI_UNSUPPORTED;\r
593 }\r
594\r
595 Instance = DHCP_INSTANCE_FROM_THIS (Dhcp);\r
596 DhcpSb = DHCP_SERVICE_FROM_THIS (This);\r
597\r
598 if (Instance->Service != DhcpSb) {\r
599 return EFI_INVALID_PARAMETER;\r
600 }\r
601\r
602 //\r
603 // A child can be destoried more than once. For example,\r
604 // Dhcp4DriverBindingStop will destory all of its children.\r
605 // when caller driver is being stopped, it will destory the\r
606 // dhcp child it opens.\r
607 //\r
608 if (Instance->InDestory) {\r
609 return EFI_SUCCESS;\r
610 }\r
611\r
e48e37fc 612 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 613 Instance->InDestory = TRUE;\r
614\r
615 //\r
616 // Close the Udp4 protocol.\r
617 //\r
618 gBS->CloseProtocol (\r
619 DhcpSb->UdpIo->UdpHandle,\r
620 &gEfiUdp4ProtocolGuid,\r
621 gDhcp4DriverBinding.DriverBindingHandle,\r
622 ChildHandle\r
623 );\r
624\r
625 //\r
626 // Uninstall the DHCP4 protocol first to enable a top down destruction.\r
627 //\r
628 Status = gBS->UninstallProtocolInterface (\r
629 ChildHandle,\r
630 &gEfiDhcp4ProtocolGuid,\r
631 Dhcp\r
632 );\r
633\r
634 if (EFI_ERROR (Status)) {\r
635 Instance->InDestory = FALSE;\r
636\r
e48e37fc 637 gBS->RestoreTPL (OldTpl);\r
772db4bb 638 return Status;\r
639 }\r
640\r
641 if (DhcpSb->ActiveChild == Instance) {\r
642 DhcpYieldControl (DhcpSb);\r
643 }\r
644\r
e48e37fc 645 RemoveEntryList (&Instance->Link);\r
772db4bb 646 DhcpSb->NumChildren--;\r
647\r
e48e37fc 648 gBS->RestoreTPL (OldTpl);\r
772db4bb 649\r
e48e37fc 650 gBS->FreePool (Instance);\r
772db4bb 651 return EFI_SUCCESS;\r
652}\r