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