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