]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / Dhcp4Dxe / Dhcp4Driver.c
1 /** @file
2
3 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6 **/
7
8 #include "Dhcp4Impl.h"
9 #include "Dhcp4Driver.h"
10
11 EFI_DRIVER_BINDING_PROTOCOL gDhcp4DriverBinding = {
12 Dhcp4DriverBindingSupported,
13 Dhcp4DriverBindingStart,
14 Dhcp4DriverBindingStop,
15 0xa,
16 NULL,
17 NULL
18 };
19
20 EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplate = {
21 Dhcp4ServiceBindingCreateChild,
22 Dhcp4ServiceBindingDestroyChild
23 };
24
25 /**
26 This is the declaration of an EFI image entry point. This entry point is
27 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
28 both device drivers and bus drivers.
29
30 Entry point of the DHCP driver to install various protocols.
31
32 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
33 @param[in] SystemTable A pointer to the EFI System Table.
34
35 @retval EFI_SUCCESS The operation completed successfully.
36 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
37
38 **/
39 EFI_STATUS
40 EFIAPI
41 Dhcp4DriverEntryPoint (
42 IN EFI_HANDLE ImageHandle,
43 IN EFI_SYSTEM_TABLE *SystemTable
44 )
45 {
46 return EfiLibInstallDriverBindingComponentName2 (
47 ImageHandle,
48 SystemTable,
49 &gDhcp4DriverBinding,
50 ImageHandle,
51 &gDhcp4ComponentName,
52 &gDhcp4ComponentName2
53 );
54 }
55
56 /**
57 Test to see if this driver supports ControllerHandle. This service
58 is called by the EFI boot service ConnectController(). In
59 order to make drivers as small as possible, there are a few calling
60 restrictions for this service. ConnectController() must
61 follow these calling restrictions. If any other agent wishes to call
62 Supported() it must also follow these calling restrictions.
63
64 @param[in] This Protocol instance pointer.
65 @param[in] ControllerHandle Handle of device to test
66 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
67 device to start.
68
69 @retval EFI_SUCCESS This driver supports this device
70 @retval EFI_ALREADY_STARTED This driver is already running on this device
71 @retval other This driver does not support this device
72
73 **/
74 EFI_STATUS
75 EFIAPI
76 Dhcp4DriverBindingSupported (
77 IN EFI_DRIVER_BINDING_PROTOCOL *This,
78 IN EFI_HANDLE ControllerHandle,
79 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
80 )
81 {
82 EFI_STATUS Status;
83
84 Status = gBS->OpenProtocol (
85 ControllerHandle,
86 &gEfiUdp4ServiceBindingProtocolGuid,
87 NULL,
88 This->DriverBindingHandle,
89 ControllerHandle,
90 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
91 );
92
93 return Status;
94 }
95
96 /**
97 Configure the default UDP child to receive all the DHCP traffics
98 on this network interface.
99
100 @param[in] UdpIo The UDP IO to configure
101 @param[in] Context The context to the function
102
103 @retval EFI_SUCCESS The UDP IO is successfully configured.
104 @retval Others Failed to configure the UDP child.
105
106 **/
107 EFI_STATUS
108 EFIAPI
109 DhcpConfigUdpIo (
110 IN UDP_IO *UdpIo,
111 IN VOID *Context
112 )
113 {
114 EFI_UDP4_CONFIG_DATA UdpConfigData;
115
116 UdpConfigData.AcceptBroadcast = TRUE;
117 UdpConfigData.AcceptPromiscuous = FALSE;
118 UdpConfigData.AcceptAnyPort = FALSE;
119 UdpConfigData.AllowDuplicatePort = TRUE;
120 UdpConfigData.TypeOfService = 0;
121 UdpConfigData.TimeToLive = 64;
122 UdpConfigData.DoNotFragment = FALSE;
123 UdpConfigData.ReceiveTimeout = 0;
124 UdpConfigData.TransmitTimeout = 0;
125
126 UdpConfigData.UseDefaultAddress = FALSE;
127 UdpConfigData.StationPort = DHCP_CLIENT_PORT;
128 UdpConfigData.RemotePort = DHCP_SERVER_PORT;
129
130 ZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));
131 ZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
132 ZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));
133
134 return UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData);
135 }
136
137 /**
138 Destroy the DHCP service. The Dhcp4 service may be partly initialized,
139 or partly destroyed. If a resource is destroyed, it is marked as so in
140 case the destroy failed and being called again later.
141
142 @param[in] DhcpSb The DHCP service instance to destroy.
143
144 @retval EFI_SUCCESS Always return success.
145
146 **/
147 EFI_STATUS
148 Dhcp4CloseService (
149 IN DHCP_SERVICE *DhcpSb
150 )
151 {
152 DhcpCleanLease (DhcpSb);
153
154 if (DhcpSb->UdpIo != NULL) {
155 UdpIoFreeIo (DhcpSb->UdpIo);
156 DhcpSb->UdpIo = NULL;
157 }
158
159 if (DhcpSb->Timer != NULL) {
160 gBS->SetTimer (DhcpSb->Timer, TimerCancel, 0);
161 gBS->CloseEvent (DhcpSb->Timer);
162
163 DhcpSb->Timer = NULL;
164 }
165
166 return EFI_SUCCESS;
167 }
168
169 /**
170 Create a new DHCP service binding instance for the controller.
171
172 @param[in] Controller The controller to install DHCP service binding
173 protocol onto
174 @param[in] ImageHandle The driver's image handle
175 @param[out] Service The variable to receive the created DHCP service
176 instance.
177
178 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource .
179 @retval EFI_SUCCESS The DHCP service instance is created.
180 @retval other Other error occurs.
181
182 **/
183 EFI_STATUS
184 Dhcp4CreateService (
185 IN EFI_HANDLE Controller,
186 IN EFI_HANDLE ImageHandle,
187 OUT DHCP_SERVICE **Service
188 )
189 {
190 DHCP_SERVICE *DhcpSb;
191 EFI_STATUS Status;
192
193 *Service = NULL;
194 DhcpSb = AllocateZeroPool (sizeof (DHCP_SERVICE));
195
196 if (DhcpSb == NULL) {
197 return EFI_OUT_OF_RESOURCES;
198 }
199
200 DhcpSb->Signature = DHCP_SERVICE_SIGNATURE;
201 DhcpSb->ServiceState = DHCP_UNCONFIGED;
202 DhcpSb->Controller = Controller;
203 DhcpSb->Image = ImageHandle;
204 InitializeListHead (&DhcpSb->Children);
205 DhcpSb->DhcpState = Dhcp4Stopped;
206 DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ());
207 CopyMem (
208 &DhcpSb->ServiceBinding,
209 &mDhcp4ServiceBindingTemplate,
210 sizeof (EFI_SERVICE_BINDING_PROTOCOL)
211 );
212 //
213 // Create various resources, UdpIo, Timer, and get Mac address
214 //
215 Status = gBS->CreateEvent (
216 EVT_NOTIFY_SIGNAL | EVT_TIMER,
217 TPL_CALLBACK,
218 DhcpOnTimerTick,
219 DhcpSb,
220 &DhcpSb->Timer
221 );
222
223 if (EFI_ERROR (Status)) {
224 goto ON_ERROR;
225 }
226
227 DhcpSb->UdpIo = UdpIoCreateIo (
228 Controller,
229 ImageHandle,
230 DhcpConfigUdpIo,
231 UDP_IO_UDP4_VERSION,
232 NULL
233 );
234
235 if (DhcpSb->UdpIo == NULL) {
236 Status = EFI_OUT_OF_RESOURCES;
237 goto ON_ERROR;
238 }
239
240 DhcpSb->HwLen = (UINT8)DhcpSb->UdpIo->SnpMode.HwAddressSize;
241 DhcpSb->HwType = DhcpSb->UdpIo->SnpMode.IfType;
242 CopyMem (&DhcpSb->Mac, &DhcpSb->UdpIo->SnpMode.CurrentAddress, sizeof (DhcpSb->Mac));
243
244 *Service = DhcpSb;
245 return EFI_SUCCESS;
246
247 ON_ERROR:
248 Dhcp4CloseService (DhcpSb);
249 FreePool (DhcpSb);
250
251 return Status;
252 }
253
254 /**
255 Start this driver on ControllerHandle. This service is called by the
256 EFI boot service ConnectController(). In order to make
257 drivers as small as possible, there are a few calling restrictions for
258 this service. ConnectController() must follow these
259 calling restrictions. If any other agent wishes to call Start() it
260 must also follow these calling restrictions.
261
262 @param[in] This Protocol instance pointer.
263 @param[in] ControllerHandle Handle of device to bind driver to
264 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
265 device to start.
266
267 @retval EFI_SUCCESS This driver is added to ControllerHandle
268 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
269 @retval other This driver does not support this device
270
271 **/
272 EFI_STATUS
273 EFIAPI
274 Dhcp4DriverBindingStart (
275 IN EFI_DRIVER_BINDING_PROTOCOL *This,
276 IN EFI_HANDLE ControllerHandle,
277 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
278 )
279 {
280 DHCP_SERVICE *DhcpSb;
281 EFI_STATUS Status;
282
283 //
284 // First: test for the DHCP4 Protocol
285 //
286 Status = gBS->OpenProtocol (
287 ControllerHandle,
288 &gEfiDhcp4ServiceBindingProtocolGuid,
289 NULL,
290 This->DriverBindingHandle,
291 ControllerHandle,
292 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
293 );
294
295 if (Status == EFI_SUCCESS) {
296 return EFI_ALREADY_STARTED;
297 }
298
299 Status = Dhcp4CreateService (ControllerHandle, This->DriverBindingHandle, &DhcpSb);
300
301 if (EFI_ERROR (Status)) {
302 return Status;
303 }
304
305 ASSERT (DhcpSb != NULL);
306
307 //
308 // Start the receiving
309 //
310 Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);
311
312 if (EFI_ERROR (Status)) {
313 goto ON_ERROR;
314 }
315
316 Status = gBS->SetTimer (DhcpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
317
318 if (EFI_ERROR (Status)) {
319 goto ON_ERROR;
320 }
321
322 //
323 // Install the Dhcp4ServiceBinding Protocol onto ControllerHandle
324 //
325 Status = gBS->InstallMultipleProtocolInterfaces (
326 &ControllerHandle,
327 &gEfiDhcp4ServiceBindingProtocolGuid,
328 &DhcpSb->ServiceBinding,
329 NULL
330 );
331
332 if (EFI_ERROR (Status)) {
333 goto ON_ERROR;
334 }
335
336 return Status;
337
338 ON_ERROR:
339 Dhcp4CloseService (DhcpSb);
340 FreePool (DhcpSb);
341 return Status;
342 }
343
344 /**
345 Callback function which provided by user to remove one node in NetDestroyLinkList process.
346
347 @param[in] Entry The entry to be removed.
348 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
349
350 @retval EFI_SUCCESS The entry has been removed successfully.
351 @retval Others Fail to remove the entry.
352
353 **/
354 EFI_STATUS
355 EFIAPI
356 Dhcp4DestroyChildEntry (
357 IN LIST_ENTRY *Entry,
358 IN VOID *Context
359 )
360 {
361 DHCP_PROTOCOL *Instance;
362 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
363
364 if ((Entry == NULL) || (Context == NULL)) {
365 return EFI_INVALID_PARAMETER;
366 }
367
368 Instance = NET_LIST_USER_STRUCT_S (Entry, DHCP_PROTOCOL, Link, DHCP_PROTOCOL_SIGNATURE);
369 ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *)Context;
370
371 return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
372 }
373
374 /**
375 Stop this driver on ControllerHandle. This service is called by the
376 EFI boot service DisconnectController(). In order to
377 make drivers as small as possible, there are a few calling
378 restrictions for this service. DisconnectController()
379 must follow these calling restrictions. If any other agent wishes
380 to call Stop() it must also follow these calling restrictions.
381
382 @param[in] This Protocol instance pointer.
383 @param[in] ControllerHandle Handle of device to stop driver on
384 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
385 children is zero stop the entire bus driver.
386 @param[in] ChildHandleBuffer List of Child Handles to Stop.
387
388 @retval EFI_SUCCESS This driver is removed ControllerHandle
389 @retval other This driver was not removed from this device
390
391 **/
392 EFI_STATUS
393 EFIAPI
394 Dhcp4DriverBindingStop (
395 IN EFI_DRIVER_BINDING_PROTOCOL *This,
396 IN EFI_HANDLE ControllerHandle,
397 IN UINTN NumberOfChildren,
398 IN EFI_HANDLE *ChildHandleBuffer
399 )
400 {
401 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
402 DHCP_SERVICE *DhcpSb;
403 EFI_HANDLE NicHandle;
404 EFI_STATUS Status;
405 LIST_ENTRY *List;
406 UINTN ListLength;
407
408 //
409 // DHCP driver opens UDP child, So, the ControllerHandle is the
410 // UDP child handle. locate the Nic handle first.
411 //
412 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
413
414 if (NicHandle == NULL) {
415 return EFI_SUCCESS;
416 }
417
418 Status = gBS->OpenProtocol (
419 NicHandle,
420 &gEfiDhcp4ServiceBindingProtocolGuid,
421 (VOID **)&ServiceBinding,
422 This->DriverBindingHandle,
423 NicHandle,
424 EFI_OPEN_PROTOCOL_GET_PROTOCOL
425 );
426
427 if (EFI_ERROR (Status)) {
428 return EFI_DEVICE_ERROR;
429 }
430
431 DhcpSb = DHCP_SERVICE_FROM_THIS (ServiceBinding);
432 if (!IsListEmpty (&DhcpSb->Children)) {
433 //
434 // Destroy all the children instances before destroy the service.
435 //
436 List = &DhcpSb->Children;
437 Status = NetDestroyLinkList (
438 List,
439 Dhcp4DestroyChildEntry,
440 ServiceBinding,
441 &ListLength
442 );
443 if (EFI_ERROR (Status) || (ListLength != 0)) {
444 Status = EFI_DEVICE_ERROR;
445 }
446 }
447
448 if ((NumberOfChildren == 0) && !IsListEmpty (&DhcpSb->Children)) {
449 Status = EFI_DEVICE_ERROR;
450 }
451
452 if ((NumberOfChildren == 0) && IsListEmpty (&DhcpSb->Children)) {
453 //
454 // Destroy the service itself if no child instance left.
455 //
456 DhcpSb->ServiceState = DHCP_DESTROY;
457
458 gBS->UninstallProtocolInterface (
459 NicHandle,
460 &gEfiDhcp4ServiceBindingProtocolGuid,
461 ServiceBinding
462 );
463
464 Dhcp4CloseService (DhcpSb);
465
466 if (gDhcpControllerNameTable != NULL) {
467 FreeUnicodeStringTable (gDhcpControllerNameTable);
468 gDhcpControllerNameTable = NULL;
469 }
470
471 FreePool (DhcpSb);
472
473 Status = EFI_SUCCESS;
474 }
475
476 return Status;
477 }
478
479 /**
480 Initialize a new DHCP instance.
481
482 @param DhcpSb The dhcp service instance
483 @param Instance The dhcp instance to initialize
484
485 **/
486 VOID
487 DhcpInitProtocol (
488 IN DHCP_SERVICE *DhcpSb,
489 IN OUT DHCP_PROTOCOL *Instance
490 )
491 {
492 Instance->Signature = DHCP_PROTOCOL_SIGNATURE;
493 CopyMem (&Instance->Dhcp4Protocol, &mDhcp4ProtocolTemplate, sizeof (Instance->Dhcp4Protocol));
494 InitializeListHead (&Instance->Link);
495 Instance->Handle = NULL;
496 Instance->Service = DhcpSb;
497 Instance->InDestroy = FALSE;
498 Instance->CompletionEvent = NULL;
499 Instance->RenewRebindEvent = NULL;
500 Instance->Token = NULL;
501 Instance->UdpIo = NULL;
502 Instance->ElaspedTime = 0;
503 NetbufQueInit (&Instance->ResponseQueue);
504 }
505
506 /**
507 Creates a child handle and installs a protocol.
508
509 The CreateChild() function installs a protocol on ChildHandle.
510 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
511 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
512
513 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
514 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,
515 then a new handle is created. If it is a pointer to an existing UEFI handle,
516 then the protocol is added to the existing UEFI handle.
517
518 @retval EFI_SUCCESS The protocol was added to ChildHandle.
519 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
520 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
521 the child
522 @retval other The child handle was not created
523
524 **/
525 EFI_STATUS
526 EFIAPI
527 Dhcp4ServiceBindingCreateChild (
528 IN EFI_SERVICE_BINDING_PROTOCOL *This,
529 IN EFI_HANDLE *ChildHandle
530 )
531 {
532 DHCP_SERVICE *DhcpSb;
533 DHCP_PROTOCOL *Instance;
534 EFI_STATUS Status;
535 EFI_TPL OldTpl;
536 VOID *Udp4;
537
538 if ((This == NULL) || (ChildHandle == NULL)) {
539 return EFI_INVALID_PARAMETER;
540 }
541
542 Instance = AllocatePool (sizeof (*Instance));
543
544 if (Instance == NULL) {
545 return EFI_OUT_OF_RESOURCES;
546 }
547
548 DhcpSb = DHCP_SERVICE_FROM_THIS (This);
549 DhcpInitProtocol (DhcpSb, Instance);
550
551 //
552 // Install DHCP4 onto ChildHandle
553 //
554 Status = gBS->InstallMultipleProtocolInterfaces (
555 ChildHandle,
556 &gEfiDhcp4ProtocolGuid,
557 &Instance->Dhcp4Protocol,
558 NULL
559 );
560
561 if (EFI_ERROR (Status)) {
562 FreePool (Instance);
563 return Status;
564 }
565
566 Instance->Handle = *ChildHandle;
567
568 //
569 // Open the Udp4 protocol BY_CHILD.
570 //
571 Status = gBS->OpenProtocol (
572 DhcpSb->UdpIo->UdpHandle,
573 &gEfiUdp4ProtocolGuid,
574 (VOID **)&Udp4,
575 gDhcp4DriverBinding.DriverBindingHandle,
576 Instance->Handle,
577 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
578 );
579 if (EFI_ERROR (Status)) {
580 gBS->UninstallMultipleProtocolInterfaces (
581 Instance->Handle,
582 &gEfiDhcp4ProtocolGuid,
583 &Instance->Dhcp4Protocol,
584 NULL
585 );
586
587 FreePool (Instance);
588 return Status;
589 }
590
591 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
592
593 InsertTailList (&DhcpSb->Children, &Instance->Link);
594 DhcpSb->NumChildren++;
595
596 gBS->RestoreTPL (OldTpl);
597
598 return EFI_SUCCESS;
599 }
600
601 /**
602 Destroys a child handle with a protocol installed on it.
603
604 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
605 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
606 last protocol on ChildHandle, then ChildHandle is destroyed.
607
608 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
609 @param ChildHandle Handle of the child to destroy
610
611 @retval EFI_SUCCESS The protocol was removed from ChildHandle.
612 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
613 @retval EFI_INVALID_PARAMETER Child handle is NULL.
614 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
615 because its services are being used.
616 @retval other The child handle was not destroyed
617
618 **/
619 EFI_STATUS
620 EFIAPI
621 Dhcp4ServiceBindingDestroyChild (
622 IN EFI_SERVICE_BINDING_PROTOCOL *This,
623 IN EFI_HANDLE ChildHandle
624 )
625 {
626 DHCP_SERVICE *DhcpSb;
627 DHCP_PROTOCOL *Instance;
628 EFI_DHCP4_PROTOCOL *Dhcp;
629 EFI_TPL OldTpl;
630 EFI_STATUS Status;
631
632 if ((This == NULL) || (ChildHandle == NULL)) {
633 return EFI_INVALID_PARAMETER;
634 }
635
636 //
637 // Retrieve the private context data structures
638 //
639 Status = gBS->OpenProtocol (
640 ChildHandle,
641 &gEfiDhcp4ProtocolGuid,
642 (VOID **)&Dhcp,
643 gDhcp4DriverBinding.DriverBindingHandle,
644 ChildHandle,
645 EFI_OPEN_PROTOCOL_GET_PROTOCOL
646 );
647
648 if (EFI_ERROR (Status)) {
649 return EFI_UNSUPPORTED;
650 }
651
652 Instance = DHCP_INSTANCE_FROM_THIS (Dhcp);
653 DhcpSb = DHCP_SERVICE_FROM_THIS (This);
654
655 if (Instance->Service != DhcpSb) {
656 return EFI_INVALID_PARAMETER;
657 }
658
659 //
660 // A child can be destroyed more than once. For example,
661 // Dhcp4DriverBindingStop will destroy all of its children.
662 // when caller driver is being stopped, it will destroy the
663 // dhcp child it opens.
664 //
665 if (Instance->InDestroy) {
666 return EFI_SUCCESS;
667 }
668
669 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
670 Instance->InDestroy = TRUE;
671
672 //
673 // Close the Udp4 protocol.
674 //
675 gBS->CloseProtocol (
676 DhcpSb->UdpIo->UdpHandle,
677 &gEfiUdp4ProtocolGuid,
678 gDhcp4DriverBinding.DriverBindingHandle,
679 ChildHandle
680 );
681
682 //
683 // Uninstall the DHCP4 protocol first to enable a top down destruction.
684 //
685 gBS->RestoreTPL (OldTpl);
686 Status = gBS->UninstallProtocolInterface (
687 ChildHandle,
688 &gEfiDhcp4ProtocolGuid,
689 Dhcp
690 );
691 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
692 if (EFI_ERROR (Status)) {
693 Instance->InDestroy = FALSE;
694
695 gBS->RestoreTPL (OldTpl);
696 return Status;
697 }
698
699 if (DhcpSb->ActiveChild == Instance) {
700 DhcpYieldControl (DhcpSb);
701 }
702
703 RemoveEntryList (&Instance->Link);
704 DhcpSb->NumChildren--;
705
706 if (Instance->UdpIo != NULL) {
707 UdpIoCleanIo (Instance->UdpIo);
708 gBS->CloseProtocol (
709 Instance->UdpIo->UdpHandle,
710 &gEfiUdp4ProtocolGuid,
711 Instance->Service->Image,
712 Instance->Handle
713 );
714 UdpIoFreeIo (Instance->UdpIo);
715 Instance->UdpIo = NULL;
716 Instance->Token = NULL;
717 }
718
719 gBS->RestoreTPL (OldTpl);
720
721 FreePool (Instance);
722 return EFI_SUCCESS;
723 }