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