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