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