]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Driver.c
Scrubbed part of the code.
[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
f9204641 34EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplate = {\r
772db4bb 35 Dhcp4ServiceBindingCreateChild,\r
36 Dhcp4ServiceBindingDestroyChild\r
37};\r
38\r
7bce0c5a 39/**\r
f9204641 40 This is the declaration of an EFI image entry point. This entry point is\r
41 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
42 both device drivers and bus drivers.\r
43 \r
7bce0c5a 44 Entry point of the DHCP driver to install various protocols.\r
45\r
f9204641 46 @param ImageHandle The firmware allocated handle for the UEFI image.\r
47 @param SystemTable A pointer to the EFI System Table.\r
7bce0c5a 48\r
f9204641 49 @retval EFI_SUCCESS The operation completed successfully.\r
50 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
772db4bb 51\r
7bce0c5a 52**/\r
772db4bb 53EFI_STATUS\r
54EFIAPI\r
55Dhcp4DriverEntryPoint (\r
56 IN EFI_HANDLE ImageHandle,\r
57 IN EFI_SYSTEM_TABLE *SystemTable\r
58 )\r
772db4bb 59{\r
83cbd279 60 return EfiLibInstallDriverBindingComponentName2 (\r
772db4bb 61 ImageHandle,\r
62 SystemTable,\r
63 &gDhcp4DriverBinding,\r
64 ImageHandle,\r
65 &gDhcp4ComponentName,\r
83cbd279 66 &gDhcp4ComponentName2\r
772db4bb 67 );\r
68}\r
69\r
70\r
71/**\r
f9204641 72 Test to see if this driver supports ControllerHandle. This service\r
73 is called by the EFI boot service ConnectController(). In\r
74 order to make drivers as small as possible, there are a few calling\r
75 restrictions for this service. ConnectController() must\r
76 follow these calling restrictions. If any other agent wishes to call\r
77 Supported() it must also follow these calling restrictions.\r
78\r
79 @param This Protocol instance pointer.\r
80 @param ControllerHandle Handle of device to test\r
81 @param RemainingDevicePath Optional parameter use to pick a specific child\r
82 device to start.\r
83\r
84 @retval EFI_SUCCESS This driver supports this device\r
85 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
86 @retval other This driver does not support this device\r
772db4bb 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
e48e37fc 146 ZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));\r
147 ZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
148 ZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));\r
772db4bb 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
f9204641 157 or partly destroyed. If a resource is destroyed, it is marked as so in\r
158 case the destroy failed and being called again later.\r
772db4bb 159\r
160 @param DhcpSb The DHCP service instance to destory.\r
161\r
f9204641 162 @retval EFI_SUCCESS Always return success.\r
772db4bb 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
f9204641 200 @retval other Other error occurs.\r
772db4bb 201\r
202**/\r
203EFI_STATUS\r
204Dhcp4CreateService (\r
205 IN EFI_HANDLE Controller,\r
206 IN EFI_HANDLE ImageHandle,\r
207 OUT DHCP_SERVICE **Service\r
208 )\r
209{\r
210 DHCP_SERVICE *DhcpSb;\r
211 EFI_STATUS Status;\r
212\r
213 *Service = NULL;\r
e48e37fc 214 DhcpSb = AllocateZeroPool (sizeof (DHCP_SERVICE));\r
772db4bb 215\r
216 if (DhcpSb == NULL) {\r
217 return EFI_OUT_OF_RESOURCES;\r
218 }\r
219\r
220 DhcpSb->Signature = DHCP_SERVICE_SIGNATURE;\r
772db4bb 221 DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
222 DhcpSb->InDestory = FALSE;\r
223 DhcpSb->Controller = Controller;\r
224 DhcpSb->Image = ImageHandle;\r
e48e37fc 225 InitializeListHead (&DhcpSb->Children);\r
772db4bb 226 DhcpSb->DhcpState = Dhcp4Stopped;\r
227 DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ());\r
f9204641 228 CopyMem (\r
229 &DhcpSb->ServiceBinding,\r
230 &mDhcp4ServiceBindingTemplate,\r
231 sizeof (EFI_SERVICE_BINDING_PROTOCOL)\r
232 );\r
772db4bb 233 //\r
234 // Create various resources, UdpIo, Timer, and get Mac address\r
235 //\r
236 Status = gBS->CreateEvent (\r
237 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 238 TPL_CALLBACK,\r
772db4bb 239 DhcpOnTimerTick,\r
240 DhcpSb,\r
241 &DhcpSb->Timer\r
242 );\r
243\r
244 if (EFI_ERROR (Status)) {\r
245 goto ON_ERROR;\r
246 }\r
247\r
248 DhcpSb->UdpIo = UdpIoCreatePort (Controller, ImageHandle, DhcpConfigUdpIo, NULL);\r
249\r
250 if (DhcpSb->UdpIo == NULL) {\r
251 Status = EFI_OUT_OF_RESOURCES;\r
252 goto ON_ERROR;\r
253 }\r
254\r
255 DhcpSb->HwLen = (UINT8) DhcpSb->UdpIo->SnpMode.HwAddressSize;\r
256 DhcpSb->HwType = DhcpSb->UdpIo->SnpMode.IfType;\r
687a2e5f 257 CopyMem (&DhcpSb->Mac, &DhcpSb->UdpIo->SnpMode.CurrentAddress, sizeof (DhcpSb->Mac));\r
772db4bb 258\r
259 *Service = DhcpSb;\r
260 return EFI_SUCCESS;\r
261\r
262ON_ERROR:\r
263 Dhcp4CloseService (DhcpSb);\r
e48e37fc 264 gBS->FreePool (DhcpSb);\r
772db4bb 265\r
266 return Status;\r
267}\r
268\r
269\r
270/**\r
f9204641 271 Start this driver on ControllerHandle. This service is called by the\r
272 EFI boot service ConnectController(). In order to make\r
273 drivers as small as possible, there are a few calling restrictions for\r
274 this service. ConnectController() must follow these\r
275 calling restrictions. If any other agent wishes to call Start() it\r
276 must also follow these calling restrictions.\r
277\r
278 @param This Protocol instance pointer.\r
279 @param ControllerHandle Handle of device to bind driver to\r
280 @param RemainingDevicePath Optional parameter use to pick a specific child\r
281 device to start.\r
282\r
283 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
284 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
285 @retval other This driver does not support this device\r
772db4bb 286\r
287**/\r
288EFI_STATUS\r
289EFIAPI\r
290Dhcp4DriverBindingStart (\r
291 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
292 IN EFI_HANDLE ControllerHandle,\r
293 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
294 )\r
295{\r
296 DHCP_SERVICE *DhcpSb;\r
297 EFI_STATUS Status;\r
298\r
299 //\r
300 // First: test for the DHCP4 Protocol\r
301 //\r
302 Status = gBS->OpenProtocol (\r
303 ControllerHandle,\r
304 &gEfiDhcp4ServiceBindingProtocolGuid,\r
305 NULL,\r
306 This->DriverBindingHandle,\r
307 ControllerHandle,\r
308 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
309 );\r
310\r
311 if (Status == EFI_SUCCESS) {\r
312 return EFI_ALREADY_STARTED;\r
313 }\r
314\r
315 Status = Dhcp4CreateService (ControllerHandle, This->DriverBindingHandle, &DhcpSb);\r
316\r
317 if (EFI_ERROR (Status)) {\r
318 return Status;\r
319 }\r
320\r
321 Status = gBS->SetTimer (DhcpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
322\r
323 if (EFI_ERROR (Status)) {\r
324 goto ON_ERROR;\r
325 }\r
326\r
327 //\r
328 // Install the Dhcp4ServiceBinding Protocol onto ControlerHandle\r
329 //\r
330 Status = gBS->InstallMultipleProtocolInterfaces (\r
331 &ControllerHandle,\r
332 &gEfiDhcp4ServiceBindingProtocolGuid,\r
333 &DhcpSb->ServiceBinding,\r
334 NULL\r
335 );\r
336\r
337 if (EFI_ERROR (Status)) {\r
338 goto ON_ERROR;\r
339 }\r
340\r
341 return Status;\r
342\r
343ON_ERROR:\r
344 Dhcp4CloseService (DhcpSb);\r
e48e37fc 345 gBS->FreePool (DhcpSb);\r
772db4bb 346 return Status;\r
347}\r
348\r
349\r
350/**\r
f9204641 351 Stop this driver on ControllerHandle. This service is called by the\r
352 EFI boot service DisconnectController(). In order to\r
353 make drivers as small as possible, there are a few calling\r
354 restrictions for this service. DisconnectController()\r
355 must follow these calling restrictions. If any other agent wishes\r
356 to call Stop() it must also follow these calling restrictions.\r
357 \r
358 @param This Protocol instance pointer.\r
359 @param ControllerHandle Handle of device to stop driver on\r
360 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
361 children is zero stop the entire bus driver.\r
362 @param ChildHandleBuffer List of Child Handles to Stop.\r
363\r
364 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
365 @retval other This driver was not removed from this device\r
772db4bb 366\r
367**/\r
368EFI_STATUS\r
369EFIAPI\r
370Dhcp4DriverBindingStop (\r
371 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
372 IN EFI_HANDLE ControllerHandle,\r
373 IN UINTN NumberOfChildren,\r
374 IN EFI_HANDLE *ChildHandleBuffer\r
375 )\r
376{\r
377 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
378 DHCP_SERVICE *DhcpSb;\r
379 DHCP_PROTOCOL *Instance;\r
380 EFI_HANDLE NicHandle;\r
381 EFI_STATUS Status;\r
382 EFI_TPL OldTpl;\r
383\r
384 //\r
385 // DHCP driver opens UDP child, So, the ControllerHandle is the\r
386 // UDP child handle. locate the Nic handle first.\r
387 //\r
388 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);\r
389\r
390 if (NicHandle == NULL) {\r
c4a62a12 391 return EFI_DEVICE_ERROR;\r
772db4bb 392 }\r
393\r
394 Status = gBS->OpenProtocol (\r
395 NicHandle,\r
396 &gEfiDhcp4ServiceBindingProtocolGuid,\r
397 (VOID **) &ServiceBinding,\r
398 This->DriverBindingHandle,\r
399 NicHandle,\r
400 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
401 );\r
402\r
403 if (EFI_ERROR (Status)) {\r
404 return EFI_DEVICE_ERROR;\r
405 }\r
406\r
407 DhcpSb = DHCP_SERVICE_FROM_THIS (ServiceBinding);\r
408\r
409 if (DhcpSb->InDestory) {\r
410 return EFI_SUCCESS;\r
411 }\r
412\r
e48e37fc 413 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 414\r
c4a62a12 415 if (NumberOfChildren == 0) {\r
772db4bb 416\r
c4a62a12 417 DhcpSb->InDestory = TRUE;\r
418 DhcpSb->ServiceState = DHCP_DESTORY;\r
772db4bb 419\r
c4a62a12 420 gBS->UninstallProtocolInterface (\r
421 NicHandle,\r
422 &gEfiDhcp4ServiceBindingProtocolGuid,\r
423 ServiceBinding\r
424 );\r
772db4bb 425\r
c4a62a12 426 Dhcp4CloseService (DhcpSb);\r
427\r
e48e37fc 428 gBS->FreePool (DhcpSb);\r
c4a62a12 429 } else {\r
430 //\r
431 // Don't use NET_LIST_FOR_EACH_SAFE here, Dhcp4ServiceBindingDestoryChild\r
432 // may cause other child to be deleted.\r
433 //\r
e48e37fc 434 while (!IsListEmpty (&DhcpSb->Children)) {\r
c4a62a12 435 Instance = NET_LIST_HEAD (&DhcpSb->Children, DHCP_PROTOCOL, Link);\r
436 ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
437 }\r
438\r
439 if (DhcpSb->NumChildren != 0) {\r
440 Status = EFI_DEVICE_ERROR;\r
441 }\r
772db4bb 442 }\r
443\r
e48e37fc 444 gBS->RestoreTPL (OldTpl);\r
772db4bb 445\r
772db4bb 446 return Status;\r
447}\r
448\r
449\r
450/**\r
f9204641 451 Initialize a new DHCP instance.\r
772db4bb 452\r
453 @param DhcpSb The dhcp service instance\r
454 @param Instance The dhcp instance to initialize\r
455\r
456 @return None\r
457\r
458**/\r
459VOID\r
460DhcpInitProtocol (\r
f9204641 461 IN DHCP_SERVICE *DhcpSb,\r
462 IN OUT DHCP_PROTOCOL *Instance\r
772db4bb 463 )\r
464{\r
465 Instance->Signature = DHCP_PROTOCOL_SIGNATURE;\r
687a2e5f 466 CopyMem (&Instance->Dhcp4Protocol, &mDhcp4ProtocolTemplate, sizeof (Instance->Dhcp4Protocol));\r
e48e37fc 467 InitializeListHead (&Instance->Link);\r
772db4bb 468 Instance->Handle = NULL;\r
469 Instance->Service = DhcpSb;\r
470 Instance->InDestory = FALSE;\r
471 Instance->CompletionEvent = NULL;\r
472 Instance->RenewRebindEvent = NULL;\r
473 Instance->Token = NULL;\r
c4a62a12 474 Instance->UdpIo = NULL;\r
475 NetbufQueInit (&Instance->ResponseQueue);\r
772db4bb 476}\r
477\r
478\r
479/**\r
f9204641 480 Creates a child handle with a set of I/O services.\r
772db4bb 481\r
f9204641 482 @param This Protocol instance pointer.\r
483 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
484 then a new handle is created. If it is not NULL, then the\r
485 I/O services are added to the existing child handle.\r
772db4bb 486\r
f9204641 487 @retval EFI_SUCCES The child handle was created with the I/O services\r
488 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
489 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
490 the child\r
491 @retval other The child handle was not created\r
772db4bb 492\r
493**/\r
494EFI_STATUS\r
495EFIAPI\r
496Dhcp4ServiceBindingCreateChild (\r
497 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
498 IN EFI_HANDLE *ChildHandle\r
499 )\r
500{\r
501 DHCP_SERVICE *DhcpSb;\r
502 DHCP_PROTOCOL *Instance;\r
503 EFI_STATUS Status;\r
504 EFI_TPL OldTpl;\r
505 VOID *Udp4;\r
506\r
507 if ((This == NULL) || (ChildHandle == NULL)) {\r
508 return EFI_INVALID_PARAMETER;\r
509 }\r
510\r
e48e37fc 511 Instance = AllocatePool (sizeof (*Instance));\r
772db4bb 512\r
513 if (Instance == NULL) {\r
514 return EFI_OUT_OF_RESOURCES;\r
515 }\r
516\r
517 DhcpSb = DHCP_SERVICE_FROM_THIS (This);\r
518 DhcpInitProtocol (DhcpSb, Instance);\r
519\r
520 //\r
521 // Install DHCP4 onto ChildHandle\r
522 //\r
523 Status = gBS->InstallMultipleProtocolInterfaces (\r
524 ChildHandle,\r
525 &gEfiDhcp4ProtocolGuid,\r
526 &Instance->Dhcp4Protocol,\r
527 NULL\r
528 );\r
529\r
530 if (EFI_ERROR (Status)) {\r
e48e37fc 531 gBS->FreePool (Instance);\r
772db4bb 532 return Status;\r
533 }\r
534\r
535 Instance->Handle = *ChildHandle;\r
536\r
537 //\r
538 // Open the Udp4 protocol BY_CHILD.\r
539 //\r
540 Status = gBS->OpenProtocol (\r
541 DhcpSb->UdpIo->UdpHandle,\r
542 &gEfiUdp4ProtocolGuid,\r
543 (VOID **) &Udp4,\r
544 gDhcp4DriverBinding.DriverBindingHandle,\r
545 Instance->Handle,\r
546 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
547 );\r
548 if (EFI_ERROR (Status)) {\r
549 gBS->UninstallMultipleProtocolInterfaces (\r
550 Instance->Handle,\r
551 &gEfiDhcp4ProtocolGuid,\r
552 &Instance->Dhcp4Protocol,\r
553 NULL\r
554 );\r
555\r
e48e37fc 556 gBS->FreePool (Instance);\r
772db4bb 557 return Status;\r
558 }\r
559\r
e48e37fc 560 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 561\r
e48e37fc 562 InsertTailList (&DhcpSb->Children, &Instance->Link);\r
772db4bb 563 DhcpSb->NumChildren++;\r
564\r
e48e37fc 565 gBS->RestoreTPL (OldTpl);\r
772db4bb 566\r
567 return EFI_SUCCESS;\r
568}\r
569\r
570\r
571/**\r
f9204641 572 Destroys a child handle with a set of I/O services.\r
772db4bb 573\r
f9204641 574 @param This Protocol instance pointer.\r
575 @param ChildHandle Handle of the child to destroy\r
772db4bb 576\r
f9204641 577 @retval EFI_SUCCES The I/O services were removed from the child handle\r
578 @retval EFI_UNSUPPORTED The child handle does not support the I/O services\r
579 that are being removed.\r
580 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.\r
581 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because its\r
582 I/O services are being used.\r
583 @retval other The child handle was not destroyed\r
772db4bb 584\r
585**/\r
586EFI_STATUS\r
587EFIAPI\r
588Dhcp4ServiceBindingDestroyChild (\r
589 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
590 IN EFI_HANDLE ChildHandle\r
591 )\r
592{\r
593 DHCP_SERVICE *DhcpSb;\r
594 DHCP_PROTOCOL *Instance;\r
595 EFI_DHCP4_PROTOCOL *Dhcp;\r
596 EFI_TPL OldTpl;\r
597 EFI_STATUS Status;\r
598\r
599 if ((This == NULL) || (ChildHandle == NULL)) {\r
600 return EFI_INVALID_PARAMETER;\r
601 }\r
602\r
603 //\r
604 // Retrieve the private context data structures\r
605 //\r
606 Status = gBS->OpenProtocol (\r
607 ChildHandle,\r
608 &gEfiDhcp4ProtocolGuid,\r
609 (VOID **) &Dhcp,\r
610 gDhcp4DriverBinding.DriverBindingHandle,\r
611 ChildHandle,\r
612 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
613 );\r
614\r
615 if (EFI_ERROR (Status)) {\r
616 return EFI_UNSUPPORTED;\r
617 }\r
618\r
619 Instance = DHCP_INSTANCE_FROM_THIS (Dhcp);\r
620 DhcpSb = DHCP_SERVICE_FROM_THIS (This);\r
621\r
622 if (Instance->Service != DhcpSb) {\r
623 return EFI_INVALID_PARAMETER;\r
624 }\r
625\r
626 //\r
f9204641 627 // A child can be destroyed more than once. For example,\r
628 // Dhcp4DriverBindingStop will destroy all of its children.\r
772db4bb 629 // when caller driver is being stopped, it will destory the\r
630 // dhcp child it opens.\r
631 //\r
632 if (Instance->InDestory) {\r
633 return EFI_SUCCESS;\r
634 }\r
635\r
e48e37fc 636 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 637 Instance->InDestory = TRUE;\r
638\r
639 //\r
640 // Close the Udp4 protocol.\r
641 //\r
642 gBS->CloseProtocol (\r
643 DhcpSb->UdpIo->UdpHandle,\r
644 &gEfiUdp4ProtocolGuid,\r
645 gDhcp4DriverBinding.DriverBindingHandle,\r
646 ChildHandle\r
647 );\r
648\r
649 //\r
650 // Uninstall the DHCP4 protocol first to enable a top down destruction.\r
651 //\r
652 Status = gBS->UninstallProtocolInterface (\r
653 ChildHandle,\r
654 &gEfiDhcp4ProtocolGuid,\r
655 Dhcp\r
656 );\r
657\r
658 if (EFI_ERROR (Status)) {\r
659 Instance->InDestory = FALSE;\r
660\r
e48e37fc 661 gBS->RestoreTPL (OldTpl);\r
772db4bb 662 return Status;\r
663 }\r
664\r
665 if (DhcpSb->ActiveChild == Instance) {\r
666 DhcpYieldControl (DhcpSb);\r
667 }\r
668\r
e48e37fc 669 RemoveEntryList (&Instance->Link);\r
772db4bb 670 DhcpSb->NumChildren--;\r
671\r
e48e37fc 672 gBS->RestoreTPL (OldTpl);\r
772db4bb 673\r
e48e37fc 674 gBS->FreePool (Instance);\r
772db4bb 675 return EFI_SUCCESS;\r
676}\r