]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.c
Add 'file not found' debug message to MTFTP.
[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
1f7eb561 331EFIAPI\r
216f7970 332Mtftp4DestroyChildEntryInHandleBuffer (\r
333 IN LIST_ENTRY *Entry,\r
334 IN VOID *Context\r
1f7eb561 335 )\r
216f7970 336{\r
337 MTFTP4_PROTOCOL *Instance;\r
338 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
339 UINTN NumberOfChildren;\r
340 EFI_HANDLE *ChildHandleBuffer;\r
341\r
342 if (Entry == NULL || Context == NULL) {\r
343 return EFI_INVALID_PARAMETER;\r
344 }\r
345\r
346 Instance = NET_LIST_USER_STRUCT_S (Entry, MTFTP4_PROTOCOL, Link, MTFTP4_PROTOCOL_SIGNATURE);\r
347 ServiceBinding = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
348 NumberOfChildren = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
349 ChildHandleBuffer = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
350\r
351 if (!NetIsInHandleBuffer (Instance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
352 return EFI_SUCCESS;\r
353 }\r
354\r
355 return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
356}\r
772db4bb 357\r
358/**\r
359 Stop the MTFTP driver on controller. The controller is a UDP\r
360 child handle.\r
361\r
362 @param This The MTFTP driver binding protocol\r
363 @param Controller The controller to stop\r
364 @param NumberOfChildren The number of children\r
365 @param ChildHandleBuffer The array of the child handle.\r
366\r
367 @retval EFI_SUCCESS The driver is stopped on the controller.\r
368 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.\r
369\r
370**/\r
371EFI_STATUS\r
dab714aa 372EFIAPI\r
772db4bb 373Mtftp4DriverBindingStop (\r
dab714aa 374 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
375 IN EFI_HANDLE Controller,\r
376 IN UINTN NumberOfChildren,\r
377 IN EFI_HANDLE *ChildHandleBuffer\r
772db4bb 378 )\r
379{\r
216f7970 380 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
381 MTFTP4_SERVICE *MtftpSb;\r
382 EFI_HANDLE NicHandle;\r
383 EFI_STATUS Status;\r
384 LIST_ENTRY *List;\r
385 MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
772db4bb 386\r
387 //\r
388 // MTFTP driver opens UDP child, So, Controller is a UDP\r
389 // child handle. Locate the Nic handle first. Then get the\r
390 // MTFTP private data back.\r
391 //\r
392 NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid);\r
393\r
394 if (NicHandle == NULL) {\r
216f7970 395 return EFI_SUCCESS;\r
772db4bb 396 }\r
397\r
398 Status = gBS->OpenProtocol (\r
399 NicHandle,\r
400 &gEfiMtftp4ServiceBindingProtocolGuid,\r
401 (VOID **) &ServiceBinding,\r
402 This->DriverBindingHandle,\r
403 NicHandle,\r
404 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
405 );\r
406\r
407 if (EFI_ERROR (Status)) {\r
408 return EFI_DEVICE_ERROR;\r
409 }\r
410\r
411 MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding);\r
412\r
216f7970 413 if (!IsListEmpty (&MtftpSb->Children)) {\r
414 //\r
415 // Destroy the Mtftp4 child instance in ChildHandleBuffer.\r
416 //\r
417 List = &MtftpSb->Children;\r
418 Context.ServiceBinding = ServiceBinding;\r
419 Context.NumberOfChildren = NumberOfChildren;\r
420 Context.ChildHandleBuffer = ChildHandleBuffer;\r
421 Status = NetDestroyLinkList (\r
422 List,\r
423 Mtftp4DestroyChildEntryInHandleBuffer,\r
424 &Context,\r
425 NULL\r
426 );\r
772db4bb 427 }\r
428\r
216f7970 429 if (NumberOfChildren == 0 && IsListEmpty (&MtftpSb->Children)) {\r
c4a62a12 430 gBS->UninstallProtocolInterface (\r
431 NicHandle,\r
432 &gEfiMtftp4ServiceBindingProtocolGuid,\r
433 ServiceBinding\r
434 );\r
772db4bb 435\r
c4a62a12 436 Mtftp4CleanService (MtftpSb);\r
216f7970 437 if (gMtftp4ControllerNameTable != NULL) {\r
438 FreeUnicodeStringTable (gMtftp4ControllerNameTable);\r
439 gMtftp4ControllerNameTable = NULL;\r
c4a62a12 440 }\r
216f7970 441 FreePool (MtftpSb);\r
772db4bb 442\r
216f7970 443 Status = EFI_SUCCESS;\r
c4a62a12 444 }\r
772db4bb 445\r
772db4bb 446 return Status;\r
447}\r
448\r
449\r
450/**\r
451 Initialize a MTFTP protocol instance which is the child of MtftpSb.\r
452\r
453 @param MtftpSb The MTFTP service binding protocol.\r
454 @param Instance The MTFTP instance to initialize.\r
455\r
772db4bb 456**/\r
457VOID\r
458Mtftp4InitProtocol (\r
dab714aa 459 IN MTFTP4_SERVICE *MtftpSb,\r
460 OUT MTFTP4_PROTOCOL *Instance\r
772db4bb 461 )\r
462{\r
e48e37fc 463 ZeroMem (Instance, sizeof (MTFTP4_PROTOCOL));\r
772db4bb 464\r
465 Instance->Signature = MTFTP4_PROTOCOL_SIGNATURE;\r
e48e37fc 466 InitializeListHead (&Instance->Link);\r
687a2e5f 467 CopyMem (&Instance->Mtftp4, &gMtftp4ProtocolTemplate, sizeof (Instance->Mtftp4));\r
772db4bb 468 Instance->State = MTFTP4_STATE_UNCONFIGED;\r
772db4bb 469 Instance->Service = MtftpSb;\r
470\r
e48e37fc 471 InitializeListHead (&Instance->Blocks);\r
772db4bb 472}\r
473\r
474\r
475/**\r
476 Create a MTFTP child for the service binding instance, then\r
477 install the MTFTP protocol to the ChildHandle.\r
478\r
479 @param This The MTFTP service binding instance.\r
480 @param ChildHandle The Child handle to install the MTFTP protocol.\r
481\r
482 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
483 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.\r
484 @retval EFI_SUCCESS The child is successfully create.\r
485\r
486**/\r
487EFI_STATUS\r
dab714aa 488EFIAPI\r
772db4bb 489Mtftp4ServiceBindingCreateChild (\r
490 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
dab714aa 491 IN EFI_HANDLE *ChildHandle\r
772db4bb 492 )\r
493{\r
494 MTFTP4_SERVICE *MtftpSb;\r
495 MTFTP4_PROTOCOL *Instance;\r
496 EFI_STATUS Status;\r
497 EFI_TPL OldTpl;\r
498 VOID *Udp4;\r
499\r
500 if ((This == NULL) || (ChildHandle == NULL)) {\r
501 return EFI_INVALID_PARAMETER;\r
502 }\r
503\r
e48e37fc 504 Instance = AllocatePool (sizeof (*Instance));\r
772db4bb 505\r
506 if (Instance == NULL) {\r
507 return EFI_OUT_OF_RESOURCES;\r
508 }\r
509\r
510 MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);\r
511\r
512 Mtftp4InitProtocol (MtftpSb, Instance);\r
513\r
b45b45b2 514 Instance->UnicastPort = UdpIoCreateIo (\r
772db4bb 515 MtftpSb->Controller,\r
516 MtftpSb->Image,\r
517 Mtftp4ConfigNullUdp,\r
b45b45b2 518 UDP_IO_UDP4_VERSION,\r
772db4bb 519 Instance\r
520 );\r
521\r
522 if (Instance->UnicastPort == NULL) {\r
766c7483 523 FreePool (Instance);\r
772db4bb 524 return EFI_OUT_OF_RESOURCES;\r
525 }\r
526\r
527 //\r
528 // Install the MTFTP protocol onto ChildHandle\r
529 //\r
530 Status = gBS->InstallMultipleProtocolInterfaces (\r
531 ChildHandle,\r
532 &gEfiMtftp4ProtocolGuid,\r
533 &Instance->Mtftp4,\r
534 NULL\r
535 );\r
536\r
537 if (EFI_ERROR (Status)) {\r
216f7970 538 UdpIoFreeIo (Instance->UnicastPort);\r
539 FreePool (Instance);\r
540 return Status;\r
772db4bb 541 }\r
542\r
543 Instance->Handle = *ChildHandle;\r
544\r
545 //\r
546 // Open the Udp4 protocol BY_CHILD.\r
547 //\r
548 Status = gBS->OpenProtocol (\r
549 MtftpSb->ConnectUdp->UdpHandle,\r
550 &gEfiUdp4ProtocolGuid,\r
551 (VOID **) &Udp4,\r
552 gMtftp4DriverBinding.DriverBindingHandle,\r
553 Instance->Handle,\r
554 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
555 );\r
556 if (EFI_ERROR (Status)) {\r
216f7970 557 goto ON_ERROR;\r
558 }\r
772db4bb 559\r
216f7970 560 //\r
561 // Open the Udp4 protocol by child.\r
562 //\r
563 Status = gBS->OpenProtocol (\r
564 Instance->UnicastPort->UdpHandle,\r
565 &gEfiUdp4ProtocolGuid,\r
566 (VOID **) &Udp4,\r
567 gMtftp4DriverBinding.DriverBindingHandle,\r
568 Instance->Handle,\r
569 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
570 );\r
571 if (EFI_ERROR (Status)) {\r
572 //\r
573 // Close the Udp4 protocol.\r
574 //\r
575 gBS->CloseProtocol (\r
576 MtftpSb->ConnectUdp->UdpHandle,\r
577 &gEfiUdp4ProtocolGuid,\r
578 gMtftp4DriverBinding.DriverBindingHandle,\r
579 ChildHandle\r
580 );\r
772db4bb 581 goto ON_ERROR;\r
582 }\r
583\r
584 //\r
585 // Add it to the parent's child list.\r
586 //\r
e48e37fc 587 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 588\r
e48e37fc 589 InsertTailList (&MtftpSb->Children, &Instance->Link);\r
772db4bb 590 MtftpSb->ChildrenNum++;\r
591\r
e48e37fc 592 gBS->RestoreTPL (OldTpl);\r
772db4bb 593\r
216f7970 594 return EFI_SUCCESS;\r
772db4bb 595\r
216f7970 596ON_ERROR:\r
597 if (Instance->Handle != NULL) {\r
598 gBS->UninstallMultipleProtocolInterfaces (\r
599 Instance->Handle,\r
600 &gEfiMtftp4ProtocolGuid,\r
601 &Instance->Mtftp4,\r
602 NULL\r
603 );\r
772db4bb 604 }\r
605\r
216f7970 606 UdpIoFreeIo (Instance->UnicastPort);\r
607 FreePool (Instance);\r
608\r
772db4bb 609 return Status;\r
610}\r
611\r
612\r
613/**\r
75dce340 614 Destroy one of the service binding's child.\r
772db4bb 615\r
616 @param This The service binding instance\r
75dce340 617 @param ChildHandle The child handle to destroy\r
772db4bb 618\r
619 @retval EFI_INVALID_PARAMETER The parameter is invaid.\r
75dce340 620 @retval EFI_UNSUPPORTED The child may have already been destroyed.\r
621 @retval EFI_SUCCESS The child is destroyed and removed from the\r
772db4bb 622 parent's child list.\r
623\r
624**/\r
625EFI_STATUS\r
dab714aa 626EFIAPI\r
772db4bb 627Mtftp4ServiceBindingDestroyChild (\r
628 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
629 IN EFI_HANDLE ChildHandle\r
630 )\r
631{\r
632 MTFTP4_SERVICE *MtftpSb;\r
633 MTFTP4_PROTOCOL *Instance;\r
634 EFI_MTFTP4_PROTOCOL *Mtftp4;\r
635 EFI_STATUS Status;\r
636 EFI_TPL OldTpl;\r
637\r
638 if ((This == NULL) || (ChildHandle == NULL)) {\r
639 return EFI_INVALID_PARAMETER;\r
640 }\r
641\r
642 //\r
643 // Retrieve the private context data structures\r
644 //\r
645 Status = gBS->OpenProtocol (\r
646 ChildHandle,\r
647 &gEfiMtftp4ProtocolGuid,\r
648 (VOID **) &Mtftp4,\r
649 gMtftp4DriverBinding.DriverBindingHandle,\r
650 ChildHandle,\r
651 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
652 );\r
653\r
654 if (EFI_ERROR (Status)) {\r
655 return EFI_UNSUPPORTED;\r
656 }\r
657\r
658 Instance = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4);\r
659 MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);\r
660\r
661 if (Instance->Service != MtftpSb) {\r
662 return EFI_INVALID_PARAMETER;\r
663 }\r
664\r
75dce340 665 if (Instance->InDestroy) {\r
772db4bb 666 return EFI_SUCCESS;\r
667 }\r
668\r
75dce340 669 Instance->InDestroy = TRUE;\r
772db4bb 670\r
671 //\r
672 // Close the Udp4 protocol.\r
673 //\r
674 gBS->CloseProtocol (\r
675 MtftpSb->ConnectUdp->UdpHandle,\r
676 &gEfiUdp4ProtocolGuid,\r
677 gMtftp4DriverBinding.DriverBindingHandle,\r
678 ChildHandle\r
679 );\r
680\r
216f7970 681 gBS->CloseProtocol (\r
682 Instance->UnicastPort->UdpHandle,\r
683 &gEfiUdp4ProtocolGuid,\r
684 gMtftp4DriverBinding.DriverBindingHandle,\r
685 ChildHandle\r
686 );\r
687\r
688 if (Instance->McastUdpPort != NULL) {\r
689 gBS->CloseProtocol (\r
690 Instance->McastUdpPort->UdpHandle,\r
691 &gEfiUdp4ProtocolGuid,\r
692 gMtftp4DriverBinding.DriverBindingHandle,\r
693 ChildHandle\r
694 ); \r
695 }\r
696\r
772db4bb 697 //\r
698 // Uninstall the MTFTP4 protocol first to enable a top down destruction.\r
699 //\r
700 Status = gBS->UninstallProtocolInterface (\r
701 ChildHandle,\r
702 &gEfiMtftp4ProtocolGuid,\r
703 Mtftp4\r
704 );\r
705\r
706 if (EFI_ERROR (Status)) {\r
75dce340 707 Instance->InDestroy = FALSE;\r
772db4bb 708 return Status;\r
709 }\r
710\r
e48e37fc 711 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 712\r
713 Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);\r
b45b45b2 714 UdpIoFreeIo (Instance->UnicastPort);\r
772db4bb 715\r
e48e37fc 716 RemoveEntryList (&Instance->Link);\r
772db4bb 717 MtftpSb->ChildrenNum--;\r
718\r
e48e37fc 719 gBS->RestoreTPL (OldTpl);\r
772db4bb 720\r
766c7483 721 FreePool (Instance);\r
772db4bb 722 return EFI_SUCCESS;\r
723}\r