]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.c
1. Fix a bug in PXE driver that the PXE boot do not restart if a new boot option...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Mtftp4Dxe / Mtftp4Driver.c
CommitLineData
772db4bb 1/** @file\r
dab714aa 2 Implementation of Mtftp drivers.\r
e2851998 3\r
75dce340 4Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
772db4bb 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
dab714aa 8http://opensource.org/licenses/bsd-license.php<BR>\r
772db4bb 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
772db4bb 13**/\r
14\r
15#include "Mtftp4Impl.h"\r
16\r
17EFI_DRIVER_BINDING_PROTOCOL gMtftp4DriverBinding = {\r
18 Mtftp4DriverBindingSupported,\r
19 Mtftp4DriverBindingStart,\r
20 Mtftp4DriverBindingStop,\r
21 0xa,\r
22 NULL,\r
23 NULL\r
24};\r
25\r
26EFI_SERVICE_BINDING_PROTOCOL gMtftp4ServiceBindingTemplete = {\r
27 Mtftp4ServiceBindingCreateChild,\r
28 Mtftp4ServiceBindingDestroyChild\r
29};\r
30\r
dab714aa 31\r
32/**\r
33 The driver entry point which installs multiple protocols to the ImageHandle.\r
34\r
35 @param ImageHandle The MTFTP's image handle.\r
36 @param SystemTable The system table.\r
37\r
e2851998 38 @retval EFI_SUCCESS The handles are successfully installed on the image.\r
dab714aa 39 @retval others some EFI_ERROR occured.\r
40\r
41**/\r
772db4bb 42EFI_STATUS\r
43EFIAPI\r
44Mtftp4DriverEntryPoint (\r
45 IN EFI_HANDLE ImageHandle,\r
46 IN EFI_SYSTEM_TABLE *SystemTable\r
47 )\r
772db4bb 48{\r
83cbd279 49 return EfiLibInstallDriverBindingComponentName2 (\r
772db4bb 50 ImageHandle,\r
51 SystemTable,\r
52 &gMtftp4DriverBinding,\r
53 ImageHandle,\r
54 &gMtftp4ComponentName,\r
83cbd279 55 &gMtftp4ComponentName2\r
772db4bb 56 );\r
57}\r
58\r
59\r
60/**\r
61 Test whether MTFTP driver support this controller.\r
62\r
63 @param This The MTFTP driver binding instance\r
64 @param Controller The controller to test\r
65 @param RemainingDevicePath The remaining device path\r
66\r
67 @retval EFI_SUCCESS The controller has UDP service binding protocol\r
68 installed, MTFTP can support it.\r
5be56d99 69 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
e2851998 70 RemainingDevicePath is already being managed by\r
5be56d99 71 the driver specified by This.\r
72 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
e2851998 73 RemainingDevicePath is already being managed by a\r
74 different driver or an application that requires\r
5be56d99 75 exclusive access.\r
76 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
e2851998 77 RemainingDevicePath is not supported by the driver\r
5be56d99 78 specified by This.\r
772db4bb 79\r
80**/\r
81EFI_STATUS\r
dab714aa 82EFIAPI\r
772db4bb 83Mtftp4DriverBindingSupported (\r
84 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
85 IN EFI_HANDLE Controller,\r
86 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
87 )\r
88{\r
89 EFI_STATUS Status;\r
90\r
91 Status = gBS->OpenProtocol (\r
92 Controller,\r
93 &gEfiUdp4ServiceBindingProtocolGuid,\r
94 NULL,\r
95 This->DriverBindingHandle,\r
96 Controller,\r
97 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
98 );\r
99\r
100 return Status;\r
101}\r
102\r
103\r
104/**\r
e2851998 105 Config a NULL UDP that is used to keep the connection between UDP and MTFTP.\r
106\r
107 Just leave the Udp child unconfigured. When UDP is unloaded,\r
dab714aa 108 MTFTP will be informed with DriverBinding Stop.\r
772db4bb 109\r
b45b45b2 110 @param UdpIo The UDP_IO to configure\r
772db4bb 111 @param Context The opaque parameter to the callback\r
112\r
113 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.\r
114\r
115**/\r
116EFI_STATUS\r
e798cd87 117EFIAPI\r
772db4bb 118Mtftp4ConfigNullUdp (\r
b45b45b2 119 IN UDP_IO *UdpIo,\r
772db4bb 120 IN VOID *Context\r
121 )\r
122{\r
123 return EFI_SUCCESS;\r
124}\r
125\r
126\r
127/**\r
128 Create then initialize a MTFTP service binding instance.\r
129\r
130 @param Controller The controller to install the MTFTP service\r
131 binding on\r
132 @param Image The driver binding image of the MTFTP driver\r
133 @param Service The variable to receive the created service\r
134 binding instance.\r
135\r
136 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance\r
137 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep\r
138 connection with UDP.\r
139 @retval EFI_SUCCESS The service instance is created for the\r
140 controller.\r
141\r
142**/\r
143EFI_STATUS\r
144Mtftp4CreateService (\r
dab714aa 145 IN EFI_HANDLE Controller,\r
146 IN EFI_HANDLE Image,\r
147 OUT MTFTP4_SERVICE **Service\r
772db4bb 148 )\r
149{\r
150 MTFTP4_SERVICE *MtftpSb;\r
151 EFI_STATUS Status;\r
152\r
153 *Service = NULL;\r
e48e37fc 154 MtftpSb = AllocatePool (sizeof (MTFTP4_SERVICE));\r
772db4bb 155\r
156 if (MtftpSb == NULL) {\r
157 return EFI_OUT_OF_RESOURCES;\r
158 }\r
159\r
160 MtftpSb->Signature = MTFTP4_SERVICE_SIGNATURE;\r
161 MtftpSb->ServiceBinding = gMtftp4ServiceBindingTemplete;\r
75dce340 162 MtftpSb->InDestroy = FALSE;\r
772db4bb 163 MtftpSb->ChildrenNum = 0;\r
e48e37fc 164 InitializeListHead (&MtftpSb->Children);\r
772db4bb 165\r
166 MtftpSb->Timer = NULL;\r
167 MtftpSb->TimerToGetMap = NULL;\r
168 MtftpSb->Controller = Controller;\r
169 MtftpSb->Image = Image;\r
170 MtftpSb->ConnectUdp = NULL;\r
171\r
172 //\r
173 // Create the timer and a udp to be notified when UDP is uninstalled\r
174 //\r
175 Status = gBS->CreateEvent (\r
176 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 177 TPL_CALLBACK,\r
772db4bb 178 Mtftp4OnTimerTick,\r
179 MtftpSb,\r
180 &MtftpSb->Timer\r
181 );\r
182\r
183 if (EFI_ERROR (Status)) {\r
766c7483 184 FreePool (MtftpSb);\r
772db4bb 185 return Status;\r
186 }\r
187\r
188 //\r
189 // Create the timer used to time out the procedure which is used to\r
190 // get the default IP address.\r
191 //\r
192 Status = gBS->CreateEvent (\r
193 EVT_TIMER,\r
e48e37fc 194 TPL_CALLBACK,\r
772db4bb 195 NULL,\r
196 NULL,\r
197 &MtftpSb->TimerToGetMap\r
198 );\r
199 if (EFI_ERROR (Status)) {\r
200 gBS->CloseEvent (MtftpSb->Timer);\r
766c7483 201 FreePool (MtftpSb);\r
772db4bb 202 return Status;\r
203 }\r
204\r
b45b45b2 205 MtftpSb->ConnectUdp = UdpIoCreateIo (\r
206 Controller,\r
207 Image,\r
208 Mtftp4ConfigNullUdp,\r
209 UDP_IO_UDP4_VERSION,\r
210 NULL\r
211 );\r
772db4bb 212\r
213 if (MtftpSb->ConnectUdp == NULL) {\r
214 gBS->CloseEvent (MtftpSb->TimerToGetMap);\r
215 gBS->CloseEvent (MtftpSb->Timer);\r
766c7483 216 FreePool (MtftpSb);\r
772db4bb 217 return EFI_DEVICE_ERROR;\r
218 }\r
219\r
220 *Service = MtftpSb;\r
221 return EFI_SUCCESS;\r
222}\r
223\r
224\r
225/**\r
226 Release all the resource used the MTFTP service binding instance.\r
227\r
228 @param MtftpSb The MTFTP service binding instance.\r
229\r
772db4bb 230**/\r
231VOID\r
232Mtftp4CleanService (\r
233 IN MTFTP4_SERVICE *MtftpSb\r
234 )\r
235{\r
b45b45b2 236 UdpIoFreeIo (MtftpSb->ConnectUdp);\r
772db4bb 237 gBS->CloseEvent (MtftpSb->TimerToGetMap);\r
238 gBS->CloseEvent (MtftpSb->Timer);\r
239}\r
240\r
241\r
242/**\r
e2851998 243 Start the MTFTP driver on this controller.\r
244\r
dab714aa 245 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported\r
772db4bb 246 controller, which can be used to create/destroy MTFTP children.\r
247\r
248 @param This The MTFTP driver binding protocol.\r
249 @param Controller The controller to manage.\r
250 @param RemainingDevicePath Remaining device path.\r
251\r
252 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been\r
253 started on the controller.\r
254 @retval EFI_SUCCESS The MTFTP service binding is installed on the\r
255 controller.\r
256\r
257**/\r
258EFI_STATUS\r
dab714aa 259EFIAPI\r
772db4bb 260Mtftp4DriverBindingStart (\r
261 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
262 IN EFI_HANDLE Controller,\r
263 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
264 )\r
265{\r
266 MTFTP4_SERVICE *MtftpSb;\r
267 EFI_STATUS Status;\r
268\r
269 //\r
270 // Directly return if driver is already running.\r
271 //\r
272 Status = gBS->OpenProtocol (\r
273 Controller,\r
274 &gEfiMtftp4ServiceBindingProtocolGuid,\r
275 NULL,\r
276 This->DriverBindingHandle,\r
277 Controller,\r
278 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
279 );\r
280\r
281 if (Status == EFI_SUCCESS) {\r
282 return EFI_ALREADY_STARTED;\r
283 }\r
284\r
285 Status = Mtftp4CreateService (Controller, This->DriverBindingHandle, &MtftpSb);\r
286\r
287 if (EFI_ERROR (Status)) {\r
288 return Status;\r
289 }\r
e2851998 290 ASSERT (MtftpSb != NULL);\r
772db4bb 291\r
292 Status = gBS->SetTimer (MtftpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
293\r
294 if (EFI_ERROR (Status)) {\r
295 goto ON_ERROR;\r
296 }\r
297\r
298 //\r
299 // Install the Mtftp4ServiceBinding Protocol onto Controller\r
300 //\r
301 Status = gBS->InstallMultipleProtocolInterfaces (\r
302 &Controller,\r
303 &gEfiMtftp4ServiceBindingProtocolGuid,\r
304 &MtftpSb->ServiceBinding,\r
305 NULL\r
306 );\r
307\r
308 if (EFI_ERROR (Status)) {\r
309 goto ON_ERROR;\r
310 }\r
311\r
312 return EFI_SUCCESS;\r
313\r
314ON_ERROR:\r
315 Mtftp4CleanService (MtftpSb);\r
766c7483 316 FreePool (MtftpSb);\r
772db4bb 317\r
318 return Status;\r
319}\r
320\r
321\r
322/**\r
323 Stop the MTFTP driver on controller. The controller is a UDP\r
324 child handle.\r
325\r
326 @param This The MTFTP driver binding protocol\r
327 @param Controller The controller to stop\r
328 @param NumberOfChildren The number of children\r
329 @param ChildHandleBuffer The array of the child handle.\r
330\r
331 @retval EFI_SUCCESS The driver is stopped on the controller.\r
332 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.\r
333\r
334**/\r
335EFI_STATUS\r
dab714aa 336EFIAPI\r
772db4bb 337Mtftp4DriverBindingStop (\r
dab714aa 338 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
339 IN EFI_HANDLE Controller,\r
340 IN UINTN NumberOfChildren,\r
341 IN EFI_HANDLE *ChildHandleBuffer\r
772db4bb 342 )\r
343{\r
344 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
345 MTFTP4_SERVICE *MtftpSb;\r
346 MTFTP4_PROTOCOL *Instance;\r
347 EFI_HANDLE NicHandle;\r
348 EFI_STATUS Status;\r
349 EFI_TPL OldTpl;\r
350\r
351 //\r
352 // MTFTP driver opens UDP child, So, Controller is a UDP\r
353 // child handle. Locate the Nic handle first. Then get the\r
354 // MTFTP private data back.\r
355 //\r
356 NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid);\r
357\r
358 if (NicHandle == NULL) {\r
c4a62a12 359 return EFI_DEVICE_ERROR;\r
772db4bb 360 }\r
361\r
362 Status = gBS->OpenProtocol (\r
363 NicHandle,\r
364 &gEfiMtftp4ServiceBindingProtocolGuid,\r
365 (VOID **) &ServiceBinding,\r
366 This->DriverBindingHandle,\r
367 NicHandle,\r
368 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
369 );\r
370\r
371 if (EFI_ERROR (Status)) {\r
372 return EFI_DEVICE_ERROR;\r
373 }\r
374\r
375 MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding);\r
376\r
75dce340 377 if (MtftpSb->InDestroy) {\r
772db4bb 378 return EFI_SUCCESS;\r
379 }\r
380\r
e48e37fc 381 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 382\r
c4a62a12 383 if (NumberOfChildren == 0) {\r
772db4bb 384\r
75dce340 385 MtftpSb->InDestroy = TRUE;\r
772db4bb 386\r
c4a62a12 387 gBS->UninstallProtocolInterface (\r
388 NicHandle,\r
389 &gEfiMtftp4ServiceBindingProtocolGuid,\r
390 ServiceBinding\r
391 );\r
772db4bb 392\r
c4a62a12 393 Mtftp4CleanService (MtftpSb);\r
772db4bb 394\r
766c7483 395 FreePool (MtftpSb);\r
c4a62a12 396 } else {\r
772db4bb 397\r
e48e37fc 398 while (!IsListEmpty (&MtftpSb->Children)) {\r
c4a62a12 399 Instance = NET_LIST_HEAD (&MtftpSb->Children, MTFTP4_PROTOCOL, Link);\r
400 Mtftp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);\r
401 }\r
772db4bb 402\r
c4a62a12 403 if (MtftpSb->ChildrenNum != 0) {\r
404 Status = EFI_DEVICE_ERROR;\r
405 }\r
406 }\r
772db4bb 407\r
e48e37fc 408 gBS->RestoreTPL (OldTpl);\r
772db4bb 409 return Status;\r
410}\r
411\r
412\r
413/**\r
414 Initialize a MTFTP protocol instance which is the child of MtftpSb.\r
415\r
416 @param MtftpSb The MTFTP service binding protocol.\r
417 @param Instance The MTFTP instance to initialize.\r
418\r
772db4bb 419**/\r
420VOID\r
421Mtftp4InitProtocol (\r
dab714aa 422 IN MTFTP4_SERVICE *MtftpSb,\r
423 OUT MTFTP4_PROTOCOL *Instance\r
772db4bb 424 )\r
425{\r
e48e37fc 426 ZeroMem (Instance, sizeof (MTFTP4_PROTOCOL));\r
772db4bb 427\r
428 Instance->Signature = MTFTP4_PROTOCOL_SIGNATURE;\r
e48e37fc 429 InitializeListHead (&Instance->Link);\r
687a2e5f 430 CopyMem (&Instance->Mtftp4, &gMtftp4ProtocolTemplate, sizeof (Instance->Mtftp4));\r
772db4bb 431 Instance->State = MTFTP4_STATE_UNCONFIGED;\r
75dce340 432 Instance->InDestroy = FALSE;\r
772db4bb 433 Instance->Service = MtftpSb;\r
434\r
e48e37fc 435 InitializeListHead (&Instance->Blocks);\r
772db4bb 436}\r
437\r
438\r
439/**\r
440 Create a MTFTP child for the service binding instance, then\r
441 install the MTFTP protocol to the ChildHandle.\r
442\r
443 @param This The MTFTP service binding instance.\r
444 @param ChildHandle The Child handle to install the MTFTP protocol.\r
445\r
446 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
447 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.\r
448 @retval EFI_SUCCESS The child is successfully create.\r
449\r
450**/\r
451EFI_STATUS\r
dab714aa 452EFIAPI\r
772db4bb 453Mtftp4ServiceBindingCreateChild (\r
454 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
dab714aa 455 IN EFI_HANDLE *ChildHandle\r
772db4bb 456 )\r
457{\r
458 MTFTP4_SERVICE *MtftpSb;\r
459 MTFTP4_PROTOCOL *Instance;\r
460 EFI_STATUS Status;\r
461 EFI_TPL OldTpl;\r
462 VOID *Udp4;\r
463\r
464 if ((This == NULL) || (ChildHandle == NULL)) {\r
465 return EFI_INVALID_PARAMETER;\r
466 }\r
467\r
e48e37fc 468 Instance = AllocatePool (sizeof (*Instance));\r
772db4bb 469\r
470 if (Instance == NULL) {\r
471 return EFI_OUT_OF_RESOURCES;\r
472 }\r
473\r
474 MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);\r
475\r
476 Mtftp4InitProtocol (MtftpSb, Instance);\r
477\r
b45b45b2 478 Instance->UnicastPort = UdpIoCreateIo (\r
772db4bb 479 MtftpSb->Controller,\r
480 MtftpSb->Image,\r
481 Mtftp4ConfigNullUdp,\r
b45b45b2 482 UDP_IO_UDP4_VERSION,\r
772db4bb 483 Instance\r
484 );\r
485\r
486 if (Instance->UnicastPort == NULL) {\r
766c7483 487 FreePool (Instance);\r
772db4bb 488 return EFI_OUT_OF_RESOURCES;\r
489 }\r
490\r
491 //\r
492 // Install the MTFTP protocol onto ChildHandle\r
493 //\r
494 Status = gBS->InstallMultipleProtocolInterfaces (\r
495 ChildHandle,\r
496 &gEfiMtftp4ProtocolGuid,\r
497 &Instance->Mtftp4,\r
498 NULL\r
499 );\r
500\r
501 if (EFI_ERROR (Status)) {\r
502 goto ON_ERROR;\r
503 }\r
504\r
505 Instance->Handle = *ChildHandle;\r
506\r
507 //\r
508 // Open the Udp4 protocol BY_CHILD.\r
509 //\r
510 Status = gBS->OpenProtocol (\r
511 MtftpSb->ConnectUdp->UdpHandle,\r
512 &gEfiUdp4ProtocolGuid,\r
513 (VOID **) &Udp4,\r
514 gMtftp4DriverBinding.DriverBindingHandle,\r
515 Instance->Handle,\r
516 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
517 );\r
518 if (EFI_ERROR (Status)) {\r
519 gBS->UninstallMultipleProtocolInterfaces (\r
520 Instance->Handle,\r
521 &gEfiMtftp4ProtocolGuid,\r
522 &Instance->Mtftp4,\r
523 NULL\r
524 );\r
525\r
526 goto ON_ERROR;\r
527 }\r
528\r
529 //\r
530 // Add it to the parent's child list.\r
531 //\r
e48e37fc 532 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 533\r
e48e37fc 534 InsertTailList (&MtftpSb->Children, &Instance->Link);\r
772db4bb 535 MtftpSb->ChildrenNum++;\r
536\r
e48e37fc 537 gBS->RestoreTPL (OldTpl);\r
772db4bb 538\r
539ON_ERROR:\r
540\r
541 if (EFI_ERROR (Status)) {\r
b45b45b2 542 UdpIoFreeIo (Instance->UnicastPort);\r
766c7483 543 FreePool (Instance);\r
772db4bb 544 }\r
545\r
546 return Status;\r
547}\r
548\r
549\r
550/**\r
75dce340 551 Destroy one of the service binding's child.\r
772db4bb 552\r
553 @param This The service binding instance\r
75dce340 554 @param ChildHandle The child handle to destroy\r
772db4bb 555\r
556 @retval EFI_INVALID_PARAMETER The parameter is invaid.\r
75dce340 557 @retval EFI_UNSUPPORTED The child may have already been destroyed.\r
558 @retval EFI_SUCCESS The child is destroyed and removed from the\r
772db4bb 559 parent's child list.\r
560\r
561**/\r
562EFI_STATUS\r
dab714aa 563EFIAPI\r
772db4bb 564Mtftp4ServiceBindingDestroyChild (\r
565 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
566 IN EFI_HANDLE ChildHandle\r
567 )\r
568{\r
569 MTFTP4_SERVICE *MtftpSb;\r
570 MTFTP4_PROTOCOL *Instance;\r
571 EFI_MTFTP4_PROTOCOL *Mtftp4;\r
572 EFI_STATUS Status;\r
573 EFI_TPL OldTpl;\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 &gEfiMtftp4ProtocolGuid,\r
585 (VOID **) &Mtftp4,\r
586 gMtftp4DriverBinding.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 = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4);\r
596 MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);\r
597\r
598 if (Instance->Service != MtftpSb) {\r
599 return EFI_INVALID_PARAMETER;\r
600 }\r
601\r
75dce340 602 if (Instance->InDestroy) {\r
772db4bb 603 return EFI_SUCCESS;\r
604 }\r
605\r
75dce340 606 Instance->InDestroy = TRUE;\r
772db4bb 607\r
608 //\r
609 // Close the Udp4 protocol.\r
610 //\r
611 gBS->CloseProtocol (\r
612 MtftpSb->ConnectUdp->UdpHandle,\r
613 &gEfiUdp4ProtocolGuid,\r
614 gMtftp4DriverBinding.DriverBindingHandle,\r
615 ChildHandle\r
616 );\r
617\r
618 //\r
619 // Uninstall the MTFTP4 protocol first to enable a top down destruction.\r
620 //\r
621 Status = gBS->UninstallProtocolInterface (\r
622 ChildHandle,\r
623 &gEfiMtftp4ProtocolGuid,\r
624 Mtftp4\r
625 );\r
626\r
627 if (EFI_ERROR (Status)) {\r
75dce340 628 Instance->InDestroy = FALSE;\r
772db4bb 629 return Status;\r
630 }\r
631\r
e48e37fc 632 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 633\r
634 Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);\r
b45b45b2 635 UdpIoFreeIo (Instance->UnicastPort);\r
772db4bb 636\r
e48e37fc 637 RemoveEntryList (&Instance->Link);\r
772db4bb 638 MtftpSb->ChildrenNum--;\r
639\r
e48e37fc 640 gBS->RestoreTPL (OldTpl);\r
772db4bb 641\r
766c7483 642 FreePool (Instance);\r
772db4bb 643 return EFI_SUCCESS;\r
644}\r