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