]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Mtftp6Dxe/Mtftp6Driver.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / Mtftp6Dxe / Mtftp6Driver.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Driver Binding functions and Service Binding functions\r
3 implementation for Mtftp6 Driver.\r
4\r
f75a7f56 5 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
a3bcde70 6\r
ecf98fbc 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a3bcde70
HT
8\r
9**/\r
10\r
11#include "Mtftp6Impl.h"\r
12\r
d1050b9d 13EFI_DRIVER_BINDING_PROTOCOL gMtftp6DriverBinding = {\r
a3bcde70
HT
14 Mtftp6DriverBindingSupported,\r
15 Mtftp6DriverBindingStart,\r
16 Mtftp6DriverBindingStop,\r
17 0xa,\r
18 NULL,\r
19 NULL\r
20};\r
21\r
22EFI_SERVICE_BINDING_PROTOCOL gMtftp6ServiceBindingTemplate = {\r
23 Mtftp6ServiceBindingCreateChild,\r
24 Mtftp6ServiceBindingDestroyChild\r
25};\r
26\r
a3bcde70 27/**\r
75dce340 28 Destroy the MTFTP6 service. The MTFTP6 service may be partly initialized,\r
a3bcde70
HT
29 or partly destroyed. If a resource is destroyed, it is marked as such in\r
30 case the destroy failed and is called again later.\r
31\r
32 @param[in] Service The MTFTP6 service to be destroyed.\r
33\r
34**/\r
35VOID\r
36Mtftp6DestroyService (\r
d1050b9d 37 IN MTFTP6_SERVICE *Service\r
a3bcde70
HT
38 )\r
39{\r
40 //\r
75dce340 41 // Make sure all children instances have been already destroyed.\r
a3bcde70
HT
42 //\r
43 ASSERT (Service->ChildrenNum == 0);\r
44\r
45 if (Service->DummyUdpIo != NULL) {\r
46 UdpIoFreeIo (Service->DummyUdpIo);\r
47 }\r
48\r
49 if (Service->Timer != NULL) {\r
50 gBS->CloseEvent (Service->Timer);\r
51 }\r
52\r
53 FreePool (Service);\r
54}\r
55\r
a3bcde70
HT
56/**\r
57 Create then initialize a MTFTP6 service binding instance.\r
58\r
59 @param[in] Controller The controller to install the MTFTP6 service\r
60 binding on.\r
61 @param[in] Image The driver binding image of the MTFTP6 driver.\r
62 @param[out] Service The variable to receive the created service\r
63 binding instance.\r
64\r
65 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to create the instance\r
66 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep connection with UDP.\r
67 @retval EFI_SUCCESS The service instance is created for the controller.\r
68\r
69**/\r
70EFI_STATUS\r
71Mtftp6CreateService (\r
d1050b9d
MK
72 IN EFI_HANDLE Controller,\r
73 IN EFI_HANDLE Image,\r
74 OUT MTFTP6_SERVICE **Service\r
a3bcde70
HT
75 )\r
76{\r
d1050b9d
MK
77 MTFTP6_SERVICE *Mtftp6Srv;\r
78 EFI_STATUS Status;\r
a3bcde70
HT
79\r
80 ASSERT (Service != NULL);\r
81\r
82 *Service = NULL;\r
83 Mtftp6Srv = AllocateZeroPool (sizeof (MTFTP6_SERVICE));\r
84\r
85 if (Mtftp6Srv == NULL) {\r
86 return EFI_OUT_OF_RESOURCES;\r
87 }\r
88\r
d1050b9d
MK
89 Mtftp6Srv->Signature = MTFTP6_SERVICE_SIGNATURE;\r
90 Mtftp6Srv->Controller = Controller;\r
91 Mtftp6Srv->Image = Image;\r
92 Mtftp6Srv->ChildrenNum = 0;\r
a3bcde70
HT
93\r
94 CopyMem (\r
95 &Mtftp6Srv->ServiceBinding,\r
96 &gMtftp6ServiceBindingTemplate,\r
97 sizeof (EFI_SERVICE_BINDING_PROTOCOL)\r
98 );\r
99\r
100 InitializeListHead (&Mtftp6Srv->Children);\r
101\r
102 //\r
103 // Create a internal timer for all instances.\r
104 //\r
105 Status = gBS->CreateEvent (\r
106 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
107 TPL_CALLBACK,\r
108 Mtftp6OnTimerTick,\r
109 Mtftp6Srv,\r
110 &Mtftp6Srv->Timer\r
111 );\r
112\r
113 if (EFI_ERROR (Status)) {\r
114 FreePool (Mtftp6Srv);\r
115 return Status;\r
116 }\r
117\r
118 //\r
119 // Create a dummy Udp6Io to build parent-child relationship between Udp6 driver\r
120 // and Mtftp6 driver.\r
121 //\r
122 Mtftp6Srv->DummyUdpIo = UdpIoCreateIo (\r
123 Controller,\r
124 Image,\r
125 Mtftp6ConfigDummyUdpIo,\r
126 UDP_IO_UDP6_VERSION,\r
127 NULL\r
128 );\r
129\r
130 if (Mtftp6Srv->DummyUdpIo == NULL) {\r
131 gBS->CloseEvent (Mtftp6Srv->Timer);\r
132 FreePool (Mtftp6Srv);\r
133 return EFI_DEVICE_ERROR;\r
134 }\r
135\r
136 *Service = Mtftp6Srv;\r
137 return EFI_SUCCESS;\r
138}\r
139\r
a3bcde70
HT
140/**\r
141 Destroy the MTFTP6 instance and recycle the resources.\r
142\r
143 @param[in] Instance The pointer to the MTFTP6 instance.\r
144\r
145**/\r
146VOID\r
147Mtftp6DestroyInstance (\r
d1050b9d 148 IN MTFTP6_INSTANCE *Instance\r
a3bcde70
HT
149 )\r
150{\r
d1050b9d
MK
151 LIST_ENTRY *Entry;\r
152 LIST_ENTRY *Next;\r
153 MTFTP6_BLOCK_RANGE *Block;\r
a3bcde70
HT
154\r
155 if (Instance->Config != NULL) {\r
156 FreePool (Instance->Config);\r
157 }\r
158\r
d1050b9d 159 if ((Instance->Token != NULL) && (Instance->Token->Event != NULL)) {\r
a3bcde70
HT
160 gBS->SignalEvent (Instance->Token->Event);\r
161 }\r
162\r
163 if (Instance->LastPacket != NULL) {\r
164 NetbufFree (Instance->LastPacket);\r
165 }\r
166\r
d1050b9d 167 if (Instance->UdpIo != NULL) {\r
a3bcde70
HT
168 UdpIoFreeIo (Instance->UdpIo);\r
169 }\r
170\r
171 if (Instance->McastUdpIo != NULL) {\r
172 UdpIoFreeIo (Instance->McastUdpIo);\r
173 }\r
174\r
175 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->BlkList) {\r
176 Block = NET_LIST_USER_STRUCT (Entry, MTFTP6_BLOCK_RANGE, Link);\r
177 RemoveEntryList (Entry);\r
178 FreePool (Block);\r
179 }\r
180\r
181 FreePool (Instance);\r
182}\r
183\r
a3bcde70
HT
184/**\r
185 Create the MTFTP6 instance and initialize it.\r
186\r
187 @param[in] Service The pointer to the MTFTP6 service.\r
188 @param[out] Instance The pointer to the MTFTP6 instance.\r
189\r
190 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
191 @retval EFI_SUCCESS The MTFTP6 instance is created.\r
192\r
193**/\r
194EFI_STATUS\r
195Mtftp6CreateInstance (\r
d1050b9d
MK
196 IN MTFTP6_SERVICE *Service,\r
197 OUT MTFTP6_INSTANCE **Instance\r
a3bcde70
HT
198 )\r
199{\r
d1050b9d 200 MTFTP6_INSTANCE *Mtftp6Ins;\r
a3bcde70
HT
201\r
202 *Instance = NULL;\r
203 Mtftp6Ins = AllocateZeroPool (sizeof (MTFTP6_INSTANCE));\r
204\r
205 if (Mtftp6Ins == NULL) {\r
206 return EFI_OUT_OF_RESOURCES;\r
207 }\r
208\r
209 Mtftp6Ins->Signature = MTFTP6_INSTANCE_SIGNATURE;\r
75dce340 210 Mtftp6Ins->InDestroy = FALSE;\r
a3bcde70
HT
211 Mtftp6Ins->Service = Service;\r
212\r
213 CopyMem (\r
214 &Mtftp6Ins->Mtftp6,\r
215 &gMtftp6ProtocolTemplate,\r
216 sizeof (EFI_MTFTP6_PROTOCOL)\r
217 );\r
218\r
219 InitializeListHead (&Mtftp6Ins->Link);\r
220 InitializeListHead (&Mtftp6Ins->BlkList);\r
221\r
222 *Instance = Mtftp6Ins;\r
223\r
224 return EFI_SUCCESS;\r
225}\r
226\r
216f7970 227/**\r
228 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
f75a7f56 229\r
216f7970 230 @param[in] Entry The entry to be removed.\r
231 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
232\r
233 @retval EFI_SUCCESS The entry has been removed successfully.\r
234 @retval Others Fail to remove the entry.\r
235\r
236**/\r
237EFI_STATUS\r
1f7eb561 238EFIAPI\r
216f7970 239Mtftp6DestroyChildEntryInHandleBuffer (\r
d1050b9d
MK
240 IN LIST_ENTRY *Entry,\r
241 IN VOID *Context\r
1f7eb561 242 )\r
216f7970 243{\r
244 MTFTP6_INSTANCE *Instance;\r
245 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
246 UINTN NumberOfChildren;\r
247 EFI_HANDLE *ChildHandleBuffer;\r
248\r
d1050b9d 249 if ((Entry == NULL) || (Context == NULL)) {\r
216f7970 250 return EFI_INVALID_PARAMETER;\r
251 }\r
252\r
d1050b9d
MK
253 Instance = NET_LIST_USER_STRUCT_S (Entry, MTFTP6_INSTANCE, Link, MTFTP6_INSTANCE_SIGNATURE);\r
254 ServiceBinding = ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ServiceBinding;\r
255 NumberOfChildren = ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->NumberOfChildren;\r
256 ChildHandleBuffer = ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ChildHandleBuffer;\r
216f7970 257\r
258 if (!NetIsInHandleBuffer (Instance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
259 return EFI_SUCCESS;\r
260 }\r
261\r
262 return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
263}\r
264\r
a3bcde70
HT
265/**\r
266 This is the declaration of an EFI image entry point. This entry point is\r
267 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including\r
268 both device drivers and bus drivers.\r
269\r
270 Entry point of the MTFTP6 driver to install various protocols.\r
271\r
272 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
273 @param[in] SystemTable The pointer to the EFI System Table.\r
274\r
275 @retval EFI_SUCCESS The operation completed successfully.\r
276 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
277\r
278**/\r
279EFI_STATUS\r
280EFIAPI\r
281Mtftp6DriverEntryPoint (\r
d1050b9d
MK
282 IN EFI_HANDLE ImageHandle,\r
283 IN EFI_SYSTEM_TABLE *SystemTable\r
a3bcde70
HT
284 )\r
285{\r
286 return EfiLibInstallDriverBindingComponentName2 (\r
287 ImageHandle,\r
288 SystemTable,\r
289 &gMtftp6DriverBinding,\r
290 ImageHandle,\r
291 &gMtftp6ComponentName,\r
292 &gMtftp6ComponentName2\r
293 );\r
294}\r
295\r
a3bcde70 296/**\r
76389e18 297 Test to see if this driver supports Controller. This service\r
a3bcde70
HT
298 is called by the EFI boot service ConnectController(). In\r
299 order to make drivers as small as possible, there are calling\r
300 restrictions for this service. ConnectController() must\r
301 follow these calling restrictions. If any other agent wishes to call\r
302 Supported(), it must also follow these calling restrictions.\r
303\r
304 @param[in] This Protocol instance pointer.\r
76389e18 305 @param[in] Controller Handle of device to test\r
a3bcde70
HT
306 @param[in] RemainingDevicePath Optional parameter use to pick a specific child.\r
307 device to start.\r
308\r
309 @retval EFI_SUCCESS This driver supports this device.\r
310 @retval Others This driver does not support this device.\r
311\r
312**/\r
313EFI_STATUS\r
314EFIAPI\r
315Mtftp6DriverBindingSupported (\r
d1050b9d
MK
316 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
317 IN EFI_HANDLE Controller,\r
318 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
a3bcde70
HT
319 )\r
320{\r
321 return gBS->OpenProtocol (\r
322 Controller,\r
323 &gEfiUdp6ServiceBindingProtocolGuid,\r
324 NULL,\r
325 This->DriverBindingHandle,\r
326 Controller,\r
327 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
328 );\r
329}\r
330\r
a3bcde70 331/**\r
76389e18 332 Start this driver on Controller. This service is called by the\r
a3bcde70
HT
333 EFI boot service ConnectController(). In order to make\r
334 drivers as small as possible, there are calling restrictions for\r
335 this service. ConnectController() must follow these\r
336 calling restrictions. If any other agent wishes to call Start() it\r
337 must also follow these calling restrictions.\r
338\r
339 @param[in] This Protocol instance pointer.\r
76389e18 340 @param[in] Controller Handle of device to bind driver to.\r
a3bcde70
HT
341 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
342 device to start.\r
343\r
76389e18 344 @retval EFI_SUCCESS This driver is added to Controller.\r
345 @retval EFI_ALREADY_STARTED This driver is already running on Controller.\r
a3bcde70
HT
346 @retval Others This driver does not support this device.\r
347\r
348**/\r
349EFI_STATUS\r
350EFIAPI\r
351Mtftp6DriverBindingStart (\r
352 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
353 IN EFI_HANDLE Controller,\r
354 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
355 )\r
356{\r
d1050b9d
MK
357 MTFTP6_SERVICE *Service;\r
358 EFI_STATUS Status;\r
a3bcde70
HT
359\r
360 //\r
361 // Directly return if driver is already running on this Nic handle.\r
362 //\r
363 Status = gBS->OpenProtocol (\r
364 Controller,\r
365 &gEfiMtftp6ServiceBindingProtocolGuid,\r
366 NULL,\r
367 This->DriverBindingHandle,\r
368 Controller,\r
369 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
370 );\r
371\r
372 if (!EFI_ERROR (Status)) {\r
373 return EFI_ALREADY_STARTED;\r
374 }\r
375\r
376 //\r
377 // Create Mtftp6 service for this Nic handle\r
378 //\r
379 Status = Mtftp6CreateService (\r
380 Controller,\r
381 This->DriverBindingHandle,\r
382 &Service\r
383 );\r
384\r
385 if (EFI_ERROR (Status)) {\r
386 return Status;\r
387 }\r
388\r
389 ASSERT (Service != NULL);\r
390\r
391 //\r
392 // Start the internal timer to track the packet retransmission.\r
393 //\r
394 Status = gBS->SetTimer (\r
395 Service->Timer,\r
396 TimerPeriodic,\r
397 TICKS_PER_SECOND\r
398 );\r
399\r
400 if (EFI_ERROR (Status)) {\r
401 goto ON_ERROR;\r
402 }\r
403\r
404 //\r
405 // Install the Mtftp6 service on the Nic handle.\r
406 //\r
407 Status = gBS->InstallMultipleProtocolInterfaces (\r
408 &Controller,\r
409 &gEfiMtftp6ServiceBindingProtocolGuid,\r
410 &Service->ServiceBinding,\r
411 NULL\r
412 );\r
413\r
414 if (EFI_ERROR (Status)) {\r
415 goto ON_ERROR;\r
416 }\r
417\r
418 return EFI_SUCCESS;\r
419\r
420ON_ERROR:\r
421\r
422 Mtftp6DestroyService (Service);\r
423 return Status;\r
424}\r
425\r
a3bcde70 426/**\r
76389e18 427 Stop this driver on Controller. This service is called by the\r
a3bcde70 428 EFI boot service DisconnectController(). In order to\r
76389e18 429 make drivers as small as possible, there are calling\r
a3bcde70
HT
430 restrictions for this service. DisconnectController()\r
431 must follow these calling restrictions. If any other agent wishes\r
76389e18 432 to call Stop(), it must also follow these calling restrictions.\r
a3bcde70
HT
433\r
434 @param[in] This Protocol instance pointer.\r
76389e18 435 @param[in] Controller Handle of device to stop driver on\r
a3bcde70
HT
436 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
437 children is zero, stop the entire bus driver.\r
438 @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
439\r
76389e18 440 @retval EFI_SUCCESS This driver is removed Controller.\r
a3bcde70
HT
441 @retval EFI_DEVICE_ERROR An unexpected error.\r
442 @retval Others This driver was not removed from this device.\r
443\r
444**/\r
445EFI_STATUS\r
446EFIAPI\r
447Mtftp6DriverBindingStop (\r
d1050b9d
MK
448 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
449 IN EFI_HANDLE Controller,\r
450 IN UINTN NumberOfChildren,\r
451 IN EFI_HANDLE *ChildHandleBuffer\r
a3bcde70
HT
452 )\r
453{\r
d1050b9d
MK
454 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
455 MTFTP6_SERVICE *Service;\r
456 EFI_HANDLE NicHandle;\r
457 EFI_STATUS Status;\r
458 LIST_ENTRY *List;\r
459 MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
f75a7f56 460\r
a3bcde70
HT
461 //\r
462 // Locate the Nic handle to retrieve the Mtftp6 private data.\r
463 //\r
464 NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp6ProtocolGuid);\r
465\r
466 if (NicHandle == NULL) {\r
216f7970 467 return EFI_SUCCESS;\r
a3bcde70
HT
468 }\r
469\r
470 Status = gBS->OpenProtocol (\r
471 NicHandle,\r
472 &gEfiMtftp6ServiceBindingProtocolGuid,\r
d1050b9d 473 (VOID **)&ServiceBinding,\r
a3bcde70
HT
474 This->DriverBindingHandle,\r
475 NicHandle,\r
476 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
477 );\r
478\r
479 if (EFI_ERROR (Status)) {\r
480 return EFI_DEVICE_ERROR;\r
481 }\r
482\r
483 Service = MTFTP6_SERVICE_FROM_THIS (ServiceBinding);\r
484\r
216f7970 485 if (!IsListEmpty (&Service->Children)) {\r
486 //\r
487 // Destroy the Mtftp6 child instance in ChildHandleBuffer.\r
488 //\r
d1050b9d 489 List = &Service->Children;\r
216f7970 490 Context.ServiceBinding = ServiceBinding;\r
491 Context.NumberOfChildren = NumberOfChildren;\r
492 Context.ChildHandleBuffer = ChildHandleBuffer;\r
d1050b9d
MK
493 Status = NetDestroyLinkList (\r
494 List,\r
495 Mtftp6DestroyChildEntryInHandleBuffer,\r
496 &Context,\r
497 NULL\r
498 );\r
a3bcde70
HT
499 }\r
500\r
d1050b9d 501 if ((NumberOfChildren == 0) && IsListEmpty (&Service->Children)) {\r
a3bcde70 502 //\r
75dce340 503 // Destroy the Mtftp6 service if there is no Mtftp6 child instance left.\r
a3bcde70 504 //\r
a3bcde70
HT
505 gBS->UninstallProtocolInterface (\r
506 NicHandle,\r
507 &gEfiMtftp6ServiceBindingProtocolGuid,\r
508 ServiceBinding\r
509 );\r
510\r
511 Mtftp6DestroyService (Service);\r
216f7970 512 Status = EFI_SUCCESS;\r
a3bcde70
HT
513 }\r
514\r
a3bcde70
HT
515 return Status;\r
516}\r
517\r
a3bcde70
HT
518/**\r
519 Creates a child handle and installs a protocol.\r
520\r
521 The CreateChild() function installs a protocol on ChildHandle.\r
522 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
523 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
524\r
525 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
526 @param[in, out] ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
527 then a new handle is created. If it is a pointer to an existing\r
528 UEFI handle, then the protocol is added to the existing UEFI handle.\r
529\r
f6c8bbbe 530 @retval EFI_SUCCESS The protocol was added to ChildHandle.\r
a3bcde70
HT
531 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
532 @retval Others The child handle was not created.\r
533\r
534**/\r
535EFI_STATUS\r
536EFIAPI\r
537Mtftp6ServiceBindingCreateChild (\r
538 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
539 IN OUT EFI_HANDLE *ChildHandle\r
540 )\r
541{\r
d1050b9d
MK
542 MTFTP6_SERVICE *Service;\r
543 MTFTP6_INSTANCE *Instance;\r
544 EFI_STATUS Status;\r
545 EFI_TPL OldTpl;\r
546 VOID *Udp6;\r
a3bcde70 547\r
d1050b9d 548 if ((This == NULL) || (ChildHandle == NULL)) {\r
a3bcde70
HT
549 return EFI_INVALID_PARAMETER;\r
550 }\r
551\r
552 Service = MTFTP6_SERVICE_FROM_THIS (This);\r
553\r
554 Status = Mtftp6CreateInstance (Service, &Instance);\r
555\r
556 if (EFI_ERROR (Status)) {\r
557 return Status;\r
558 }\r
559\r
560 ASSERT (Instance != NULL);\r
561\r
562 //\r
563 // Install the Mtftp6 protocol on the new child handle.\r
564 //\r
565 Status = gBS->InstallMultipleProtocolInterfaces (\r
566 ChildHandle,\r
567 &gEfiMtftp6ProtocolGuid,\r
568 &Instance->Mtftp6,\r
569 NULL\r
570 );\r
571\r
572 if (EFI_ERROR (Status)) {\r
573 goto ON_ERROR;\r
574 }\r
575\r
576 Instance->Handle = *ChildHandle;\r
577\r
578 //\r
579 // Open the Udp6 protocol by child.\r
580 //\r
581 Status = gBS->OpenProtocol (\r
582 Service->DummyUdpIo->UdpHandle,\r
583 &gEfiUdp6ProtocolGuid,\r
d1050b9d 584 (VOID **)&Udp6,\r
a3bcde70
HT
585 gMtftp6DriverBinding.DriverBindingHandle,\r
586 Instance->Handle,\r
587 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
588 );\r
589\r
590 if (EFI_ERROR (Status)) {\r
591 gBS->UninstallMultipleProtocolInterfaces (\r
592 Instance->Handle,\r
593 &gEfiMtftp6ProtocolGuid,\r
594 &Instance->Mtftp6,\r
595 NULL\r
596 );\r
597\r
598 goto ON_ERROR;\r
599 }\r
600\r
601 //\r
602 // Add the new Mtftp6 instance into the children list of Mtftp6 service.\r
603 //\r
604 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
605\r
606 InsertTailList (&Service->Children, &Instance->Link);\r
607 Service->ChildrenNum++;\r
608\r
609 gBS->RestoreTPL (OldTpl);\r
610 return EFI_SUCCESS;\r
611\r
612ON_ERROR:\r
613\r
614 Mtftp6DestroyInstance (Instance);\r
615 return Status;\r
616}\r
617\r
a3bcde70
HT
618/**\r
619 Destroys a child handle with a protocol installed on it.\r
620\r
621 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
622 that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
623 last protocol on ChildHandle, then ChildHandle is destroyed.\r
624\r
625 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
626 @param[in] ChildHandle Handle of the child to destroy.\r
627\r
f6c8bbbe 628 @retval EFI_SUCCESS The protocol was removed from ChildHandle.\r
a3bcde70 629 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
15ee13fc 630 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
a3bcde70
HT
631 @retval Others The child handle was not destroyed\r
632\r
633**/\r
634EFI_STATUS\r
635EFIAPI\r
636Mtftp6ServiceBindingDestroyChild (\r
d1050b9d
MK
637 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
638 IN EFI_HANDLE ChildHandle\r
a3bcde70
HT
639 )\r
640{\r
d1050b9d
MK
641 MTFTP6_SERVICE *Service;\r
642 MTFTP6_INSTANCE *Instance;\r
643 EFI_MTFTP6_PROTOCOL *Mtftp6;\r
644 EFI_STATUS Status;\r
645 EFI_TPL OldTpl;\r
a3bcde70 646\r
d1050b9d 647 if ((This == NULL) || (ChildHandle == NULL)) {\r
a3bcde70
HT
648 return EFI_INVALID_PARAMETER;\r
649 }\r
650\r
651 //\r
652 // Locate the Nic handle to retrieve the Mtftp6 private data.\r
653 //\r
654 Status = gBS->OpenProtocol (\r
655 ChildHandle,\r
656 &gEfiMtftp6ProtocolGuid,\r
d1050b9d 657 (VOID **)&Mtftp6,\r
a3bcde70
HT
658 gMtftp6DriverBinding.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
667 Instance = MTFTP6_INSTANCE_FROM_THIS (Mtftp6);\r
668 Service = MTFTP6_SERVICE_FROM_THIS (This);\r
669\r
670 if (Instance->Service != Service) {\r
671 return EFI_INVALID_PARAMETER;\r
672 }\r
673\r
674 //\r
75dce340 675 // Check whether the instance already in Destroy state.\r
a3bcde70 676 //\r
75dce340 677 if (Instance->InDestroy) {\r
a3bcde70
HT
678 return EFI_SUCCESS;\r
679 }\r
680\r
681 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
682\r
75dce340 683 Instance->InDestroy = TRUE;\r
a3bcde70
HT
684\r
685 gBS->CloseProtocol (\r
686 Service->DummyUdpIo->UdpHandle,\r
687 &gEfiUdp6ProtocolGuid,\r
688 gMtftp6DriverBinding.DriverBindingHandle,\r
689 ChildHandle\r
690 );\r
691\r
216f7970 692 if (Instance->UdpIo != NULL) {\r
693 gBS->CloseProtocol (\r
d1050b9d
MK
694 Instance->UdpIo->UdpHandle,\r
695 &gEfiUdp6ProtocolGuid,\r
696 gMtftp6DriverBinding.DriverBindingHandle,\r
697 Instance->Handle\r
698 );\r
216f7970 699 }\r
700\r
701 if (Instance->McastUdpIo != NULL) {\r
702 gBS->CloseProtocol (\r
703 Instance->McastUdpIo->UdpHandle,\r
704 &gEfiUdp6ProtocolGuid,\r
705 gMtftp6DriverBinding.DriverBindingHandle,\r
706 Instance->Handle\r
707 );\r
708 }\r
709\r
a3bcde70
HT
710 //\r
711 // Uninstall the MTFTP6 protocol first to enable a top down destruction.\r
712 //\r
216f7970 713 gBS->RestoreTPL (OldTpl);\r
a3bcde70
HT
714 Status = gBS->UninstallProtocolInterface (\r
715 ChildHandle,\r
716 &gEfiMtftp6ProtocolGuid,\r
717 Mtftp6\r
718 );\r
216f7970 719 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
a3bcde70 720 if (EFI_ERROR (Status)) {\r
75dce340 721 Instance->InDestroy = FALSE;\r
a3bcde70
HT
722 gBS->RestoreTPL (OldTpl);\r
723 return Status;\r
724 }\r
725\r
726 //\r
727 // Remove the Mtftp6 instance from the children list of Mtftp6 service.\r
728 //\r
729 RemoveEntryList (&Instance->Link);\r
d1050b9d 730 Service->ChildrenNum--;\r
a3bcde70 731\r
a3bcde70
HT
732 gBS->RestoreTPL (OldTpl);\r
733\r
216f7970 734 Mtftp6DestroyInstance (Instance);\r
735\r
a3bcde70
HT
736 return EFI_SUCCESS;\r
737}\r