]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Mtftp4Dxe / Mtftp4Driver.c
CommitLineData
772db4bb 1/** @file\r
dab714aa 2 Implementation of Mtftp drivers.\r
e2851998 3\r
0e2a5749 4Copyright (c) 2006 - 2018, 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
772db4bb 162 MtftpSb->ChildrenNum = 0;\r
e48e37fc 163 InitializeListHead (&MtftpSb->Children);\r
772db4bb 164\r
0e2a5749
FS
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
772db4bb 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
0e2a5749
FS
182 if (EFI_ERROR (Status)) {\r
183 FreePool (MtftpSb);\r
184 return Status;\r
185 }\r
772db4bb 186\r
0e2a5749
FS
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
772db4bb 194 if (EFI_ERROR (Status)) {\r
0e2a5749 195 gBS->CloseEvent (MtftpSb->Timer);\r
766c7483 196 FreePool (MtftpSb);\r
772db4bb 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
e48e37fc 206 TPL_CALLBACK,\r
772db4bb 207 NULL,\r
208 NULL,\r
209 &MtftpSb->TimerToGetMap\r
210 );\r
211 if (EFI_ERROR (Status)) {\r
0e2a5749 212 gBS->CloseEvent (MtftpSb->TimerNotifyLevel);\r
772db4bb 213 gBS->CloseEvent (MtftpSb->Timer);\r
766c7483 214 FreePool (MtftpSb);\r
772db4bb 215 return Status;\r
216 }\r
217\r
b45b45b2 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
772db4bb 225\r
226 if (MtftpSb->ConnectUdp == NULL) {\r
227 gBS->CloseEvent (MtftpSb->TimerToGetMap);\r
0e2a5749 228 gBS->CloseEvent (MtftpSb->TimerNotifyLevel);\r
772db4bb 229 gBS->CloseEvent (MtftpSb->Timer);\r
766c7483 230 FreePool (MtftpSb);\r
772db4bb 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
772db4bb 244**/\r
245VOID\r
246Mtftp4CleanService (\r
247 IN MTFTP4_SERVICE *MtftpSb\r
248 )\r
249{\r
b45b45b2 250 UdpIoFreeIo (MtftpSb->ConnectUdp);\r
772db4bb 251 gBS->CloseEvent (MtftpSb->TimerToGetMap);\r
0e2a5749 252 gBS->CloseEvent (MtftpSb->TimerNotifyLevel);\r
772db4bb 253 gBS->CloseEvent (MtftpSb->Timer);\r
254}\r
255\r
256\r
257/**\r
e2851998 258 Start the MTFTP driver on this controller.\r
259\r
dab714aa 260 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported\r
772db4bb 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
dab714aa 274EFIAPI\r
772db4bb 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
e2851998 305 ASSERT (MtftpSb != NULL);\r
772db4bb 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
0e2a5749
FS
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
d1102dba 318\r
772db4bb 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
766c7483 337 FreePool (MtftpSb);\r
772db4bb 338\r
339 return Status;\r
340}\r
341\r
216f7970 342/**\r
343 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
d1102dba 344\r
216f7970 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
1f7eb561 353EFIAPI\r
216f7970 354Mtftp4DestroyChildEntryInHandleBuffer (\r
355 IN LIST_ENTRY *Entry,\r
356 IN VOID *Context\r
1f7eb561 357 )\r
216f7970 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
772db4bb 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
dab714aa 394EFIAPI\r
772db4bb 395Mtftp4DriverBindingStop (\r
dab714aa 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
772db4bb 400 )\r
401{\r
216f7970 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
772db4bb 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
216f7970 417 return EFI_SUCCESS;\r
772db4bb 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
216f7970 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
772db4bb 449 }\r
450\r
216f7970 451 if (NumberOfChildren == 0 && IsListEmpty (&MtftpSb->Children)) {\r
c4a62a12 452 gBS->UninstallProtocolInterface (\r
453 NicHandle,\r
454 &gEfiMtftp4ServiceBindingProtocolGuid,\r
455 ServiceBinding\r
456 );\r
772db4bb 457\r
c4a62a12 458 Mtftp4CleanService (MtftpSb);\r
216f7970 459 if (gMtftp4ControllerNameTable != NULL) {\r
460 FreeUnicodeStringTable (gMtftp4ControllerNameTable);\r
461 gMtftp4ControllerNameTable = NULL;\r
c4a62a12 462 }\r
216f7970 463 FreePool (MtftpSb);\r
772db4bb 464\r
216f7970 465 Status = EFI_SUCCESS;\r
c4a62a12 466 }\r
772db4bb 467\r
772db4bb 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
772db4bb 478**/\r
479VOID\r
480Mtftp4InitProtocol (\r
dab714aa 481 IN MTFTP4_SERVICE *MtftpSb,\r
482 OUT MTFTP4_PROTOCOL *Instance\r
772db4bb 483 )\r
484{\r
e48e37fc 485 ZeroMem (Instance, sizeof (MTFTP4_PROTOCOL));\r
772db4bb 486\r
487 Instance->Signature = MTFTP4_PROTOCOL_SIGNATURE;\r
e48e37fc 488 InitializeListHead (&Instance->Link);\r
687a2e5f 489 CopyMem (&Instance->Mtftp4, &gMtftp4ProtocolTemplate, sizeof (Instance->Mtftp4));\r
772db4bb 490 Instance->State = MTFTP4_STATE_UNCONFIGED;\r
772db4bb 491 Instance->Service = MtftpSb;\r
492\r
e48e37fc 493 InitializeListHead (&Instance->Blocks);\r
772db4bb 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
dab714aa 510EFIAPI\r
772db4bb 511Mtftp4ServiceBindingCreateChild (\r
512 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
dab714aa 513 IN EFI_HANDLE *ChildHandle\r
772db4bb 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
e48e37fc 526 Instance = AllocatePool (sizeof (*Instance));\r
772db4bb 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
b45b45b2 536 Instance->UnicastPort = UdpIoCreateIo (\r
772db4bb 537 MtftpSb->Controller,\r
538 MtftpSb->Image,\r
539 Mtftp4ConfigNullUdp,\r
b45b45b2 540 UDP_IO_UDP4_VERSION,\r
772db4bb 541 Instance\r
542 );\r
543\r
544 if (Instance->UnicastPort == NULL) {\r
766c7483 545 FreePool (Instance);\r
772db4bb 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
216f7970 560 UdpIoFreeIo (Instance->UnicastPort);\r
561 FreePool (Instance);\r
562 return Status;\r
772db4bb 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
216f7970 579 goto ON_ERROR;\r
580 }\r
772db4bb 581\r
216f7970 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
772db4bb 603 goto ON_ERROR;\r
604 }\r
605\r
606 //\r
607 // Add it to the parent's child list.\r
608 //\r
e48e37fc 609 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 610\r
e48e37fc 611 InsertTailList (&MtftpSb->Children, &Instance->Link);\r
772db4bb 612 MtftpSb->ChildrenNum++;\r
613\r
e48e37fc 614 gBS->RestoreTPL (OldTpl);\r
772db4bb 615\r
216f7970 616 return EFI_SUCCESS;\r
772db4bb 617\r
216f7970 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
772db4bb 626 }\r
627\r
216f7970 628 UdpIoFreeIo (Instance->UnicastPort);\r
629 FreePool (Instance);\r
630\r
772db4bb 631 return Status;\r
632}\r
633\r
634\r
635/**\r
75dce340 636 Destroy one of the service binding's child.\r
772db4bb 637\r
638 @param This The service binding instance\r
75dce340 639 @param ChildHandle The child handle to destroy\r
772db4bb 640\r
641 @retval EFI_INVALID_PARAMETER The parameter is invaid.\r
75dce340 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
772db4bb 644 parent's child list.\r
645\r
646**/\r
647EFI_STATUS\r
dab714aa 648EFIAPI\r
772db4bb 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
75dce340 687 if (Instance->InDestroy) {\r
772db4bb 688 return EFI_SUCCESS;\r
689 }\r
690\r
75dce340 691 Instance->InDestroy = TRUE;\r
772db4bb 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
216f7970 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
d1102dba 716 );\r
216f7970 717 }\r
718\r
772db4bb 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
75dce340 729 Instance->InDestroy = FALSE;\r
772db4bb 730 return Status;\r
731 }\r
732\r
e48e37fc 733 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 734\r
735 Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);\r
b45b45b2 736 UdpIoFreeIo (Instance->UnicastPort);\r
772db4bb 737\r
e48e37fc 738 RemoveEntryList (&Instance->Link);\r
772db4bb 739 MtftpSb->ChildrenNum--;\r
740\r
e48e37fc 741 gBS->RestoreTPL (OldTpl);\r
772db4bb 742\r
766c7483 743 FreePool (Instance);\r
772db4bb 744 return EFI_SUCCESS;\r
745}\r