]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.c
Fixed GCC 4.4 build issue. All protocols and public interfaces must specify EFIAPI...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Mtftp4Dxe / Mtftp4Driver.c
CommitLineData
772db4bb 1/** @file\r
dab714aa 2 Implementation of Mtftp drivers.\r
e2851998 3\r
4Copyright (c) 2006 - 2010, Intel Corporation<BR>\r
772db4bb 5All rights reserved. This program and the accompanying materials\r
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
117Mtftp4ConfigNullUdp (\r
b45b45b2 118 IN UDP_IO *UdpIo,\r
772db4bb 119 IN VOID *Context\r
120 )\r
121{\r
122 return EFI_SUCCESS;\r
123}\r
124\r
125\r
126/**\r
127 Create then initialize a MTFTP service binding instance.\r
128\r
129 @param Controller The controller to install the MTFTP service\r
130 binding on\r
131 @param Image The driver binding image of the MTFTP driver\r
132 @param Service The variable to receive the created service\r
133 binding instance.\r
134\r
135 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance\r
136 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep\r
137 connection with UDP.\r
138 @retval EFI_SUCCESS The service instance is created for the\r
139 controller.\r
140\r
141**/\r
142EFI_STATUS\r
143Mtftp4CreateService (\r
dab714aa 144 IN EFI_HANDLE Controller,\r
145 IN EFI_HANDLE Image,\r
146 OUT MTFTP4_SERVICE **Service\r
772db4bb 147 )\r
148{\r
149 MTFTP4_SERVICE *MtftpSb;\r
150 EFI_STATUS Status;\r
151\r
152 *Service = NULL;\r
e48e37fc 153 MtftpSb = AllocatePool (sizeof (MTFTP4_SERVICE));\r
772db4bb 154\r
155 if (MtftpSb == NULL) {\r
156 return EFI_OUT_OF_RESOURCES;\r
157 }\r
158\r
159 MtftpSb->Signature = MTFTP4_SERVICE_SIGNATURE;\r
160 MtftpSb->ServiceBinding = gMtftp4ServiceBindingTemplete;\r
161 MtftpSb->InDestory = FALSE;\r
162 MtftpSb->ChildrenNum = 0;\r
e48e37fc 163 InitializeListHead (&MtftpSb->Children);\r
772db4bb 164\r
165 MtftpSb->Timer = NULL;\r
166 MtftpSb->TimerToGetMap = NULL;\r
167 MtftpSb->Controller = Controller;\r
168 MtftpSb->Image = Image;\r
169 MtftpSb->ConnectUdp = NULL;\r
170\r
171 //\r
172 // Create the timer and a udp to be notified when UDP is uninstalled\r
173 //\r
174 Status = gBS->CreateEvent (\r
175 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 176 TPL_CALLBACK,\r
772db4bb 177 Mtftp4OnTimerTick,\r
178 MtftpSb,\r
179 &MtftpSb->Timer\r
180 );\r
181\r
182 if (EFI_ERROR (Status)) {\r
766c7483 183 FreePool (MtftpSb);\r
772db4bb 184 return Status;\r
185 }\r
186\r
187 //\r
188 // Create the timer used to time out the procedure which is used to\r
189 // get the default IP address.\r
190 //\r
191 Status = gBS->CreateEvent (\r
192 EVT_TIMER,\r
e48e37fc 193 TPL_CALLBACK,\r
772db4bb 194 NULL,\r
195 NULL,\r
196 &MtftpSb->TimerToGetMap\r
197 );\r
198 if (EFI_ERROR (Status)) {\r
199 gBS->CloseEvent (MtftpSb->Timer);\r
766c7483 200 FreePool (MtftpSb);\r
772db4bb 201 return Status;\r
202 }\r
203\r
b45b45b2 204 MtftpSb->ConnectUdp = UdpIoCreateIo (\r
205 Controller,\r
206 Image,\r
207 Mtftp4ConfigNullUdp,\r
208 UDP_IO_UDP4_VERSION,\r
209 NULL\r
210 );\r
772db4bb 211\r
212 if (MtftpSb->ConnectUdp == NULL) {\r
213 gBS->CloseEvent (MtftpSb->TimerToGetMap);\r
214 gBS->CloseEvent (MtftpSb->Timer);\r
766c7483 215 FreePool (MtftpSb);\r
772db4bb 216 return EFI_DEVICE_ERROR;\r
217 }\r
218\r
219 *Service = MtftpSb;\r
220 return EFI_SUCCESS;\r
221}\r
222\r
223\r
224/**\r
225 Release all the resource used the MTFTP service binding instance.\r
226\r
227 @param MtftpSb The MTFTP service binding instance.\r
228\r
772db4bb 229**/\r
230VOID\r
231Mtftp4CleanService (\r
232 IN MTFTP4_SERVICE *MtftpSb\r
233 )\r
234{\r
b45b45b2 235 UdpIoFreeIo (MtftpSb->ConnectUdp);\r
772db4bb 236 gBS->CloseEvent (MtftpSb->TimerToGetMap);\r
237 gBS->CloseEvent (MtftpSb->Timer);\r
238}\r
239\r
240\r
241/**\r
e2851998 242 Start the MTFTP driver on this controller.\r
243\r
dab714aa 244 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported\r
772db4bb 245 controller, which can be used to create/destroy MTFTP children.\r
246\r
247 @param This The MTFTP driver binding protocol.\r
248 @param Controller The controller to manage.\r
249 @param RemainingDevicePath Remaining device path.\r
250\r
251 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been\r
252 started on the controller.\r
253 @retval EFI_SUCCESS The MTFTP service binding is installed on the\r
254 controller.\r
255\r
256**/\r
257EFI_STATUS\r
dab714aa 258EFIAPI\r
772db4bb 259Mtftp4DriverBindingStart (\r
260 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
261 IN EFI_HANDLE Controller,\r
262 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
263 )\r
264{\r
265 MTFTP4_SERVICE *MtftpSb;\r
266 EFI_STATUS Status;\r
267\r
268 //\r
269 // Directly return if driver is already running.\r
270 //\r
271 Status = gBS->OpenProtocol (\r
272 Controller,\r
273 &gEfiMtftp4ServiceBindingProtocolGuid,\r
274 NULL,\r
275 This->DriverBindingHandle,\r
276 Controller,\r
277 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
278 );\r
279\r
280 if (Status == EFI_SUCCESS) {\r
281 return EFI_ALREADY_STARTED;\r
282 }\r
283\r
284 Status = Mtftp4CreateService (Controller, This->DriverBindingHandle, &MtftpSb);\r
285\r
286 if (EFI_ERROR (Status)) {\r
287 return Status;\r
288 }\r
e2851998 289 ASSERT (MtftpSb != NULL);\r
772db4bb 290\r
291 Status = gBS->SetTimer (MtftpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
292\r
293 if (EFI_ERROR (Status)) {\r
294 goto ON_ERROR;\r
295 }\r
296\r
297 //\r
298 // Install the Mtftp4ServiceBinding Protocol onto Controller\r
299 //\r
300 Status = gBS->InstallMultipleProtocolInterfaces (\r
301 &Controller,\r
302 &gEfiMtftp4ServiceBindingProtocolGuid,\r
303 &MtftpSb->ServiceBinding,\r
304 NULL\r
305 );\r
306\r
307 if (EFI_ERROR (Status)) {\r
308 goto ON_ERROR;\r
309 }\r
310\r
311 return EFI_SUCCESS;\r
312\r
313ON_ERROR:\r
314 Mtftp4CleanService (MtftpSb);\r
766c7483 315 FreePool (MtftpSb);\r
772db4bb 316\r
317 return Status;\r
318}\r
319\r
320\r
321/**\r
322 Stop the MTFTP driver on controller. The controller is a UDP\r
323 child handle.\r
324\r
325 @param This The MTFTP driver binding protocol\r
326 @param Controller The controller to stop\r
327 @param NumberOfChildren The number of children\r
328 @param ChildHandleBuffer The array of the child handle.\r
329\r
330 @retval EFI_SUCCESS The driver is stopped on the controller.\r
331 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.\r
332\r
333**/\r
334EFI_STATUS\r
dab714aa 335EFIAPI\r
772db4bb 336Mtftp4DriverBindingStop (\r
dab714aa 337 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
338 IN EFI_HANDLE Controller,\r
339 IN UINTN NumberOfChildren,\r
340 IN EFI_HANDLE *ChildHandleBuffer\r
772db4bb 341 )\r
342{\r
343 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
344 MTFTP4_SERVICE *MtftpSb;\r
345 MTFTP4_PROTOCOL *Instance;\r
346 EFI_HANDLE NicHandle;\r
347 EFI_STATUS Status;\r
348 EFI_TPL OldTpl;\r
349\r
350 //\r
351 // MTFTP driver opens UDP child, So, Controller is a UDP\r
352 // child handle. Locate the Nic handle first. Then get the\r
353 // MTFTP private data back.\r
354 //\r
355 NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid);\r
356\r
357 if (NicHandle == NULL) {\r
c4a62a12 358 return EFI_DEVICE_ERROR;\r
772db4bb 359 }\r
360\r
361 Status = gBS->OpenProtocol (\r
362 NicHandle,\r
363 &gEfiMtftp4ServiceBindingProtocolGuid,\r
364 (VOID **) &ServiceBinding,\r
365 This->DriverBindingHandle,\r
366 NicHandle,\r
367 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
368 );\r
369\r
370 if (EFI_ERROR (Status)) {\r
371 return EFI_DEVICE_ERROR;\r
372 }\r
373\r
374 MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding);\r
375\r
376 if (MtftpSb->InDestory) {\r
377 return EFI_SUCCESS;\r
378 }\r
379\r
e48e37fc 380 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 381\r
c4a62a12 382 if (NumberOfChildren == 0) {\r
772db4bb 383\r
c4a62a12 384 MtftpSb->InDestory = TRUE;\r
772db4bb 385\r
c4a62a12 386 gBS->UninstallProtocolInterface (\r
387 NicHandle,\r
388 &gEfiMtftp4ServiceBindingProtocolGuid,\r
389 ServiceBinding\r
390 );\r
772db4bb 391\r
c4a62a12 392 Mtftp4CleanService (MtftpSb);\r
772db4bb 393\r
766c7483 394 FreePool (MtftpSb);\r
c4a62a12 395 } else {\r
772db4bb 396\r
e48e37fc 397 while (!IsListEmpty (&MtftpSb->Children)) {\r
c4a62a12 398 Instance = NET_LIST_HEAD (&MtftpSb->Children, MTFTP4_PROTOCOL, Link);\r
399 Mtftp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);\r
400 }\r
772db4bb 401\r
c4a62a12 402 if (MtftpSb->ChildrenNum != 0) {\r
403 Status = EFI_DEVICE_ERROR;\r
404 }\r
405 }\r
772db4bb 406\r
e48e37fc 407 gBS->RestoreTPL (OldTpl);\r
772db4bb 408 return Status;\r
409}\r
410\r
411\r
412/**\r
413 Initialize a MTFTP protocol instance which is the child of MtftpSb.\r
414\r
415 @param MtftpSb The MTFTP service binding protocol.\r
416 @param Instance The MTFTP instance to initialize.\r
417\r
772db4bb 418**/\r
419VOID\r
420Mtftp4InitProtocol (\r
dab714aa 421 IN MTFTP4_SERVICE *MtftpSb,\r
422 OUT MTFTP4_PROTOCOL *Instance\r
772db4bb 423 )\r
424{\r
e48e37fc 425 ZeroMem (Instance, sizeof (MTFTP4_PROTOCOL));\r
772db4bb 426\r
427 Instance->Signature = MTFTP4_PROTOCOL_SIGNATURE;\r
e48e37fc 428 InitializeListHead (&Instance->Link);\r
687a2e5f 429 CopyMem (&Instance->Mtftp4, &gMtftp4ProtocolTemplate, sizeof (Instance->Mtftp4));\r
772db4bb 430 Instance->State = MTFTP4_STATE_UNCONFIGED;\r
dab714aa 431 Instance->InDestory = FALSE;\r
772db4bb 432 Instance->Service = MtftpSb;\r
433\r
e48e37fc 434 InitializeListHead (&Instance->Blocks);\r
772db4bb 435}\r
436\r
437\r
438/**\r
439 Create a MTFTP child for the service binding instance, then\r
440 install the MTFTP protocol to the ChildHandle.\r
441\r
442 @param This The MTFTP service binding instance.\r
443 @param ChildHandle The Child handle to install the MTFTP protocol.\r
444\r
445 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
446 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.\r
447 @retval EFI_SUCCESS The child is successfully create.\r
448\r
449**/\r
450EFI_STATUS\r
dab714aa 451EFIAPI\r
772db4bb 452Mtftp4ServiceBindingCreateChild (\r
453 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
dab714aa 454 IN EFI_HANDLE *ChildHandle\r
772db4bb 455 )\r
456{\r
457 MTFTP4_SERVICE *MtftpSb;\r
458 MTFTP4_PROTOCOL *Instance;\r
459 EFI_STATUS Status;\r
460 EFI_TPL OldTpl;\r
461 VOID *Udp4;\r
462\r
463 if ((This == NULL) || (ChildHandle == NULL)) {\r
464 return EFI_INVALID_PARAMETER;\r
465 }\r
466\r
e48e37fc 467 Instance = AllocatePool (sizeof (*Instance));\r
772db4bb 468\r
469 if (Instance == NULL) {\r
470 return EFI_OUT_OF_RESOURCES;\r
471 }\r
472\r
473 MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);\r
474\r
475 Mtftp4InitProtocol (MtftpSb, Instance);\r
476\r
b45b45b2 477 Instance->UnicastPort = UdpIoCreateIo (\r
772db4bb 478 MtftpSb->Controller,\r
479 MtftpSb->Image,\r
480 Mtftp4ConfigNullUdp,\r
b45b45b2 481 UDP_IO_UDP4_VERSION,\r
772db4bb 482 Instance\r
483 );\r
484\r
485 if (Instance->UnicastPort == NULL) {\r
766c7483 486 FreePool (Instance);\r
772db4bb 487 return EFI_OUT_OF_RESOURCES;\r
488 }\r
489\r
490 //\r
491 // Install the MTFTP protocol onto ChildHandle\r
492 //\r
493 Status = gBS->InstallMultipleProtocolInterfaces (\r
494 ChildHandle,\r
495 &gEfiMtftp4ProtocolGuid,\r
496 &Instance->Mtftp4,\r
497 NULL\r
498 );\r
499\r
500 if (EFI_ERROR (Status)) {\r
501 goto ON_ERROR;\r
502 }\r
503\r
504 Instance->Handle = *ChildHandle;\r
505\r
506 //\r
507 // Open the Udp4 protocol BY_CHILD.\r
508 //\r
509 Status = gBS->OpenProtocol (\r
510 MtftpSb->ConnectUdp->UdpHandle,\r
511 &gEfiUdp4ProtocolGuid,\r
512 (VOID **) &Udp4,\r
513 gMtftp4DriverBinding.DriverBindingHandle,\r
514 Instance->Handle,\r
515 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
516 );\r
517 if (EFI_ERROR (Status)) {\r
518 gBS->UninstallMultipleProtocolInterfaces (\r
519 Instance->Handle,\r
520 &gEfiMtftp4ProtocolGuid,\r
521 &Instance->Mtftp4,\r
522 NULL\r
523 );\r
524\r
525 goto ON_ERROR;\r
526 }\r
527\r
528 //\r
529 // Add it to the parent's child list.\r
530 //\r
e48e37fc 531 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 532\r
e48e37fc 533 InsertTailList (&MtftpSb->Children, &Instance->Link);\r
772db4bb 534 MtftpSb->ChildrenNum++;\r
535\r
e48e37fc 536 gBS->RestoreTPL (OldTpl);\r
772db4bb 537\r
538ON_ERROR:\r
539\r
540 if (EFI_ERROR (Status)) {\r
b45b45b2 541 UdpIoFreeIo (Instance->UnicastPort);\r
766c7483 542 FreePool (Instance);\r
772db4bb 543 }\r
544\r
545 return Status;\r
546}\r
547\r
548\r
549/**\r
550 Destory one of the service binding's child.\r
551\r
552 @param This The service binding instance\r
553 @param ChildHandle The child handle to destory\r
554\r
555 @retval EFI_INVALID_PARAMETER The parameter is invaid.\r
556 @retval EFI_UNSUPPORTED The child may have already been destoried.\r
557 @retval EFI_SUCCESS The child is destoried and removed from the\r
558 parent's child list.\r
559\r
560**/\r
561EFI_STATUS\r
dab714aa 562EFIAPI\r
772db4bb 563Mtftp4ServiceBindingDestroyChild (\r
564 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
565 IN EFI_HANDLE ChildHandle\r
566 )\r
567{\r
568 MTFTP4_SERVICE *MtftpSb;\r
569 MTFTP4_PROTOCOL *Instance;\r
570 EFI_MTFTP4_PROTOCOL *Mtftp4;\r
571 EFI_STATUS Status;\r
572 EFI_TPL OldTpl;\r
573\r
574 if ((This == NULL) || (ChildHandle == NULL)) {\r
575 return EFI_INVALID_PARAMETER;\r
576 }\r
577\r
578 //\r
579 // Retrieve the private context data structures\r
580 //\r
581 Status = gBS->OpenProtocol (\r
582 ChildHandle,\r
583 &gEfiMtftp4ProtocolGuid,\r
584 (VOID **) &Mtftp4,\r
585 gMtftp4DriverBinding.DriverBindingHandle,\r
586 ChildHandle,\r
587 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
588 );\r
589\r
590 if (EFI_ERROR (Status)) {\r
591 return EFI_UNSUPPORTED;\r
592 }\r
593\r
594 Instance = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4);\r
595 MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);\r
596\r
597 if (Instance->Service != MtftpSb) {\r
598 return EFI_INVALID_PARAMETER;\r
599 }\r
600\r
dab714aa 601 if (Instance->InDestory) {\r
772db4bb 602 return EFI_SUCCESS;\r
603 }\r
604\r
dab714aa 605 Instance->InDestory = TRUE;\r
772db4bb 606\r
607 //\r
608 // Close the Udp4 protocol.\r
609 //\r
610 gBS->CloseProtocol (\r
611 MtftpSb->ConnectUdp->UdpHandle,\r
612 &gEfiUdp4ProtocolGuid,\r
613 gMtftp4DriverBinding.DriverBindingHandle,\r
614 ChildHandle\r
615 );\r
616\r
617 //\r
618 // Uninstall the MTFTP4 protocol first to enable a top down destruction.\r
619 //\r
620 Status = gBS->UninstallProtocolInterface (\r
621 ChildHandle,\r
622 &gEfiMtftp4ProtocolGuid,\r
623 Mtftp4\r
624 );\r
625\r
626 if (EFI_ERROR (Status)) {\r
dab714aa 627 Instance->InDestory = FALSE;\r
772db4bb 628 return Status;\r
629 }\r
630\r
e48e37fc 631 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 632\r
633 Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);\r
b45b45b2 634 UdpIoFreeIo (Instance->UnicastPort);\r
772db4bb 635\r
e48e37fc 636 RemoveEntryList (&Instance->Link);\r
772db4bb 637 MtftpSb->ChildrenNum--;\r
638\r
e48e37fc 639 gBS->RestoreTPL (OldTpl);\r
772db4bb 640\r
766c7483 641 FreePool (Instance);\r
772db4bb 642 return EFI_SUCCESS;\r
643}\r