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