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